forked from eatvio/eatvio_app
feat(glossary): added pass key for glossary
This commit is contained in:
@@ -257,7 +257,7 @@ class AppRouter {
|
||||
return AboutPlanScreen(slug: data['slug'] as String, index: data['index'] as int?, navigateToComments: data['navigateToComments'] as bool);
|
||||
},
|
||||
),
|
||||
GoRoute(path: '/glossary-screen', name: 'glossaryScreen', builder: (context, state) => const GlossaryScreen()),
|
||||
GoRoute(path: '/glossary-screen', name: 'glossaryScreen', builder: (context, state) => GlossaryScreen(passKey: state.extra as String,)),
|
||||
GoRoute(
|
||||
path: '/about-recipes-screen',
|
||||
name: 'aboutRecipesScreen',
|
||||
|
||||
@@ -12,8 +12,8 @@ class PhoneVerifyErrorInterceptor extends Interceptor {
|
||||
final data = err.response?.data;
|
||||
|
||||
if (data is Map<String, dynamic> && data['type'] == 'unverificated_phone') {
|
||||
final String phone = await sl<ProfileRepository>().getMyPhone();
|
||||
final String passKey = await sl<ProfileRepository>().getPassKey(phone);
|
||||
final String phone = await sl<ProfileRepository>().getMyPhone();
|
||||
final String passKey = await sl<ProfileRepository>().getPassKey(routeName: 'user_detailz.change-phone-verify', routeParams: {"phone": phone});
|
||||
await showErrorDialog(AppRouter.navigatorKey.currentContext!,
|
||||
title: 'Привяжите номер телефона', description: 'Для того, что бы выполнить это действие необходимо привязать номер телефона');
|
||||
AppRouter.navigatorKey.currentContext?.pushNamed('verifyScreen', extra: passKey);
|
||||
|
||||
@@ -45,6 +45,7 @@ import 'package:eatvio_app/features/blog_post_create/services/blog_post_service.
|
||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/new_messages_cubit/new_messages_cubit.dart';
|
||||
import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/consultant_finances/consultant_finances_cubit.dart';
|
||||
import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/user_purchases/user_purchases_cubit.dart';
|
||||
import 'package:eatvio_app/features/menu/presentation/bloc/menu_cubit/menu_cubit.dart';
|
||||
import 'package:eatvio_app/features/menu/presentation/blocked_user_cubit/blocked_users_cubit.dart';
|
||||
import 'package:eatvio_app/features/menu/presentation/bloc/notification_settings_cubit/notification_settings_cubit.dart';
|
||||
import 'package:eatvio_app/features/menu/presentation/repositories/blocked_users_repository.dart';
|
||||
@@ -183,6 +184,7 @@ Future<void> init() async {
|
||||
sl.registerFactory<NotificationSettingsCubit>(() => NotificationSettingsCubit(notificationSettingsRepository: sl()));
|
||||
sl.registerFactory<ConsultantRatingCubit>(() => ConsultantRatingCubit(sl()));
|
||||
sl.registerFactory<ViewsCubit>(() => ViewsCubit(viewsRepository: sl()));
|
||||
sl.registerFactory<MenuCubit>(() => MenuCubit(sl()));
|
||||
|
||||
// Repository
|
||||
sl.registerLazySingleton<ChatRepository>(() => ChatRepository(chatService: sl()));
|
||||
|
||||
@@ -3,8 +3,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
|
||||
class GlossaryScreen extends StatefulWidget {
|
||||
const GlossaryScreen({super.key});
|
||||
|
||||
const GlossaryScreen({super.key, required this.passKey});
|
||||
final String passKey;
|
||||
@override
|
||||
State<GlossaryScreen> createState() => _GlossaryScreenState();
|
||||
}
|
||||
@@ -18,15 +18,13 @@ class _GlossaryScreenState extends State<GlossaryScreen> {
|
||||
|
||||
_controller = WebViewController()
|
||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||
..loadRequest(Uri.parse('$baseUrl/product_nutritional_value'));
|
||||
..loadRequest(Uri.parse('$baseUrl/login_with_pass_key?id=${widget.passKey}'));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Глоссарий'),
|
||||
),
|
||||
appBar: AppBar(title: const Text('Глоссарий')),
|
||||
body: WebViewWidget(controller: _controller),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:eatvio_app/features/menu/presentation/bloc/menu_cubit/menu_state.dart';
|
||||
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class MenuCubit extends Cubit<MenuState> {
|
||||
final ProfileRepository profileRepository;
|
||||
MenuCubit(this.profileRepository) : super(MenuState());
|
||||
|
||||
Future<String?> makePassKey() async {
|
||||
try {
|
||||
final passKey = await profileRepository.getPassKey(routeName: 'product_nutritional_value.index', routeParams: {});
|
||||
return passKey;
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
class MenuState {}
|
||||
@@ -9,12 +9,14 @@ import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/features/consultant_rating/presentation/consultant_rating_screen.dart';
|
||||
import 'package:eatvio_app/features/finances_and_consultations_archive/presentation/consultant_finances_screen.dart';
|
||||
import 'package:eatvio_app/features/finances_and_consultations_archive/presentation/user_purchases_screen.dart';
|
||||
import 'package:eatvio_app/features/menu/presentation/bloc/menu_cubit/menu_cubit.dart';
|
||||
import 'package:eatvio_app/features/my_diets/presentation/my_diets_screen.dart';
|
||||
import 'package:eatvio_app/features/my_plans/presentation/my_plans_screen.dart';
|
||||
import 'package:eatvio_app/features/profile/models/profile_model.dart';
|
||||
import 'package:eatvio_app/features/recipe/presentation/pages/my_recipes_screen.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
@@ -26,66 +28,86 @@ class MenuScreen extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(centerTitle: false, title: const Text('Меню')),
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
_tile(title: 'Настройки профиля', leading: ImageConstant.icnProfileSettings, onTap: () => GoRouter.of(context).push('/settings-screen')),
|
||||
if (profileModel.roles.contains('consultant')) _divider(context),
|
||||
if (profileModel.roles.contains('consultant'))
|
||||
_tile(leading: ImageConstant.icnRecipes, title: 'Мои рецепты', onTap: () => GoRouter.of(context).push(MyRecipesScreen.path)),
|
||||
if (profileModel.roles.contains('consultant')) _divider(context),
|
||||
if (profileModel.roles.contains('consultant'))
|
||||
_tile(leading: 'assets/icons/diets.svg', title: 'Мои диеты', onTap: () => GoRouter.of(context).push(MyDietsScreen.path)),
|
||||
if (profileModel.roles.contains('consultant')) _divider(context),
|
||||
if (profileModel.roles.contains('consultant'))
|
||||
_tile(leading: ImageConstant.icnPlans, title: 'Мои планы', onTap: () => GoRouter.of(context).push(MyPlansScreen.path)),
|
||||
if (!hidePlans) ...[
|
||||
_divider(context),
|
||||
_tile(
|
||||
leading: 'assets/icons/finance.svg',
|
||||
title: 'Мои финансы',
|
||||
onTap: () {
|
||||
if (profileModel.roles.contains('consultant')) {
|
||||
GoRouter.of(context).push(ConsultantFinancesScreen.path);
|
||||
return;
|
||||
}
|
||||
GoRouter.of(context).push(UserPurchasesScreen.path);
|
||||
},
|
||||
return BlocProvider(
|
||||
create: (context) => sl<MenuCubit>(),
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(centerTitle: false, title: const Text('Меню')),
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
_tile(title: 'Настройки профиля', leading: ImageConstant.icnProfileSettings, onTap: () => GoRouter.of(context).push('/settings-screen')),
|
||||
if (profileModel.roles.contains('consultant')) _divider(context),
|
||||
if (profileModel.roles.contains('consultant'))
|
||||
_tile(leading: ImageConstant.icnRecipes, title: 'Мои рецепты', onTap: () => GoRouter.of(context).push(MyRecipesScreen.path)),
|
||||
if (profileModel.roles.contains('consultant')) _divider(context),
|
||||
if (profileModel.roles.contains('consultant'))
|
||||
_tile(leading: 'assets/icons/diets.svg', title: 'Мои диеты', onTap: () => GoRouter.of(context).push(MyDietsScreen.path)),
|
||||
if (profileModel.roles.contains('consultant')) _divider(context),
|
||||
if (profileModel.roles.contains('consultant'))
|
||||
_tile(leading: ImageConstant.icnPlans, title: 'Мои планы', onTap: () => GoRouter.of(context).push(MyPlansScreen.path)),
|
||||
if (!hidePlans) ...[
|
||||
_divider(context),
|
||||
_tile(
|
||||
leading: 'assets/icons/finance.svg',
|
||||
title: 'Мои финансы',
|
||||
onTap: () {
|
||||
if (profileModel.roles.contains('consultant')) {
|
||||
GoRouter.of(context).push(ConsultantFinancesScreen.path);
|
||||
return;
|
||||
}
|
||||
GoRouter.of(context).push(UserPurchasesScreen.path);
|
||||
},
|
||||
),
|
||||
],
|
||||
if (profileModel.roles.contains('consultant')) _divider(context),
|
||||
if (profileModel.roles.contains('consultant'))
|
||||
_tile(
|
||||
leading: 'assets/icons/finance.svg',
|
||||
title: 'Мой рейтинг',
|
||||
onTap: () {
|
||||
GoRouter.of(context).push(ConsultantRatingScreen.path);
|
||||
},
|
||||
),
|
||||
_divider(context),
|
||||
_tile(
|
||||
leading: ImageConstant.icnGlossary,
|
||||
title: 'Глоссарий',
|
||||
onTap: () async {
|
||||
final passKey = await context.read<MenuCubit>().makePassKey();
|
||||
if (passKey != null && context.mounted) {
|
||||
GoRouter.of(context).push('/glossary-screen', extra: passKey);
|
||||
}
|
||||
},
|
||||
),
|
||||
_divider(context),
|
||||
_tile(
|
||||
leading: 'assets/icons/notifications.svg',
|
||||
title: 'Уведомления',
|
||||
onTap: () => GoRouter.of(context).pushNamed('notificationsSettingsScreen'),
|
||||
),
|
||||
_divider(context),
|
||||
_tile(leading: ImageConstant.icnSupport, title: 'Поддержка', onTap: () => GoRouter.of(context).push('/support-screen')),
|
||||
_divider(context),
|
||||
_tile(leading: 'assets/icons/blocked_users.svg', title: 'Чёрный список', onTap: () => GoRouter.of(context).pushNamed('blockedUsersScreen')),
|
||||
// _divider(context),
|
||||
// _tile(
|
||||
// leading: ImageConstant.icnDevTools,
|
||||
// title: 'Для разработчиков',
|
||||
// onTap: () {
|
||||
// GoRouter.of(context).pushNamed(DevToolsScreen.name);
|
||||
// },
|
||||
// ),
|
||||
_divider(context),
|
||||
_tile(leading: ImageConstant.icnExit, title: 'Выход', onTap: _onTapLogout(context)),
|
||||
const SizedBox(height: 10),
|
||||
const AppInfo(),
|
||||
],
|
||||
),
|
||||
],
|
||||
if (profileModel.roles.contains('consultant')) _divider(context),
|
||||
if (profileModel.roles.contains('consultant'))
|
||||
_tile(
|
||||
leading: 'assets/icons/finance.svg',
|
||||
title: 'Мой рейтинг',
|
||||
onTap: () {
|
||||
GoRouter.of(context).push(ConsultantRatingScreen.path);
|
||||
},
|
||||
),
|
||||
_divider(context),
|
||||
_tile(leading: ImageConstant.icnGlossary, title: 'Глоссарий', onTap: () => GoRouter.of(context).push('/glossary-screen')),
|
||||
_divider(context),
|
||||
_tile(leading: 'assets/icons/notifications.svg', title: 'Уведомления', onTap: () => GoRouter.of(context).pushNamed('notificationsSettingsScreen')),
|
||||
_divider(context),
|
||||
_tile(leading: ImageConstant.icnSupport, title: 'Поддержка', onTap: () => GoRouter.of(context).push('/support-screen')),
|
||||
_divider(context),
|
||||
_tile(leading: 'assets/icons/blocked_users.svg', title: 'Чёрный список', onTap: () => GoRouter.of(context).pushNamed('blockedUsersScreen')),
|
||||
// _divider(context),
|
||||
// _tile(
|
||||
// leading: ImageConstant.icnDevTools,
|
||||
// title: 'Для разработчиков',
|
||||
// onTap: () {
|
||||
// GoRouter.of(context).pushNamed(DevToolsScreen.name);
|
||||
// },
|
||||
// ),
|
||||
_divider(context),
|
||||
_tile(leading: ImageConstant.icnExit, title: 'Выход', onTap: _onTapLogout(context)),
|
||||
const SizedBox(height: 10),
|
||||
const AppInfo(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
15
lib/features/profile/models/pass_key_params.dart
Normal file
15
lib/features/profile/models/pass_key_params.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'pass_key_params.freezed.dart';
|
||||
part 'pass_key_params.g.dart';
|
||||
|
||||
@freezed
|
||||
abstract class PassKeyParams with _$PassKeyParams {
|
||||
|
||||
factory PassKeyParams({
|
||||
@JsonKey(name: 'route_name') required String routeName,
|
||||
@JsonKey(name: 'route_params') Map<String, dynamic>? routeParams,
|
||||
}) = _PassKeyParams;
|
||||
|
||||
factory PassKeyParams.fromJson(Map<String, dynamic> json) => _$PassKeyParamsFromJson(json);
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import 'dart:io';
|
||||
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
|
||||
import 'package:eatvio_app/features/profile/models/chosen_diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/profile/models/circumference_model.dart';
|
||||
import 'package:eatvio_app/features/profile/models/pass_key_params.dart';
|
||||
import 'package:eatvio_app/features/profile/models/profile_model.dart';
|
||||
import 'package:eatvio_app/features/profile/models/sub_model.dart';
|
||||
import 'package:eatvio_app/features/profile/models/weight_model.dart';
|
||||
@@ -154,10 +155,10 @@ class ProfileRepository {
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> getPassKey(String phone) async {
|
||||
return (jsonDecode(
|
||||
(await profileService.getPassKey(json: '{"route_name": "user_detailz.change-phone-verify", "route_params": {"phone": "$phone"}}')),
|
||||
))['key_is']!;
|
||||
Future<String> getPassKey({required String routeName, Map<String, dynamic>? routeParams}) async {
|
||||
return (await profileService.getPassKey(
|
||||
json: PassKeyParams(routeName: routeName, routeParams: routeParams),
|
||||
)).data['key_is']!;
|
||||
}
|
||||
|
||||
Future<String> getMyPhone() async {
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
|
||||
import 'package:eatvio_app/features/profile/models/chosen_diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/profile/models/circumference_model.dart';
|
||||
import 'package:eatvio_app/features/profile/models/pass_key_params.dart';
|
||||
import 'package:eatvio_app/features/profile/models/profile_model.dart';
|
||||
import 'package:eatvio_app/features/profile/models/sub_model.dart';
|
||||
import 'package:eatvio_app/features/profile/models/weight_model.dart';
|
||||
@@ -75,7 +76,7 @@ abstract class ProfileService {
|
||||
Future<ChosenDietsPaginationModel> getChosenDiets();
|
||||
|
||||
@POST('/api/profile/make_pass_key')
|
||||
Future<String> getPassKey({@Body() required String json});
|
||||
Future<HttpResponse> getPassKey({@Body() required PassKeyParams json});
|
||||
|
||||
@GET('/api/profile/my_phone')
|
||||
Future<String> getMyPhone();
|
||||
|
||||
@@ -28,9 +28,10 @@ class S {
|
||||
static const AppLocalizationDelegate delegate = AppLocalizationDelegate();
|
||||
|
||||
static Future<S> load(Locale locale) {
|
||||
final name = (locale.countryCode?.isEmpty ?? false)
|
||||
? locale.languageCode
|
||||
: locale.toString();
|
||||
final name =
|
||||
(locale.countryCode?.isEmpty ?? false)
|
||||
? locale.languageCode
|
||||
: locale.toString();
|
||||
final localeName = Intl.canonicalizedLocale(name);
|
||||
return initializeMessages(localeName).then((_) {
|
||||
Intl.defaultLocale = localeName;
|
||||
|
||||
Reference in New Issue
Block a user