forked from eatvio/eatvio_app
230 lines
10 KiB
Dart
230 lines
10 KiB
Dart
import 'package:dio/dio.dart';
|
|
import 'package:eatvio_app/core/app_config.dart';
|
|
import 'package:eatvio_app/core/error_reporting/error_reporter.dart';
|
|
import 'package:eatvio_app/core/const.dart';
|
|
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
|
import 'package:eatvio_app/core/token_storage.dart';
|
|
import 'package:eatvio_app/core/utils/image_constant.dart';
|
|
import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
|
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
|
import 'package:eatvio_app/core/widgets/loader.dart';
|
|
import 'package:eatvio_app/core/locator_service.dart';
|
|
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
|
import 'package:eatvio_app/core/websockets/ws_manager.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/menu/presentation/bloc/menu_cubit/menu_state.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/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';
|
|
|
|
class MenuScreen extends StatelessWidget {
|
|
const MenuScreen({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return BlocProvider(
|
|
create: (context) => sl<MenuCubit>()..getMyProfile(),
|
|
child: Builder(
|
|
builder: (context) {
|
|
return BlocBuilder<MenuCubit, MenuState>(
|
|
builder: (BuildContext context, MenuState state) {
|
|
if (state is MenuStateLoaded) {
|
|
final profileModel = state.profileModel;
|
|
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<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 (state is MenuStateError) {
|
|
return Scaffold(
|
|
appBar: AppBar(centerTitle: false, title: const Text('Меню')),
|
|
body: DataErrorWidget(onReload: () async => context.read<MenuCubit>().getMyProfile()),
|
|
);
|
|
}
|
|
|
|
return Scaffold(
|
|
appBar: AppBar(centerTitle: false, title: const Text('Меню')),
|
|
body: const Loader(),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
ListTile _tile({required String title, required String leading, required Function() onTap}) {
|
|
return ListTile(
|
|
onTap: onTap,
|
|
leading: SvgPicture.asset(leading, height: 24, width: 24, colorFilter: ColorFilter.mode(appTheme.blueA400, BlendMode.srcIn)),
|
|
title: Text(title),
|
|
trailing: const Icon(Icons.arrow_forward_ios_rounded, size: 12, color: Colors.black38),
|
|
);
|
|
}
|
|
|
|
Container _divider(BuildContext context) {
|
|
return Container(
|
|
height: 0.4,
|
|
width: MediaQuery.of(context).size.width - 32,
|
|
decoration: BoxDecoration(color: Colors.black26, borderRadius: BorderRadius.circular(16)),
|
|
);
|
|
}
|
|
|
|
Future<Null> Function() _onTapLogout(BuildContext context) {
|
|
return () async {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => CupertinoAlertDialog(
|
|
title: const Text("Выход"),
|
|
actions: [
|
|
CupertinoDialogAction(
|
|
onPressed: () async {
|
|
try {
|
|
await sl<Dio>().post('${sl<AppConfig>().baseUrl}/api/profile/logout');
|
|
} catch (e, s) {
|
|
await sl<ErrorReporter>().report(e, s, origin: 'MenuScreen');
|
|
} finally {
|
|
await sl<WsManager>().clear();
|
|
await TokenStorage.removeTokenInStorage();
|
|
if (context.mounted) {
|
|
GoRouter.of(context).go('/auth-screen', extra: true);
|
|
}
|
|
}
|
|
},
|
|
isDestructiveAction: true,
|
|
child: const Text("Выйти"),
|
|
),
|
|
CupertinoDialogAction(
|
|
onPressed: () {
|
|
Navigator.of(context).pop();
|
|
},
|
|
child: const Text("Отмена"),
|
|
),
|
|
],
|
|
content: const Text("Вы уверены, что хотите выйти из аккаунта?"),
|
|
),
|
|
);
|
|
};
|
|
}
|
|
}
|
|
|
|
class AppInfo extends StatefulWidget {
|
|
const AppInfo({super.key});
|
|
|
|
@override
|
|
State<AppInfo> createState() => _AppInfoState();
|
|
}
|
|
|
|
class _AppInfoState extends State<AppInfo> {
|
|
String version = '';
|
|
String buildNumber = '';
|
|
@override
|
|
void didChangeDependencies() {
|
|
PackageInfo.fromPlatform().then((PackageInfo packageInfo) {
|
|
setState(() {
|
|
version = packageInfo.version;
|
|
buildNumber = packageInfo.buildNumber;
|
|
});
|
|
});
|
|
super.didChangeDependencies();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Align(
|
|
alignment: Alignment.centerLeft,
|
|
child: Padding(
|
|
padding: const EdgeInsetsGeometry.only(left: 16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text('Версия приложения: $version ($buildNumber)', style: TextStyles.textXSSemibold.copyWith(color: appTheme.gray)),
|
|
if (buildDate != '') Text('Дата сборки: ${formatBuildDate(buildDate)}', style: TextStyles.textXSSemibold.copyWith(color: appTheme.gray)),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|