diff --git a/lib/core/di/cubit_registrations.dart b/lib/core/di/cubit_registrations.dart index 2f4e764d..ca3ece97 100644 --- a/lib/core/di/cubit_registrations.dart +++ b/lib/core/di/cubit_registrations.dart @@ -30,6 +30,7 @@ import 'package:eatvio_app/features/feed/presentation/bloc/recipes_cubit/recipes import 'package:eatvio_app/features/finances_and_consultations_archive/cubit/archive/consultations_archive_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/my_diets/presentation/cubit/my_diets_cubit.dart'; @@ -141,5 +142,6 @@ class CubitRegistrations { sl.registerFactory(() => ConsultantRatingCubit(feedRepository: sl(), repository: sl(), profileRepository: sl())); sl.registerFactory(() => ViewsCubit(viewsRepository: sl())); sl.registerFactory(() => UserDetailsCubit(profileRepository: sl())); + sl.registerFactory(() => MenuCubit(sl())); } } diff --git a/lib/core/interceptors/phone_verify_error_interceptor.dart b/lib/core/interceptors/phone_verify_error_interceptor.dart index ab6188bf..4073cb85 100644 --- a/lib/core/interceptors/phone_verify_error_interceptor.dart +++ b/lib/core/interceptors/phone_verify_error_interceptor.dart @@ -12,8 +12,8 @@ class PhoneVerifyErrorInterceptor extends Interceptor { final data = err.response?.data; if (data is Map && data['type'] == 'unverificated_phone') { - final String phone = await sl().getMyPhone(); - final String passKey = await sl().getPassKey(phone); + final String phone = await sl().getMyPhone(); + final String passKey = await sl().getPassKey(routeName: 'user_detailz.change-phone-verify', routeParams: {"phone": phone}); await showErrorDialog(AppRouter.navigatorKey.currentContext!, title: 'Привяжите номер телефона', description: 'Для того, что бы выполнить это действие необходимо привязать номер телефона'); AppRouter.navigatorKey.currentContext?.pushNamed('verifyScreen', extra: passKey); diff --git a/lib/core/routing/other_routes.dart b/lib/core/routing/other_routes.dart index 7ae20a0f..7b5017df 100644 --- a/lib/core/routing/other_routes.dart +++ b/lib/core/routing/other_routes.dart @@ -180,7 +180,7 @@ class OtherRoutes { ), // Other routes - GoRoute(path: RouteConstants.glossaryScreen, name: 'glossaryScreen', builder: (context, state) => const GlossaryScreen()), + GoRoute(path: RouteConstants.glossaryScreen, name: 'glossaryScreen', builder: (context, state) => GlossaryScreen(passKey: state.extra as String)), GoRoute(path: RouteConstants.blockedUsersScreen, name: 'blockedUsersScreen', builder: (context, state) => const BlockedUsersScreen()), GoRoute( path: RouteConstants.notificationsSettingsScreen, diff --git a/lib/features/glossary/presentation/pages/glossary_screen.dart b/lib/features/glossary/presentation/pages/glossary_screen.dart index 22050f00..a1315953 100644 --- a/lib/features/glossary/presentation/pages/glossary_screen.dart +++ b/lib/features/glossary/presentation/pages/glossary_screen.dart @@ -4,8 +4,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 createState() => _GlossaryScreenState(); } @@ -19,15 +19,13 @@ class _GlossaryScreenState extends State { _controller = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) - ..loadRequest(Uri.parse('${sl().baseUrl}/product_nutritional_value')); + ..loadRequest(Uri.parse('${sl().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), ); } diff --git a/lib/features/menu/presentation/bloc/menu_cubit/menu_cubit.dart b/lib/features/menu/presentation/bloc/menu_cubit/menu_cubit.dart new file mode 100644 index 00000000..bb60d139 --- /dev/null +++ b/lib/features/menu/presentation/bloc/menu_cubit/menu_cubit.dart @@ -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 { + final ProfileRepository profileRepository; + MenuCubit(this.profileRepository) : super(MenuState()); + + Future makePassKey() async { + try { + final passKey = await profileRepository.getPassKey(routeName: 'product_nutritional_value.index', routeParams: {}); + return passKey; + } catch (e) { + log(e.toString()); + } + return null; + } +} diff --git a/lib/features/menu/presentation/bloc/menu_cubit/menu_state.dart b/lib/features/menu/presentation/bloc/menu_cubit/menu_state.dart new file mode 100644 index 00000000..70f37bb8 --- /dev/null +++ b/lib/features/menu/presentation/bloc/menu_cubit/menu_state.dart @@ -0,0 +1 @@ +class MenuState {} \ No newline at end of file diff --git a/lib/features/menu/presentation/pages/menu_screen.dart b/lib/features/menu/presentation/pages/menu_screen.dart index 7d237245..293f5485 100644 --- a/lib/features/menu/presentation/pages/menu_screen.dart +++ b/lib/features/menu/presentation/pages/menu_screen.dart @@ -10,12 +10,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'; @@ -27,66 +29,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(), + 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/consultant_rating_icon.svg', + title: 'Мой рейтинг', + onTap: () { + GoRouter.of(context).push(ConsultantRatingScreen.path); + }, + ), + _divider(context), + _tile( + leading: ImageConstant.icnGlossary, + title: 'Глоссарий', + onTap: () async { + final passKey = await context.read().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/consultant_rating_icon.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(), - ], - ), + ), + ); + }, ), ); } diff --git a/lib/features/profile/models/pass_key_params.dart b/lib/features/profile/models/pass_key_params.dart new file mode 100644 index 00000000..972f0f9f --- /dev/null +++ b/lib/features/profile/models/pass_key_params.dart @@ -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? routeParams, + }) = _PassKeyParams; + + factory PassKeyParams.fromJson(Map json) => _$PassKeyParamsFromJson(json); +} \ No newline at end of file diff --git a/lib/features/profile/repositories/profile_repository.dart b/lib/features/profile/repositories/profile_repository.dart index 4867d85a..0f2e903c 100644 --- a/lib/features/profile/repositories/profile_repository.dart +++ b/lib/features/profile/repositories/profile_repository.dart @@ -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 getPassKey(String phone) async { - return (jsonDecode( - (await profileService.getPassKey(json: '{"route_name": "user_detailz.change-phone-verify", "route_params": {"phone": "$phone"}}')), - ))['key_is']!; + Future getPassKey({required String routeName, Map? routeParams}) async { + return (await profileService.getPassKey( + json: PassKeyParams(routeName: routeName, routeParams: routeParams), + )).data['key_is']!; } Future getMyPhone() async { diff --git a/lib/features/profile/services/profile_service.dart b/lib/features/profile/services/profile_service.dart index b313f27f..95117d36 100644 --- a/lib/features/profile/services/profile_service.dart +++ b/lib/features/profile/services/profile_service.dart @@ -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 getChosenDiets(); @POST('/api/profile/make_pass_key') - Future getPassKey({@Body() required String json}); + Future getPassKey({@Body() required PassKeyParams json}); @GET('/api/profile/my_phone') Future getMyPhone();