From de30b93fa6e321b6f39ba1faab034fb5a3ab09f6 Mon Sep 17 00:00:00 2001 From: mso7nueh Date: Wed, 2 Oct 2024 13:10:21 +0300 Subject: [PATCH] feat: settings (data save) + new fields --- lib/app_router.dart | 23 +-- .../settings/entities/settings_entity.dart | 15 ++ .../bloc/settings_cubit/settings_cubit.dart | 12 +- .../pages/change_password_screen.dart | 28 ++++ .../pages/general_info_screen.dart | 105 ++++++++++---- .../presentation/pages/other_info_screen.dart | 37 +++-- .../pages/physical_activity_screen.dart | 20 ++- .../pages/physical_form_screen.dart | 27 ++-- .../presentation/pages/pressure_screen.dart | 37 ++--- .../presentation/pages/settings_screen.dart | 136 +++++++++++++++--- lib/widgets/custom_drop_down.dart | 15 +- 11 files changed, 338 insertions(+), 117 deletions(-) create mode 100644 lib/features/settings/entities/settings_entity.dart create mode 100644 lib/features/settings/presentation/pages/change_password_screen.dart diff --git a/lib/app_router.dart b/lib/app_router.dart index 7d97c634..e54fe2da 100644 --- a/lib/app_router.dart +++ b/lib/app_router.dart @@ -17,12 +17,13 @@ import 'package:eatvio_app/features/menu/presentation/pages/menu_screen.dart'; import 'package:eatvio_app/features/notifications/presentation/pages/notifications_screen.dart'; import 'package:eatvio_app/features/plans/models/plan_pagination_model.dart'; import 'package:eatvio_app/features/plans/presentation/pages/about_plan_screen.dart'; -import 'package:eatvio_app/features/profile/models/profile_model.dart'; import 'package:eatvio_app/features/profile/presentation/pages/profile_screen.dart'; import 'package:eatvio_app/features/recipes/presentation/pages/about_recipes_screen.dart'; import 'package:eatvio_app/features/recipes/presentation/pages/recipe_create_screen.dart'; import 'package:eatvio_app/features/recipes/presentation/pages/recipe_edit_screen.dart'; import 'package:eatvio_app/features/registration/presentation/pages/registration_screen.dart'; +import 'package:eatvio_app/features/settings/entities/settings_entity.dart'; +import 'package:eatvio_app/features/settings/presentation/pages/change_password_screen.dart'; import 'package:eatvio_app/features/settings/presentation/pages/general_info_screen.dart'; import 'package:eatvio_app/features/settings/presentation/pages/other_info_screen.dart'; import 'package:eatvio_app/features/settings/presentation/pages/physical_activity_screen.dart'; @@ -172,39 +173,45 @@ class AppRouter { builder: (context, state) => SettingsScreen(), routes: [ GoRoute( - path: 'general-info-screen/:isPublicProfile', + path: 'general-info-screen', name: 'generalInfoScreen', builder: (context, state) => GeneralInfoScreen( - profileDetailsModel: state.extra as ProfileDetailsModel, - isPublicProfile: bool.parse(state.pathParameters['isPublicProfile']!), + settingsEntity: state.extra as SettingsEntity, ), ), GoRoute( path: 'other-info-screen', name: 'otherInfoScreen', builder: (context, state) => OtherInfoScreen( - profileDetailsModel: state.extra as ProfileDetailsModel, + settingsEntity: state.extra as SettingsEntity, ), ), GoRoute( path: 'physical-activity-screen', name: 'physicalActivityScreen', builder: (context, state) => PhysicalActivityScreen( - profileDetailsModel: state.extra as ProfileDetailsModel, + settingsEntity: state.extra as SettingsEntity, ), ), GoRoute( path: 'physical-form-screen', name: 'physicalFormScreen', builder: (context, state) => PhysicalFormScreen( - profileDetailsModel: state.extra as ProfileDetailsModel, + settingsEntity: state.extra as SettingsEntity, ), ), GoRoute( path: 'pressure-screen', name: 'pressureScreen', builder: (context, state) => PressureScreen( - profileDetailsModel: state.extra as ProfileDetailsModel, + settingsEntity: state.extra as SettingsEntity, + ), + ), + GoRoute( + path: 'change-password-screen', + name: 'changePasswordScreen', + builder: (context, state) => ChangePasswordScreen( + settingsEntity: state.extra as SettingsEntity, ), ), ], diff --git a/lib/features/settings/entities/settings_entity.dart b/lib/features/settings/entities/settings_entity.dart new file mode 100644 index 00000000..4bd31ef3 --- /dev/null +++ b/lib/features/settings/entities/settings_entity.dart @@ -0,0 +1,15 @@ +import 'package:eatvio_app/features/profile/models/profile_model.dart'; +import 'package:eatvio_app/features/settings/models/profile_settings_model.dart'; +import 'package:eatvio_app/features/settings/presentation/bloc/settings_cubit/settings_cubit.dart'; + +class SettingsEntity { + final ProfileSettingsModel profileSettingsModel; + final ProfileDetailsModel profileDetailsModel; + final SettingsCubit settingsCubit; + + SettingsEntity({ + required this.profileSettingsModel, + required this.profileDetailsModel, + required this.settingsCubit, + }); +} diff --git a/lib/features/settings/presentation/bloc/settings_cubit/settings_cubit.dart b/lib/features/settings/presentation/bloc/settings_cubit/settings_cubit.dart index c4c0287b..ce448c88 100644 --- a/lib/features/settings/presentation/bloc/settings_cubit/settings_cubit.dart +++ b/lib/features/settings/presentation/bloc/settings_cubit/settings_cubit.dart @@ -12,9 +12,9 @@ class SettingsCubit extends Cubit { SettingsCubit({ required this.profileRepository, required this.settingsRepository, - }) : super(SettingsState.loading()); + }) : super(const SettingsState.loading()); - init() async { + Future init() async { try { emit(SettingsState.loaded( profileSettings: await settingsRepository.getProfileSettings(), @@ -26,7 +26,7 @@ class SettingsCubit extends Cubit { } updateProfileDetails({ - required ProfileDetailsModel profileDetailsModel + required ProfileDetailsModel profileDetailsModel, }) async { try { await settingsRepository.updateProfileDetails( @@ -35,11 +35,13 @@ class SettingsCubit extends Cubit { } catch (e) { print(e); rethrow; + } finally { + await init(); } } updateProfileSettings({ - required ProfileSettingsModel profileSettingsModel + required ProfileSettingsModel profileSettingsModel, }) async { try { await settingsRepository.updateProfileSettings( @@ -48,6 +50,8 @@ class SettingsCubit extends Cubit { } catch (e) { print(e); rethrow; + } finally { + await init(); } } } diff --git a/lib/features/settings/presentation/pages/change_password_screen.dart b/lib/features/settings/presentation/pages/change_password_screen.dart new file mode 100644 index 00000000..b67df070 --- /dev/null +++ b/lib/features/settings/presentation/pages/change_password_screen.dart @@ -0,0 +1,28 @@ +import 'package:eatvio_app/features/settings/entities/settings_entity.dart'; +import 'package:flutter/material.dart'; + +class ChangePasswordScreen extends StatefulWidget { + final SettingsEntity settingsEntity; + + const ChangePasswordScreen({ + super.key, + required this.settingsEntity, + }); + + @override + State createState() => _ChangePasswordScreenState(); +} + +class _ChangePasswordScreenState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Смена пароля'), + ), + body: Center( + child: Text('Coming soon...'), + ), + ); + } +} diff --git a/lib/features/settings/presentation/pages/general_info_screen.dart b/lib/features/settings/presentation/pages/general_info_screen.dart index 109e584c..4ad9e084 100644 --- a/lib/features/settings/presentation/pages/general_info_screen.dart +++ b/lib/features/settings/presentation/pages/general_info_screen.dart @@ -1,20 +1,21 @@ import 'package:eatvio_app/core/utils/date_time_utils.dart'; -import 'package:eatvio_app/features/profile/models/profile_model.dart'; +import 'package:eatvio_app/data/models/selectionPopupModel/selection_popup_model.dart'; +import 'package:eatvio_app/features/settings/entities/settings_entity.dart'; +import 'package:eatvio_app/features/settings/presentation/bloc/settings_cubit/settings_state.dart'; import 'package:eatvio_app/generated/l10n.dart'; import 'package:eatvio_app/theme/theme_helper.dart'; +import 'package:eatvio_app/widgets/custom_drop_down.dart'; import 'package:eatvio_app/widgets/custom_text_form_field.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; class GeneralInfoScreen extends StatefulWidget { - final ProfileDetailsModel profileDetailsModel; - final bool isPublicProfile; + final SettingsEntity settingsEntity; const GeneralInfoScreen({ super.key, - required this.profileDetailsModel, - required this.isPublicProfile, + required this.settingsEntity, }); @override @@ -24,25 +25,36 @@ class GeneralInfoScreen extends StatefulWidget { class _GeneralInfoScreenState extends State { final firstNameController = TextEditingController(); final lastNameController = TextEditingController(); - final genderController = TextEditingController(); + late DateTime selectedDate; + late SelectionPopupModel gender; final countryController = TextEditingController(); final cityController = TextEditingController(); final languageController = TextEditingController(); - late DateTime selectedDate; - late bool isPublicProfile; + late SelectionPopupModel isPublicProfile; + + final List genderSelectionPopupList = [ + SelectionPopupModel(id: 0, title: 'Женский', value: 'female'), + SelectionPopupModel(id: 1, title: 'Мужской', value: 'male'), + ]; + + final List isPublicProfileSelectionPopupList = [ + SelectionPopupModel(id: 0, title: 'Только зарегистрированным', value: false), + SelectionPopupModel(id: 1, title: 'Всем', value: true), + ]; @override void initState() { super.initState(); selectedDate = DateTime.now(); - firstNameController.text = widget.profileDetailsModel.firstName; - lastNameController.text = widget.profileDetailsModel.lastName; - selectedDate = DateTime.parse(widget.profileDetailsModel.birthdate); - genderController.text = widget.profileDetailsModel.gender; - countryController.text = widget.profileDetailsModel.country; - cityController.text = widget.profileDetailsModel.city; - languageController.text = widget.profileDetailsModel.lang; - isPublicProfile = widget.isPublicProfile; + firstNameController.text = widget.settingsEntity.profileDetailsModel.firstName; + lastNameController.text = widget.settingsEntity.profileDetailsModel.lastName; + selectedDate = DateTime.parse(widget.settingsEntity.profileDetailsModel.birthdate); + gender = widget.settingsEntity.profileDetailsModel.gender == 'male' ? genderSelectionPopupList[1] : genderSelectionPopupList[0]; + countryController.text = widget.settingsEntity.profileDetailsModel.country; + cityController.text = widget.settingsEntity.profileDetailsModel.city; + languageController.text = widget.settingsEntity.profileDetailsModel.lang; + isPublicProfile = + widget.settingsEntity.profileSettingsModel.isPublicProfile == true ? isPublicProfileSelectionPopupList[1] : isPublicProfileSelectionPopupList[0]; } @override @@ -78,43 +90,60 @@ class _GeneralInfoScreenState extends State { SizedBox(height: 16), Text(s.date_of_birth), SizedBox(height: 4), - CustomTextFormField( - initialValue: selectedDate.format('dd MMMM yyyy', 'ru'), + ListTile( + onTap: onTapCalendar(context), + trailing: Icon( + Icons.keyboard_arrow_down_rounded, + color: Colors.grey.shade700, + ), + contentPadding: EdgeInsets.symmetric(horizontal: 12), + title: Text(selectedDate.format('dd MMMM yyyy', 'ru')), + tileColor: Color(0xFFF6F6F6), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), ), SizedBox(height: 16), Text('Пол'), SizedBox(height: 4), - CustomTextFormField( - controller: genderController, - onChanged: (newValue) {}, + CustomDropDown( + items: genderSelectionPopupList, + value: gender, + onChanged: (newValue) { + setState(() { + gender = newValue; + }); + }, ), SizedBox(height: 16), Text('Страна'), SizedBox(height: 4), CustomTextFormField( controller: countryController, - onChanged: (newValue) {}, ), SizedBox(height: 16), Text('Город'), SizedBox(height: 4), CustomTextFormField( controller: cityController, - onChanged: (newValue) {}, ), SizedBox(height: 16), Text('Предпочтительный язык общения'), SizedBox(height: 4), CustomTextFormField( controller: languageController, - onChanged: (newValue) {}, ), SizedBox(height: 16), Text('Показывать анкету'), SizedBox(height: 4), - CustomTextFormField( - initialValue: isPublicProfile ? 'Всем' : 'Только зарегистрированным', - onChanged: (newValue) {}, + CustomDropDown( + items: isPublicProfileSelectionPopupList, + value: isPublicProfile, + onChanged: (newValue) { + setState(() { + isPublicProfile = newValue; + }); + }, ), ], ), @@ -133,8 +162,6 @@ class _GeneralInfoScreenState extends State { onDateTimeChanged: (DateTime newDateTime) { setState(() { selectedDate = newDateTime; - // final registrationCubit = context.read(); - // registrationCubit.updateSheet(registrationCubit.state.sheet.copyWith(birthdate: selectedDate.toString())); }); }, ), @@ -162,7 +189,25 @@ class _GeneralInfoScreenState extends State { _saveButton() { return InkWell( - onTap: () => GoRouter.of(context).pop(), + onTap: () { + widget.settingsEntity.settingsCubit.updateProfileDetails( + profileDetailsModel: (widget.settingsEntity.settingsCubit.state as SettingsStateLoaded).profileDetails.copyWith( + firstName: firstNameController.text, + lastName: lastNameController.text, + birthdate: selectedDate.toString(), + gender: gender.value, + country: countryController.text, + city: cityController.text, + lang: languageController.text, + ), + ); + widget.settingsEntity.settingsCubit.updateProfileSettings( + profileSettingsModel: (widget.settingsEntity.settingsCubit.state as SettingsStateLoaded).profileSettings.copyWith( + isPublicProfile: isPublicProfile.value, + ), + ); + GoRouter.of(context).pop(); + }, borderRadius: BorderRadius.circular(20), child: Ink( height: 52, diff --git a/lib/features/settings/presentation/pages/other_info_screen.dart b/lib/features/settings/presentation/pages/other_info_screen.dart index 4501a9f6..2799b853 100644 --- a/lib/features/settings/presentation/pages/other_info_screen.dart +++ b/lib/features/settings/presentation/pages/other_info_screen.dart @@ -1,4 +1,5 @@ -import 'package:eatvio_app/features/profile/models/profile_model.dart'; +import 'package:eatvio_app/features/settings/entities/settings_entity.dart'; +import 'package:eatvio_app/features/settings/presentation/bloc/settings_cubit/settings_state.dart'; import 'package:eatvio_app/generated/l10n.dart'; import 'package:eatvio_app/theme/theme_helper.dart'; import 'package:eatvio_app/widgets/custom_text_form_field.dart'; @@ -6,11 +7,11 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; class OtherInfoScreen extends StatefulWidget { - final ProfileDetailsModel profileDetailsModel; + final SettingsEntity settingsEntity; const OtherInfoScreen({ super.key, - required this.profileDetailsModel, + required this.settingsEntity, }); @override @@ -22,18 +23,18 @@ class _OtherInfoScreenState extends State { final aboutTakingPillsController = TextEditingController(); final aboutSportHobbiesController = TextEditingController(); final favoriteFoodsController = TextEditingController(); - final unfavouriteFoodsController = TextEditingController(); + final unFavouriteFoodsController = TextEditingController(); final additionalInfoController = TextEditingController(); @override void initState() { super.initState(); - aboutAllergyController.text = widget.profileDetailsModel.aboutAlergy; - aboutTakingPillsController.text = widget.profileDetailsModel.aboutTakingPils; - aboutSportHobbiesController.text = widget.profileDetailsModel.aboutSportHobbies; - favoriteFoodsController.text = widget.profileDetailsModel.favoriteFoods; - unfavouriteFoodsController.text = widget.profileDetailsModel.unfavoriteFoods; - additionalInfoController.text = widget.profileDetailsModel.additionalInfo; + aboutAllergyController.text = widget.settingsEntity.profileDetailsModel.aboutAlergy; + aboutTakingPillsController.text = widget.settingsEntity.profileDetailsModel.aboutTakingPils; + aboutSportHobbiesController.text = widget.settingsEntity.profileDetailsModel.aboutSportHobbies; + favoriteFoodsController.text = widget.settingsEntity.profileDetailsModel.favoriteFoods; + unFavouriteFoodsController.text = widget.settingsEntity.profileDetailsModel.unfavoriteFoods; + additionalInfoController.text = widget.settingsEntity.profileDetailsModel.additionalInfo; } @override @@ -96,7 +97,7 @@ class _OtherInfoScreenState extends State { Text(s.unfavorite_foods), SizedBox(height: 4), CustomTextFormField( - controller: unfavouriteFoodsController, + controller: unFavouriteFoodsController, hintText: s.enter_information, maxLines: 7, minLines: 2, @@ -124,7 +125,19 @@ class _OtherInfoScreenState extends State { _saveButton() { return InkWell( - onTap: () => GoRouter.of(context).pop(), + onTap: () { + widget.settingsEntity.settingsCubit.updateProfileDetails( + profileDetailsModel: (widget.settingsEntity.settingsCubit.state as SettingsStateLoaded).profileDetails.copyWith( + aboutAlergy: aboutAllergyController.text, + aboutTakingPils: aboutTakingPillsController.text, + aboutSportHobbies: aboutSportHobbiesController.text, + favoriteFoods: favoriteFoodsController.text, + unfavoriteFoods: unFavouriteFoodsController.text, + additionalInfo: additionalInfoController.text, + ), + ); + GoRouter.of(context).pop(); + }, borderRadius: BorderRadius.circular(20), child: Ink( height: 52, diff --git a/lib/features/settings/presentation/pages/physical_activity_screen.dart b/lib/features/settings/presentation/pages/physical_activity_screen.dart index 536009c2..22781421 100644 --- a/lib/features/settings/presentation/pages/physical_activity_screen.dart +++ b/lib/features/settings/presentation/pages/physical_activity_screen.dart @@ -1,17 +1,15 @@ -import 'package:eatvio_app/features/profile/models/profile_model.dart'; -import 'package:eatvio_app/features/settings/presentation/bloc/settings_cubit/settings_cubit.dart'; +import 'package:eatvio_app/features/settings/entities/settings_entity.dart'; import 'package:eatvio_app/features/settings/presentation/bloc/settings_cubit/settings_state.dart'; -import 'package:eatvio_app/locator_service.dart'; import 'package:eatvio_app/theme/theme_helper.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; class PhysicalActivityScreen extends StatefulWidget { - final ProfileDetailsModel profileDetailsModel; + final SettingsEntity settingsEntity; const PhysicalActivityScreen({ super.key, - required this.profileDetailsModel, + required this.settingsEntity, }); @override @@ -26,7 +24,7 @@ class _PhysicalActivityScreenState extends State { @override void initState() { super.initState(); - switch (widget.profileDetailsModel.activityCoefficient) { + switch (widget.settingsEntity.profileDetailsModel.activityCoefficient) { case 1.2: _physicalActivity = PhysicalActivity.minimum; break; @@ -141,11 +139,11 @@ class _PhysicalActivityScreenState extends State { default: break; } - sl().updateProfileDetails( - profileDetailsModel: (sl().state as SettingsStateLoaded).profileDetails.copyWith( - activityCoefficient: activityCoefficient, - ), - ); + widget.settingsEntity.settingsCubit.updateProfileDetails( + profileDetailsModel: (widget.settingsEntity.settingsCubit.state as SettingsStateLoaded).profileDetails.copyWith( + activityCoefficient: activityCoefficient, + ), + ); GoRouter.of(context).pop(); }, borderRadius: BorderRadius.circular(20), diff --git a/lib/features/settings/presentation/pages/physical_form_screen.dart b/lib/features/settings/presentation/pages/physical_form_screen.dart index d45a8367..4bd34b94 100644 --- a/lib/features/settings/presentation/pages/physical_form_screen.dart +++ b/lib/features/settings/presentation/pages/physical_form_screen.dart @@ -1,4 +1,5 @@ -import 'package:eatvio_app/features/profile/models/profile_model.dart'; +import 'package:eatvio_app/features/settings/entities/settings_entity.dart'; +import 'package:eatvio_app/features/settings/presentation/bloc/settings_cubit/settings_state.dart'; import 'package:eatvio_app/generated/l10n.dart'; import 'package:eatvio_app/theme/theme_helper.dart'; import 'package:eatvio_app/widgets/custom_text_form_field.dart'; @@ -7,11 +8,11 @@ import 'package:flutter/services.dart'; import 'package:go_router/go_router.dart'; class PhysicalFormScreen extends StatefulWidget { - final ProfileDetailsModel profileDetailsModel; + final SettingsEntity settingsEntity; const PhysicalFormScreen({ super.key, - required this.profileDetailsModel, + required this.settingsEntity, }); @override @@ -28,10 +29,10 @@ class _PhysicalFormScreenState extends State { @override void initState() { super.initState(); - chestCircumferenceController.text = widget.profileDetailsModel.chestCircumference.toString(); - waistCircumferenceController.text = widget.profileDetailsModel.waistCircumference.toString(); - hipCircumferenceController.text = widget.profileDetailsModel.hipCircumference.toString(); - heightController.text = widget.profileDetailsModel.height.toString(); + chestCircumferenceController.text = widget.settingsEntity.profileDetailsModel.chestCircumference.toString(); + waistCircumferenceController.text = widget.settingsEntity.profileDetailsModel.waistCircumference.toString(); + hipCircumferenceController.text = widget.settingsEntity.profileDetailsModel.hipCircumference.toString(); + heightController.text = widget.settingsEntity.profileDetailsModel.height.toString(); } @override @@ -90,7 +91,17 @@ class _PhysicalFormScreenState extends State { _saveButton() { return InkWell( - onTap: () => GoRouter.of(context).pop(), + onTap: () { + widget.settingsEntity.settingsCubit.updateProfileDetails( + profileDetailsModel: (widget.settingsEntity.settingsCubit.state as SettingsStateLoaded).profileDetails.copyWith( + chestCircumference: int.parse(chestCircumferenceController.text), + waistCircumference: int.parse(waistCircumferenceController.text), + hipCircumference: int.parse(hipCircumferenceController.text), + height: int.parse(heightController.text), + ), + ); + GoRouter.of(context).pop(); + }, borderRadius: BorderRadius.circular(20), child: Ink( height: 52, diff --git a/lib/features/settings/presentation/pages/pressure_screen.dart b/lib/features/settings/presentation/pages/pressure_screen.dart index 62d4ce8a..7c1ee72a 100644 --- a/lib/features/settings/presentation/pages/pressure_screen.dart +++ b/lib/features/settings/presentation/pages/pressure_screen.dart @@ -1,5 +1,6 @@ import 'package:eatvio_app/data/models/selectionPopupModel/selection_popup_model.dart'; -import 'package:eatvio_app/features/profile/models/profile_model.dart'; +import 'package:eatvio_app/features/settings/entities/settings_entity.dart'; +import 'package:eatvio_app/features/settings/presentation/bloc/settings_cubit/settings_state.dart'; import 'package:eatvio_app/generated/l10n.dart'; import 'package:eatvio_app/theme/theme_helper.dart'; import 'package:eatvio_app/widgets/custom_drop_down.dart'; @@ -9,11 +10,11 @@ import 'package:flutter/services.dart'; import 'package:go_router/go_router.dart'; class PressureScreen extends StatefulWidget { - final ProfileDetailsModel profileDetailsModel; + final SettingsEntity settingsEntity; const PressureScreen({ super.key, - required this.profileDetailsModel, + required this.settingsEntity, }); @override @@ -30,21 +31,15 @@ class _PressureScreenState extends State { @override void initState() { super.initState(); - bloodPressureUpController.text = widget.profileDetailsModel.bloodPressureUp.toString(); - bloodPressureDownController.text = widget.profileDetailsModel.bloodPressureDown.toString(); - hypo = widget.profileDetailsModel.hasHypo ? selectionPopupList[0] : selectionPopupList[1]; - hyper = widget.profileDetailsModel.hasHyper ? selectionPopupList[0] : selectionPopupList[1]; + bloodPressureUpController.text = widget.settingsEntity.profileDetailsModel.bloodPressureUp.toString(); + bloodPressureDownController.text = widget.settingsEntity.profileDetailsModel.bloodPressureDown.toString(); + hypo = widget.settingsEntity.profileDetailsModel.hasHypo ? selectionPopupList[1] : selectionPopupList[0]; + hyper = widget.settingsEntity.profileDetailsModel.hasHyper ? selectionPopupList[1] : selectionPopupList[0]; } final List selectionPopupList = [ - SelectionPopupModel( - id: 1, - title: "Да", - ), - SelectionPopupModel( - id: 0, - title: "Нет", - ), + SelectionPopupModel(id: 0, title: 'Нет', value: false), + SelectionPopupModel(id: 1, title: 'Да', value: true), ]; @override @@ -113,7 +108,17 @@ class _PressureScreenState extends State { _saveButton() { return InkWell( - onTap: () => GoRouter.of(context).pop(), + onTap: () { + widget.settingsEntity.settingsCubit.updateProfileDetails( + profileDetailsModel: (widget.settingsEntity.settingsCubit.state as SettingsStateLoaded).profileDetails.copyWith( + bloodPressureUp: int.parse(bloodPressureUpController.text), + bloodPressureDown: int.parse(bloodPressureDownController.text), + hasHyper: hyper.value, + hasHypo: hypo.value, + ), + ); + GoRouter.of(context).pop(); + }, borderRadius: BorderRadius.circular(20), child: Ink( height: 52, diff --git a/lib/features/settings/presentation/pages/settings_screen.dart b/lib/features/settings/presentation/pages/settings_screen.dart index 1072c270..9c1e7b34 100644 --- a/lib/features/settings/presentation/pages/settings_screen.dart +++ b/lib/features/settings/presentation/pages/settings_screen.dart @@ -1,4 +1,5 @@ import 'package:eatvio_app/core/const.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/locator_service.dart'; @@ -18,18 +19,24 @@ class SettingsScreen extends StatefulWidget { } class _SettingsScreenState extends State { + final SettingsCubit settingsCubit = sl()..init(); late bool updatesNotificationsSwitchState; late bool fillDiaryNotificationsSwitchState; + late bool bedTimeSwitchState; + late bool moodSwitchState; @override Widget build(BuildContext context) { return BlocProvider( - create: (BuildContext context) => sl()..init(), + 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 == 1 ? true : false; + moodSwitchState = state.profileSettings.isMoodFillable == 1 ? true : false; } }, builder: (BuildContext context, SettingsState state) { @@ -100,10 +107,11 @@ class _SettingsScreenState extends State { _tile( onTap: () => GoRouter.of(context).pushNamed( 'generalInfoScreen', - extra: state.profileDetails, - pathParameters: { - 'isPublicProfile': state.profileSettings.isPublicProfile.toString(), - }, + extra: SettingsEntity( + profileSettingsModel: state.profileSettings, + profileDetailsModel: state.profileDetails, + settingsCubit: settingsCubit, + ), ), title: 'Общая информация', ), @@ -111,7 +119,11 @@ class _SettingsScreenState extends State { _tile( onTap: () => GoRouter.of(context).pushNamed( 'physicalFormScreen', - extra: state.profileDetails, + extra: SettingsEntity( + profileSettingsModel: state.profileSettings, + profileDetailsModel: state.profileDetails, + settingsCubit: settingsCubit, + ), ), title: 'Физическая форма', ), @@ -119,7 +131,11 @@ class _SettingsScreenState extends State { _tile( onTap: () => GoRouter.of(context).pushNamed( 'pressureScreen', - extra: state.profileDetails, + extra: SettingsEntity( + profileSettingsModel: state.profileSettings, + profileDetailsModel: state.profileDetails, + settingsCubit: settingsCubit, + ), ), title: 'Давление', ), @@ -127,7 +143,11 @@ class _SettingsScreenState extends State { _tile( onTap: () => GoRouter.of(context).pushNamed( 'otherInfoScreen', - extra: state.profileDetails, + extra: SettingsEntity( + profileSettingsModel: state.profileSettings, + profileDetailsModel: state.profileDetails, + settingsCubit: settingsCubit, + ), ), title: 'Прочая информация', ), @@ -135,10 +155,26 @@ class _SettingsScreenState extends State { _tile( onTap: () => GoRouter.of(context).pushNamed( 'physicalActivityScreen', - extra: state.profileDetails, + extra: SettingsEntity( + profileSettingsModel: state.profileSettings, + profileDetailsModel: state.profileDetails, + settingsCubit: settingsCubit, + ), ), title: 'Физическая нагрузка', ), + _divider(context), + _tile( + onTap: () => GoRouter.of(context).pushNamed( + 'changePasswordScreen', + extra: SettingsEntity( + profileSettingsModel: state.profileSettings, + profileDetailsModel: state.profileDetails, + settingsCubit: settingsCubit, + ), + ), + title: 'Сменить пароль', + ), ], ); } @@ -163,11 +199,11 @@ class _SettingsScreenState extends State { setState(() { updatesNotificationsSwitchState = !updatesNotificationsSwitchState; }); - context.read().updateProfileSettings( - profileSettingsModel: state.profileSettings.copyWith( + settingsCubit.updateProfileSettings( + profileSettingsModel: state.profileSettings.copyWith( newUpdatesNotifications: updatesNotificationsSwitchState, ), - ); + ); }, title: 'Уведомление о новых обновлениях', trailing: CupertinoSwitch( @@ -177,11 +213,11 @@ class _SettingsScreenState extends State { setState(() { updatesNotificationsSwitchState = newValue; }); - context.read().updateProfileSettings( - profileSettingsModel: state.profileSettings.copyWith( + settingsCubit.updateProfileSettings( + profileSettingsModel: state.profileSettings.copyWith( newUpdatesNotifications: updatesNotificationsSwitchState, ), - ); + ); }, ), ), @@ -191,11 +227,11 @@ class _SettingsScreenState extends State { setState(() { fillDiaryNotificationsSwitchState = !fillDiaryNotificationsSwitchState; }); - context.read().updateProfileSettings( - profileSettingsModel: state.profileSettings.copyWith( + settingsCubit.updateProfileSettings( + profileSettingsModel: state.profileSettings.copyWith( diaryReminderNotifications: fillDiaryNotificationsSwitchState, ), - ); + ); }, title: 'Напоминание о заполнении дневника', trailing: CupertinoSwitch( @@ -205,11 +241,67 @@ class _SettingsScreenState extends State { setState(() { fillDiaryNotificationsSwitchState = newValue; }); - context.read().updateProfileSettings( - profileSettingsModel: state.profileSettings.copyWith( + settingsCubit.updateProfileSettings( + profileSettingsModel: state.profileSettings.copyWith( diaryReminderNotifications: fillDiaryNotificationsSwitchState, ), - ); + ); + }, + ), + ), + _divider(context), + _tile( + onTap: () { + setState(() { + moodSwitchState = !moodSwitchState; + }); + settingsCubit.updateProfileSettings( + profileSettingsModel: state.profileSettings.copyWith( + isMoodFillable: moodSwitchState, + ), + ); + }, + title: 'Указывать “настроение” в заполнение дневника', + trailing: CupertinoSwitch( + value: moodSwitchState, + activeColor: appTheme.blueA400, + onChanged: (newValue) { + setState(() { + moodSwitchState = newValue; + }); + settingsCubit.updateProfileSettings( + profileSettingsModel: state.profileSettings.copyWith( + isMoodFillable: moodSwitchState, + ), + ); + }, + ), + ), + _divider(context), + _tile( + onTap: () { + setState(() { + bedTimeSwitchState = !bedTimeSwitchState; + }); + settingsCubit.updateProfileSettings( + profileSettingsModel: state.profileSettings.copyWith( + isBedtimeFillable: bedTimeSwitchState, + ), + ); + }, + title: 'Указывать “отход ко сну” в заполнение дневника', + trailing: CupertinoSwitch( + value: bedTimeSwitchState, + activeColor: appTheme.blueA400, + onChanged: (newValue) { + setState(() { + bedTimeSwitchState = newValue; + }); + settingsCubit.updateProfileSettings( + profileSettingsModel: state.profileSettings.copyWith( + isBedtimeFillable: bedTimeSwitchState, + ), + ); }, ), ), @@ -264,7 +356,6 @@ class _SettingsScreenState extends State { style: TextStyle( color: Colors.white, height: 1, - fontWeight: FontWeight.w600, fontSize: 18, ), ), @@ -293,7 +384,6 @@ class _SettingsScreenState extends State { style: TextStyle( color: Colors.black, height: 1, - fontWeight: FontWeight.w600, fontSize: 18, ), ), diff --git a/lib/widgets/custom_drop_down.dart b/lib/widgets/custom_drop_down.dart index a68a696f..7522893a 100644 --- a/lib/widgets/custom_drop_down.dart +++ b/lib/widgets/custom_drop_down.dart @@ -64,11 +64,11 @@ class CustomDropDown extends StatelessWidget { value: value, isDense: true, isExpanded: true, - style: textStyle ?? - TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - ), + style: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w400, + ), items: items?.map((SelectionPopupModel item) { return DropdownMenuItem( value: item, @@ -95,6 +95,11 @@ class CustomDropDown extends StatelessWidget { InputDecoration _buildInputDecoration(BuildContext context) { return InputDecoration( + labelStyle: TextStyle( + fontSize: 16, + color: Colors.black, + fontWeight: FontWeight.w400, + ), hintText: hintText ?? "", hintStyle: hintStyle ?? TextStyle(