import 'package:eatvio_app/core/app_router.dart'; import 'package:eatvio_app/core/theme/custom_text_style.dart'; import 'package:eatvio_app/core/widgets/bottom_sheet_handler_bar.dart'; import 'package:eatvio_app/core/widgets/bottom_sheet_with_blur.dart'; import 'package:eatvio_app/core/widgets/custom_outlined_button.dart'; import 'package:eatvio_app/core/widgets/data_error_widget.dart'; import 'package:eatvio_app/core/widgets/loader.dart'; import 'package:eatvio_app/core/widgets/show_error_dialog.dart'; import 'package:eatvio_app/features/consultant/become_consultant/models/consultation_request_model.dart'; import 'package:eatvio_app/features/settings/entities/settings_entity.dart'; import 'package:eatvio_app/features/settings/presentation/bloc/settings_cubit/settings_cubit.dart'; import 'package:eatvio_app/features/settings/presentation/bloc/settings_cubit/settings_state.dart'; import 'package:eatvio_app/core/locator_service.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; import 'package:eatvio_app/generated/l10n.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; class SettingsScreen extends StatefulWidget { const SettingsScreen({super.key}); @override State createState() => _SettingsScreenState(); } class _SettingsScreenState extends State { final SettingsCubit settingsCubit = sl()..init(); late bool updatesNotificationsSwitchState; late bool fillDiaryNotificationsSwitchState; late bool bedTimeSwitchState; late bool moodSwitchState; void _showConsultationWarning() { showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: const Text('Предупреждение'), content: const Text('Во время консультации этот параметр нельзя отключить'), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Понятно'), ), ], ); }, ); } @override Widget build(BuildContext context) { return BlocProvider( create: (BuildContext context) => settingsCubit, child: BlocConsumer( bloc: settingsCubit, listener: (BuildContext context, SettingsState state) { if (state is SettingsStateLoaded) { updatesNotificationsSwitchState = state.profileSettings.newUpdatesNotifications == 1 ? true : false; fillDiaryNotificationsSwitchState = state.profileSettings.diaryReminderNotifications == 1 ? true : false; bedTimeSwitchState = state.profileSettings.isBedtimeFillable; moodSwitchState = state.profileSettings.isMoodFillable; } }, builder: (BuildContext context, SettingsState state) { if (state is SettingsStateLoaded) { return Scaffold( appBar: AppBar(title: const Text('Настройки')), body: SafeArea( child: SingleChildScrollView( padding: const EdgeInsets.symmetric(vertical: 16), physics: const BouncingScrollPhysics(), child: Column( children: [ _additionalInfo(state), const SizedBox(height: 12), _notifications(state), const SizedBox(height: 12), _becomeConsultantButton(state), _deleteAccountButton(state, settingsCubit), ], ), ), ), ); } if (state is SettingsStateError) { return Scaffold( appBar: AppBar(title: const Text('Настройки')), body: DataErrorWidget(onReload: () => settingsCubit.init()), ); } return Scaffold( appBar: AppBar(title: const Text('Настройки')), body: const Loader(), ); }, ), ); } Column _additionalInfo(SettingsStateLoaded state) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Padding( padding: EdgeInsets.symmetric(horizontal: 16), child: Text( 'Дополнительаная информация', style: TextStyle(fontSize: 16, height: 1, color: Colors.grey, fontFamily: 'Mulish'), ), ), _tile( onTap: () => GoRouter.of(context).pushNamed( 'generalInfoScreen', extra: SettingsEntity(profileSettingsModel: state.profileSettings, profileDetailsModel: state.profileDetails, settingsCubit: settingsCubit), ), title: 'Общая информация', ), _divider(context), _tile( onTap: () => GoRouter.of(context).pushNamed( 'physicalFormScreen', extra: SettingsEntity(profileSettingsModel: state.profileSettings, profileDetailsModel: state.profileDetails, settingsCubit: settingsCubit), ), title: 'Физическая форма', ), _divider(context), _tile( onTap: () => GoRouter.of(context).pushNamed( 'pressureScreen', extra: SettingsEntity(profileSettingsModel: state.profileSettings, profileDetailsModel: state.profileDetails, settingsCubit: settingsCubit), ), title: 'Давление', ), _divider(context), _tile( onTap: () => GoRouter.of(context).pushNamed( 'otherInfoScreen', extra: SettingsEntity(profileSettingsModel: state.profileSettings, profileDetailsModel: state.profileDetails, settingsCubit: settingsCubit), ), title: 'Прочая информация', ), _divider(context), _tile( onTap: () => GoRouter.of(context).pushNamed( 'physicalActivityScreen', extra: SettingsEntity(profileSettingsModel: state.profileSettings, profileDetailsModel: state.profileDetails, settingsCubit: settingsCubit), ), title: 'Физическая нагрузка', ), _divider(context), _tile(onTap: () => GoRouter.of(context).pushNamed('forgetPasswordScreen', extra: true), title: 'Сменить пароль'), _divider(context), _tile( onTap: () => GoRouter.of(context).pushNamed( 'changeEmailScreen', extra: SettingsEntity(profileSettingsModel: state.profileSettings, profileDetailsModel: state.profileDetails, settingsCubit: settingsCubit), ), title: 'Сменить Email', ), ], ); } Column _notifications(SettingsStateLoaded state) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Padding( padding: EdgeInsets.symmetric(horizontal: 16), child: Text('При использовании дневника', style: TextStyle(fontSize: 16, height: 1, color: Colors.grey)), ), _tile( padding: const EdgeInsets.symmetric(horizontal: 16), onTap: () { if (state.hasActiveConsultation) { _showConsultationWarning(); return; } setState(() { moodSwitchState = !moodSwitchState; }); settingsCubit.updateProfileSettings(profileSettingsModel: state.profileSettings.copyWith(isMoodFillable: moodSwitchState)); }, title: 'Указывать "настроение" в заполнение дневника', trailing: CupertinoSwitch( value: state.hasActiveConsultation ? true : moodSwitchState, activeTrackColor: appTheme.blueA400, onChanged: (newValue) { if (state.hasActiveConsultation) { _showConsultationWarning(); return; } setState(() { moodSwitchState = newValue; }); settingsCubit.updateProfileSettings(profileSettingsModel: state.profileSettings.copyWith(isMoodFillable: moodSwitchState)); }, ), ), _divider(context), _tile( padding: const EdgeInsets.symmetric(horizontal: 16), onTap: () { if (state.hasActiveConsultation) { _showConsultationWarning(); return; } setState(() { bedTimeSwitchState = !bedTimeSwitchState; }); settingsCubit.updateProfileSettings(profileSettingsModel: state.profileSettings.copyWith(isBedtimeFillable: bedTimeSwitchState)); }, title: 'Указывать "отход ко сну" в заполнение дневника', trailing: CupertinoSwitch( value: state.hasActiveConsultation ? true : bedTimeSwitchState, activeTrackColor: appTheme.blueA400, onChanged: (newValue) { if (state.hasActiveConsultation) { _showConsultationWarning(); return; } setState(() { bedTimeSwitchState = newValue; }); settingsCubit.updateProfileSettings(profileSettingsModel: state.profileSettings.copyWith(isBedtimeFillable: bedTimeSwitchState)); }, ), ), ], ); } SingleChildRenderObjectWidget _becomeConsultantButton(SettingsStateLoaded state) { if (state.consultationRequestModel == null) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16) + const EdgeInsets.only(bottom: 8), child: InkWell( onTap: () => GoRouter.of(context).pushNamed('becomeConsultantScreen'), borderRadius: BorderRadius.circular(20), child: Ink( height: 52, width: MediaQuery.of(context).size.width - 16, decoration: BoxDecoration(borderRadius: BorderRadius.circular(20), color: appTheme.blueA400), child: const Center( child: Text('Стать консультантом', style: TextStyle(color: Colors.white, height: 1, fontSize: 18)), ), ), ), ); } else { if (state.consultationRequestModel!.educationModel.requestState == ModerationStatus.created) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16) + const EdgeInsets.only(bottom: 8), child: Ink( height: 52, width: MediaQuery.of(context).size.width - 16, decoration: BoxDecoration(borderRadius: BorderRadius.circular(20), color: const Color(0xFFEAEAEA)), child: const Center( child: Text('Данные на проверке', style: TextStyle(color: Colors.black, height: 1, fontSize: 18)), ), ), ); } else if (state.consultationRequestModel!.educationModel.requestState == ModerationStatus.canceled) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16) + const EdgeInsets.only(bottom: 8), child: InkWell( onTap: () => GoRouter.of(context).pushNamed('stepperBecomeConsultantScreen', extra: state.profile.slug), borderRadius: BorderRadius.circular(20), child: Ink( height: 52, width: MediaQuery.of(context).size.width - 16, decoration: BoxDecoration(borderRadius: BorderRadius.circular(20), color: const Color(0x33FFCC00)), child: const Center( child: Text('Заявка обработана', style: TextStyle(color: Colors.black, height: 1, fontSize: 18)), ), ), ), ); } } return const SizedBox.shrink(); } Padding _deleteAccountButton(SettingsStateLoaded state, SettingsCubit settingsCubit) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: InkWell( onTap: () async { showBottomSheetWithBlur( userRootNavigator: true, context: context, height: null, child: DeleteAccountBottomSheet(cubit: settingsCubit), ); }, borderRadius: BorderRadius.circular(20), child: Ink( height: 52, width: MediaQuery.of(context).size.width - 16, decoration: BoxDecoration(borderRadius: BorderRadius.circular(20), color: const Color(0xFFEAEAEA)), child: const Center( child: Text('Удалить аккаунт', style: TextStyle(color: Colors.black, height: 1, fontSize: 18)), ), ), ), ); } ListTile _tile({required String title, required Function() onTap, Widget? trailing, EdgeInsets? padding}) { return ListTile( contentPadding: padding, onTap: onTap, title: Text(title, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500, height: 1)), trailing: trailing ?? const Icon(Icons.arrow_forward_ios_rounded, size: 12, color: Colors.black38), ); } Center _divider(BuildContext context) { return Center( child: Container( height: 0.4, width: MediaQuery.of(context).size.width - 32, decoration: BoxDecoration(color: Colors.black26, borderRadius: BorderRadius.circular(16)), ), ); } } class DeleteAccountBottomSheet extends StatefulWidget { const DeleteAccountBottomSheet({super.key, required this.cubit}); final SettingsCubit cubit; @override State createState() => _DeleteAccountBottomSheet(); } class _DeleteAccountBottomSheet extends State { bool? isFailure; @override Widget build(BuildContext context) { final s = S.of(context); return Padding( padding: const EdgeInsets.symmetric(horizontal: 12.0), child: Column( mainAxisSize: MainAxisSize.min, children: [ const SizedBox(height: 8), const BottomSheetHandlerBar(), const SizedBox(height: 20), Text(s.accountDeleting, style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black)), const SizedBox(height: 16), Text( s.youShureYouWantToDeleteAccount, style: TextStyles.textSMedium.copyWith(color: appTheme.black), textAlign: TextAlign.center, ), const SizedBox(height: 8), Text( s.itCantBeRecovered, style: TextStyles.textSMedium.copyWith(color: appTheme.black), textAlign: TextAlign.center, ), const SizedBox(height: 8), CustomOutlinedButton( text: s.delete, height: 52, buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700), buttonStyle: ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.blueA400)), onPressed: () async { final result = await widget.cubit.deleteAccount(); if (result == true) { AppRouter.navigatorKey.currentContext?.go('/auth-screen'); return; } AppRouter.navigatorKey.currentContext?.pop(); if (!context.mounted) return; showErrorDialog(context, description: s.cannotDeleteAccount); }, ), const SizedBox(height: 40), ], ), ); } }