From ce19460af3668728e938466e683ace42fb21877c Mon Sep 17 00:00:00 2001 From: maxxkim Date: Mon, 1 Apr 2024 13:24:56 +0300 Subject: [PATCH 1/5] feat(diary): Added portion change (pcs gr) --- lib/localization/ru/ru_translations.dart | 2 + .../bloc/diary_edit_bloc.dart | 35 ++++++++++-- .../bloc/diary_edit_event.dart | 8 +++ .../bloc/diary_edit_state.dart | 5 ++ .../diary_edit_screen/diary_edit_screen.dart | 57 ++++++++++++------- .../models/diary_edit_model.dart | 7 ++- 6 files changed, 87 insertions(+), 27 deletions(-) diff --git a/lib/localization/ru/ru_translations.dart b/lib/localization/ru/ru_translations.dart index 85794150..3d28a232 100644 --- a/lib/localization/ru/ru_translations.dart +++ b/lib/localization/ru/ru_translations.dart @@ -133,4 +133,6 @@ final Map ru = { "admin": "Админ", "diary": "Дневник", "save": "Сохранить", + "pcs": "порций", + "gr": "гр", }; diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart index be0a7a9d..bedf0c27 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart @@ -20,6 +20,7 @@ class DiaryEditBloc extends Bloc { on(_changeMood); // пользователь нажимает на шкалу настроения on(_changeMealTime); // пользовательяет времяа пиши on(_changeMeal); + on(_changePortion); on(_changeWakeup); // пользователь выбирает время пробуждения on(_changeRetire); // пользователь выбирает время отхода ко сну on(_toggleMood); @@ -103,6 +104,8 @@ class DiaryEditBloc extends Bloc { emit(DiaryEditLoadedState( currentMeal: SelectionPopupModel( id: 1, title: "Прием пищи 1", isSelected: true), + portionController: SelectionPopupModel( + id: 0, title: "порций", isSelected: true), wakeupExpanded: true, moodExpanded: true, moderationExpanded: false, @@ -127,8 +130,9 @@ class DiaryEditBloc extends Bloc { diaryId: diaryId, diaryDate: diaryDate, autocompleteList: [], - diaryEditModelObj: state.diaryEditModelObj - ?.copyWith(mealList: fillMealList()))); + diaryEditModelObj: state.diaryEditModelObj?.copyWith( + mealList: fillMealList(), + portionList: fillPortions()))); } } else { // Ошибка при декодировании JSON @@ -192,6 +196,8 @@ class DiaryEditBloc extends Bloc { await Future(() => emit(DiaryEditLoadedState( currentMeal: SelectionPopupModel( id: 1, title: "Прием пищи 1", isSelected: true), + portionController: SelectionPopupModel( + id: 0, title: "порций", isSelected: true), wakeupExpanded: true, moodExpanded: true, moderationExpanded: false, @@ -216,8 +222,8 @@ class DiaryEditBloc extends Bloc { diaryId: diaryId, diaryDate: diaryDate, autocompleteList: [], - diaryEditModelObj: state.diaryEditModelObj - ?.copyWith(mealList: fillMealList())))); + diaryEditModelObj: state.diaryEditModelObj?.copyWith( + mealList: fillMealList(), portionList: fillPortions())))); print("Updated"); } catch (e) { @@ -456,6 +462,18 @@ class DiaryEditBloc extends Bloc { } } + FutureOr _changePortion( + ChangePortion event, Emitter emit) { + if (state is DiaryEditLoadedState) { + var currentState = state as DiaryEditLoadedState; + DiaryEditLoadedState updatedState = currentState.copyWith( + portionController: event.value, + ); + print(updatedState.portionController?.title); + emit(updatedState); + } + } + FutureOr _toggleMood( ToggleMoodExpandedEvent event, Emitter emit) { if (state is DiaryEditLoadedState) { @@ -484,7 +502,7 @@ class DiaryEditBloc extends Bloc { var response = await sendPortionData( currentState.token, currentState.productNameController?.text, - 'pcs', + currentState.portionController?.id == 0 ? 'pcs' : 'gr', int.parse(currentState.productQuantityController!.text), currentState.currentMeal!.id, currentState.diaryId, @@ -803,4 +821,11 @@ class DiaryEditBloc extends Bloc { SelectionPopupModel(id: 6, title: "Прием пищи 6"), ]; } + + List fillPortions() { + return [ + SelectionPopupModel(id: 0, title: "порций", isSelected: true), + SelectionPopupModel(id: 1, title: "грамм"), + ]; + } } diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_event.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_event.dart index 6ab61626..873a667c 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_event.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_event.dart @@ -114,6 +114,14 @@ class ChangeMeal extends DiaryEditEvent { List get props => [value, meals]; } +class ChangePortion extends DiaryEditEvent { + ChangePortion({required this.value}); + + SelectionPopupModel value; + @override + List get props => [value]; +} + class FinishDay extends DiaryEditEvent { FinishDay(); diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_state.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_state.dart index abaed360..470b3268 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_state.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_state.dart @@ -30,6 +30,7 @@ class DiaryEditLoadedState extends DiaryEditState { this.retireController, this.commentController, this.mealTimeController, + this.portionController, this.productNameController, this.productQuantityController, this.selectedMood, @@ -53,6 +54,7 @@ class DiaryEditLoadedState extends DiaryEditState { List? photos; List? autocompleteList; SelectionPopupModel? currentMeal; + SelectionPopupModel? portionController; TimeOfDay? wakeupController; TimeOfDay? retireController; TimeOfDay? mealTimeController; @@ -84,6 +86,7 @@ class DiaryEditLoadedState extends DiaryEditState { commentController, productNameController, productQuantityController, + portionController, caloriesController, fatsController, proteinsController, @@ -99,6 +102,7 @@ class DiaryEditLoadedState extends DiaryEditState { DiaryEditLoadedState copyWith({ DiaryEditModel? diaryEditModelObj, SelectionPopupModel? currentMeal, + SelectionPopupModel? portionController, String? diaryDate, String? token, List? meals, @@ -133,6 +137,7 @@ class DiaryEditLoadedState extends DiaryEditState { retireController: retireController ?? this.retireController, mealTimeController: mealTimeController ?? this.mealTimeController, commentController: commentController ?? this.commentController, + portionController: portionController ?? this.portionController, productNameController: productNameController ?? this.productNameController, productQuantityController: diff --git a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart index 7c839e7e..20be9837 100644 --- a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart +++ b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart @@ -365,25 +365,36 @@ class DiaryEditScreen extends StatelessWidget { SizedBox(height: 20.v), Padding( padding: EdgeInsets.symmetric(horizontal: 10.h), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - CustomTextFormField( - width: 146.h, - hintText: "Кол-во", - textInputAction: TextInputAction.done, - focusNode: focusNodeQuantity, - controller: state.productQuantityController, - keyboardType: TextInputType.number, - inputFormatters: [digitsOnly], - ), - Padding( - padding: EdgeInsets.only(right: 30.h), - child: Text( - "порций", - style: CustomTextStyles.bodyMediumBlack900, - )), - ], + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + CustomTextFormField( + width: 150.h, + hintText: "Кол-во", + textInputAction: TextInputAction.done, + focusNode: focusNodeQuantity, + controller: state.productQuantityController, + keyboardType: TextInputType.number, + inputFormatters: [digitsOnly], + ), + Padding( + padding: EdgeInsets.only(left: 30.h), + child: BlocSelector( + selector: (state) => state.diaryEditModelObj, + builder: (context, diaryEditModelObj) { + return CustomDropDown( + items: diaryEditModelObj?.portionList, + defaultValue: diaryEditModelObj?.portionList?[0], + onChanged: changePortion(context, state), + ); + }, + ), + ), + ], + ), ), ), SizedBox(height: 30.v), @@ -583,6 +594,12 @@ class DiaryEditScreen extends StatelessWidget { }; } + changePortion(BuildContext context, DiaryEditLoadedState state) { + return (value) { + context.read().add(ChangePortion(value: value)); + }; + } + _buildProduct(BuildContext context, Map portion) { return Container( margin: EdgeInsets.symmetric(horizontal: 10.h), @@ -617,7 +634,7 @@ class DiaryEditScreen extends StatelessWidget { child: Text( portion['quantity'].toString() + ' ' + - portion['portion'].toString(), + portion['portion'].toString().tr, ), ), Spacer(), diff --git a/lib/presentation/diary/diary_edit_screen/models/diary_edit_model.dart b/lib/presentation/diary/diary_edit_screen/models/diary_edit_model.dart index a175b889..6f68bc2d 100644 --- a/lib/presentation/diary/diary_edit_screen/models/diary_edit_model.dart +++ b/lib/presentation/diary/diary_edit_screen/models/diary_edit_model.dart @@ -6,17 +6,20 @@ import 'package:eatvio_app/data/models/selectionPopupModel/selection_popup_model /// This class defines the variables used in the [k0_page], /// and is typically used to hold data that is passed between different parts of the application. class DiaryEditModel extends Equatable { - DiaryEditModel({this.mealList = const []}); + DiaryEditModel({this.mealList = const [], this.portionList = const []}); List mealList; + List? portionList; DiaryEditModel copyWith({ List? mealList, + List? portionList, }) { return DiaryEditModel( mealList: mealList ?? this.mealList, + portionList: portionList ?? this.portionList, ); } @override - List get props => [mealList]; + List get props => [mealList, portionList]; } From a2998c1fc7ac795e2a1b7d8aa0b2a88acf4c2570 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Mon, 1 Apr 2024 17:21:26 +0300 Subject: [PATCH 2/5] feat(diary): Image remove layout and API method --- .../bloc/diary_edit_bloc.dart | 51 +++++++++++++++++-- .../bloc/diary_edit_event.dart | 8 +++ .../diary_edit_screen/diary_edit_screen.dart | 46 ++++++++++++++--- 3 files changed, 92 insertions(+), 13 deletions(-) diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart index bedf0c27..72f012d7 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart @@ -26,8 +26,9 @@ class DiaryEditBloc extends Bloc { on(_toggleMood); on(_toggleWakeup); on(_addPortion); //пользователь нажимает "Добавить продукт" - on( - _removePortion); // пользователь нажимает на крестик около продукта + on(_removePortion); + on( + _removeImage); // пользователь нажимает на крестик около продукта on(_uploadImages); //пользователь нажимает "Добавить фото" on(_addComment); //пользователь нажимает "Добавить комментарий" on( @@ -469,7 +470,6 @@ class DiaryEditBloc extends Bloc { DiaryEditLoadedState updatedState = currentState.copyWith( portionController: event.value, ); - print(updatedState.portionController?.title); emit(updatedState); } } @@ -508,8 +508,6 @@ class DiaryEditBloc extends Bloc { currentState.diaryId, ); - print(response.body); - if (response.statusCode == 200) { await reloadScreen(event, emit); } else { @@ -624,6 +622,49 @@ class DiaryEditBloc extends Bloc { return response; } + FutureOr _removeImage( + RemoveImageEvent event, Emitter emit) async { + if (state is DiaryEditLoadedState) { + var currentState = state as DiaryEditLoadedState; + + var response = await sendRemovePhoto( + currentState.token, + event.path, + event.photoID, + currentState.currentMeal?.id, + currentState.diaryId, + ); + print(response.statusCode); + if (response.statusCode == 204) { + await reloadScreen(event, emit); + } else { + print( + 'Failed to remove photo. Status Code: ${response.statusCode} ${response.body}'); + } + } + } + + Future sendRemovePhoto(String? token, String? path, + String? photoID, int? mealID, int diaryID) async { + String url = + '${dotenv.env['SERVER_ROOT']!}/diary/$diaryID/meal/$mealID/photo/delete'; + final Map credentials = { + 'id': photoID, + 'path': path, + }; + var response = await http.delete( + Uri.parse(url), + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer $token', + }, + body: json.encode(credentials), + encoding: utf8, + ); + + return response; + } + Future _finishDay(FinishDay event, Emitter emit) async { if (state is DiaryEditLoadedState) { var currentState = state as DiaryEditLoadedState; diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_event.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_event.dart index 873a667c..08b1e90a 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_event.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_event.dart @@ -98,6 +98,14 @@ class UploadImages extends DiaryEditEvent { List get props => [image]; } +class RemoveImageEvent extends DiaryEditEvent { + RemoveImageEvent(this.photoID, this.path); + final String photoID; + final String path; + @override + List get props => [photoID, path]; +} + class ProductInput extends DiaryEditEvent { ProductInput(this.input); final String input; diff --git a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart index 20be9837..52dffb50 100644 --- a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart +++ b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart @@ -653,14 +653,36 @@ class DiaryEditScreen extends StatelessWidget { } _buildPhoto(BuildContext context, Map photo) { - return Container( - margin: EdgeInsets.symmetric(horizontal: 10.h, vertical: 10.h), - decoration: AppDecoration.fillGray.copyWith( - borderRadius: BorderRadiusStyle.roundedBorder5, - ), - child: Image.network( - dotenv.env['STORAGE_URL']! + photo['path'], - ), + return Stack( + children: [ + Container( + margin: EdgeInsets.symmetric(horizontal: 10.h, vertical: 10.h), + decoration: AppDecoration.fillGray.copyWith( + borderRadius: BorderRadiusStyle.roundedBorder5, + ), + child: Image.network( + dotenv.env['STORAGE_URL']! + photo['path'], + ), + ), + Positioned( + top: 5, + right: 5, + child: GestureDetector( + onTap: removePhoto(context, photo), + child: Container( + padding: EdgeInsets.all(5), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.transparent, + ), + child: Icon( + Icons.close, + color: appTheme.blueGray300, + ), + ), + ), + ), + ], ); } @@ -670,6 +692,14 @@ class DiaryEditScreen extends StatelessWidget { }; } + removePhoto(BuildContext context, Map photo) { + return () { + context + .read() + .add(RemoveImageEvent(photo['id'].toString(), photo['path'])); + }; + } + _buildNutritionChart(BuildContext context) { final List recommendedValues = [ 2000, From 76a421bba5df992a6dc892a2f266f37070182237 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Tue, 2 Apr 2024 17:14:17 +0300 Subject: [PATCH 3/5] profile(refactor): New functionalityy for settings screen --- lib/presentation/auth/auth_screen/auth_screen.dart | 12 ++++++++++++ .../diary_edit_screen/bloc/diary_edit_bloc.dart | 1 + .../my_profile_screen/bloc/my_profile_bloc.dart | 6 ++++-- .../my_profile_screen/my_settings_screen.dart | 6 +++--- lib/widgets/custom_expandable_list.dart | 4 ++-- 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/lib/presentation/auth/auth_screen/auth_screen.dart b/lib/presentation/auth/auth_screen/auth_screen.dart index 93d38b46..1ac19724 100644 --- a/lib/presentation/auth/auth_screen/auth_screen.dart +++ b/lib/presentation/auth/auth_screen/auth_screen.dart @@ -71,6 +71,12 @@ class AuthScreen extends StatelessWidget { EdgeInsets.only(left: 16.h, right: 16.h, bottom: 50.v), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, onPressed: onTapDiaryTest(context)), + NextStepButton( + text: "Тест профиля".toUpperCase(), + margin: + EdgeInsets.only(left: 16.h, right: 16.h, bottom: 50.v), + buttonStyle: CustomButtonStyles.outlinePrimaryTL15, + onPressed: onTapProfileTest(context)), BlocBuilder(builder: (context, state) { return NextStepButton( text: "authentificate".tr.toUpperCase(), @@ -156,6 +162,12 @@ class AuthScreen extends StatelessWidget { }; } + onTapProfileTest(BuildContext context) { + return () { + Navigator.pushNamed(context, AppRoutes.mySettings); + }; + } + onTapNoAccount(BuildContext context) { return () { Navigator.pushNamed(context, AppRoutes.languageSelectScreen); diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart index 72f012d7..82bafe8a 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart @@ -451,6 +451,7 @@ class DiaryEditBloc extends Bloc { (meal) => meal['type'] == event.value.id, orElse: () => null); + print(meal); int? id = event.value.id; DiaryEditLoadedState updatedState = currentState.copyWith( currentMeal: event.value, diff --git a/lib/presentation/profile/my_profile_screen/bloc/my_profile_bloc.dart b/lib/presentation/profile/my_profile_screen/bloc/my_profile_bloc.dart index 03ae81b8..dad1ce9a 100644 --- a/lib/presentation/profile/my_profile_screen/bloc/my_profile_bloc.dart +++ b/lib/presentation/profile/my_profile_screen/bloc/my_profile_bloc.dart @@ -21,8 +21,10 @@ class MyProfileBloc extends Bloc { Emitter emit, ) async { try { - final box = await Hive.openBox('token'); - final token = box.get('token'); + /*final box = await Hive.openBox('token'); + final token = box.get('token');*/ + final token = + "9|laravel_sanctum_KFXbccDcWEvTPfJmV99EQv1neAggmpR2TidVGDPN34fa201a"; final response = await http.get( Uri.parse(dotenv.env['SERVER_ROOT']! + '/profile/index'), headers: { diff --git a/lib/presentation/profile/my_profile_screen/my_settings_screen.dart b/lib/presentation/profile/my_profile_screen/my_settings_screen.dart index a95b0434..923597a6 100644 --- a/lib/presentation/profile/my_profile_screen/my_settings_screen.dart +++ b/lib/presentation/profile/my_profile_screen/my_settings_screen.dart @@ -44,15 +44,15 @@ class MySettingsScreen extends StatelessWidget { _buildSetingsScreen(BuildContext context, MyProfileLoadedState state) { mediaQueryData = MediaQuery.of(context); - SafeArea( + return SafeArea( child: Scaffold( appBar: _buildAppBar(context, "my_settings".tr), body: Padding( padding: const EdgeInsets.all(16.0), child: ListView( children: [ - SectionTitle('Язык'), - LanguageDropdown(), + //SectionTitle('Язык'), + //LanguageDropdown(), SectionTitle('Уведомления'), NotificationSwitch('Уведомление об обновлениях'), NotificationSwitch('Напоминания о заполнении'), diff --git a/lib/widgets/custom_expandable_list.dart b/lib/widgets/custom_expandable_list.dart index f20ac19e..786ed6be 100644 --- a/lib/widgets/custom_expandable_list.dart +++ b/lib/widgets/custom_expandable_list.dart @@ -130,7 +130,7 @@ class _ExpandableListState extends State { decoration: InputDecoration(labelText: 'date_of_birth'.tr), controller: state.dateFormController, onTap: inputTime(context, state)), - DropdownButtonFormField( + /*DropdownButtonFormField( value: state.selectedCountry, hint: Text(state.selectedCountry ?? "Не выбрано"), onChanged: setCountry(state), @@ -153,7 +153,7 @@ class _ExpandableListState extends State { ); }).toList(), decoration: InputDecoration(labelText: 'city_of_living'.tr), - ), + ),*/ TextField( controller: state.weightFormController, decoration: InputDecoration(labelText: 'weight_measurements'.tr), From 64c25f11fea7d1d86aba9f22f8275aeedd827a4a Mon Sep 17 00:00:00 2001 From: maxxkim Date: Wed, 3 Apr 2024 14:03:06 +0300 Subject: [PATCH 4/5] feat(diary): Nutrition chart API methods implemented --- .../bloc/diary_edit_bloc.dart | 248 +++++++++++------- .../bloc/diary_edit_state.dart | 11 + .../diary_edit_screen/diary_edit_screen.dart | 16 +- .../bloc/my_profile_bloc.dart | 2 +- lib/widgets/custom_expandable_list.dart | 4 +- test/diary_test.dart | 2 + 6 files changed, 170 insertions(+), 113 deletions(-) diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart index 82bafe8a..d3d9d29c 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart @@ -70,70 +70,97 @@ class DiaryEditBloc extends Bloc { if (diary is Map) { final String diaryDate = diary['date'] ?? DateTime.now().toString(); - // Продолжайте обработку данных дневника - if (state is DiaryEditLoadedState) { - // Если текущее состояние уже загружено, обновляем его - var currentState = state as DiaryEditLoadedState; - emit((currentState).copyWith( - currentMeal: currentState.currentMeal, - wakeupExpanded: currentState.wakeupExpanded, - moodExpanded: currentState.moodExpanded, - moderationExpanded: currentState.moderationExpanded, - token: currentState.token, - meals: currentState.meals, - portions: currentState.portions, - photos: currentState.photos, - wakeupController: currentState.wakeupController, - retireController: currentState.retireController, - commentController: currentState.commentController, - mealTimeController: currentState.mealTimeController, - productNameController: currentState.productNameController, - caloriesController: currentState.caloriesController, - proteinsController: currentState.proteinsController, - fatsController: currentState.fatsController, - carbsController: currentState.carbsController, - selectedSatiety: currentState.selectedSatiety, - selectedMood: currentState.selectedMood, - diaryDate: currentState.diaryDate, - diaryId: currentState.diaryId, - productQuantityController: - currentState.productQuantityController, - autocompleteList: currentState.autocompleteList, - diaryEditModelObj: currentState.diaryEditModelObj)); + final responseChart = await http.get( + Uri.parse(dotenv.env['SERVER_ROOT']! + + '/diary/$diaryId/dailyNutritionData/'), + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer $token', + }, + ); + if (responseChart.statusCode == 200) { + final recommendedChartValues = jsonDecode( + responseChart.body)['dailyNutritionRecommendation']; + final consumedChartValues = + jsonDecode(responseChart.body)['dailyNutritionIntake']; + + if (state is DiaryEditLoadedState) { + // Если текущее состояние уже загружено, обновляем его + var currentState = state as DiaryEditLoadedState; + emit((currentState).copyWith( + currentMeal: currentState.currentMeal, + wakeupExpanded: currentState.wakeupExpanded, + moodExpanded: currentState.moodExpanded, + moderationExpanded: currentState.moderationExpanded, + token: currentState.token, + meals: currentState.meals, + portions: currentState.portions, + photos: currentState.photos, + wakeupController: currentState.wakeupController, + retireController: currentState.retireController, + commentController: currentState.commentController, + mealTimeController: currentState.mealTimeController, + productNameController: currentState.productNameController, + caloriesController: currentState.caloriesController, + proteinsController: currentState.proteinsController, + fatsController: currentState.fatsController, + carbsController: currentState.carbsController, + selectedSatiety: currentState.selectedSatiety, + selectedMood: currentState.selectedMood, + diaryDate: currentState.diaryDate, + diaryId: currentState.diaryId, + productQuantityController: + currentState.productQuantityController, + recommendedChartValues: + currentState.recommendedChartValues, + consumedChartValues: currentState.consumedChartValues, + autocompleteList: currentState.autocompleteList, + diaryEditModelObj: currentState.diaryEditModelObj)); + } else { + // Если текущее состояние - начальное, создаем новое загруженное состояние + emit(DiaryEditLoadedState( + currentMeal: SelectionPopupModel( + id: 1, title: "Прием пищи 1", isSelected: true), + portionController: SelectionPopupModel( + id: 0, title: "порций", isSelected: true), + wakeupExpanded: true, + moodExpanded: true, + moderationExpanded: false, + token: token, + recommendedChartValues: recommendedChartValues.values + .map((value) => value as int) + .toList(), + consumedChartValues: consumedChartValues.values + .map((value) => value as int) + .toList() ?? + [0, 0, 0, 0], + meals: diary['meals'], + portions: diary['meals'][0]['portions'], + photos: diary['meals'][0]['photos'], + wakeupController: toTime(diary['wakeup'] ?? "09:00"), + retireController: toTime(diary['retire'] ?? "23:00"), + mealTimeController: + toTime(diary['meals'][0]['time'] ?? "10:00"), + selectedSatiety: diary['meals'][0]['satiety'], + selectedMood: diary['meals'][0]['mood'], + commentController: + TextEditingController(text: diary['comment']), + productNameController: TextEditingController(), + productQuantityController: TextEditingController(), + caloriesController: TextEditingController(), + proteinsController: TextEditingController(), + fatsController: TextEditingController(), + carbsController: TextEditingController(), + diaryId: diaryId, + diaryDate: diaryDate, + autocompleteList: [], + diaryEditModelObj: state.diaryEditModelObj?.copyWith( + mealList: fillMealList(), + portionList: fillPortions()))); + } } else { - // Если текущее состояние - начальное, создаем новое загруженное состояние - emit(DiaryEditLoadedState( - currentMeal: SelectionPopupModel( - id: 1, title: "Прием пищи 1", isSelected: true), - portionController: SelectionPopupModel( - id: 0, title: "порций", isSelected: true), - wakeupExpanded: true, - moodExpanded: true, - moderationExpanded: false, - token: token, - meals: diary['meals'], - portions: diary['meals'][0]['portions'], - photos: diary['meals'][0]['photos'], - wakeupController: toTime(diary['wakeup'] ?? "09:00"), - retireController: toTime(diary['retire'] ?? "23:00"), - mealTimeController: - toTime(diary['meals'][0]['time'] ?? "10:00"), - selectedSatiety: diary['meals'][0]['satiety'], - selectedMood: diary['meals'][0]['mood'], - commentController: - TextEditingController(text: diary['comment']), - productNameController: TextEditingController(), - productQuantityController: TextEditingController(), - caloriesController: TextEditingController(), - proteinsController: TextEditingController(), - fatsController: TextEditingController(), - carbsController: TextEditingController(), - diaryId: diaryId, - diaryDate: diaryDate, - autocompleteList: [], - diaryEditModelObj: state.diaryEditModelObj?.copyWith( - mealList: fillMealList(), - portionList: fillPortions()))); + emit(DiaryEditErrorState( + 'Ошибка при декодировании данных КБЖУ')); } } else { // Ошибка при декодировании JSON @@ -191,44 +218,65 @@ class DiaryEditBloc extends Bloc { if (diary is Map) { final String diaryDate = diary['date'] ?? DateTime.now().toString(); - // Продолжайте обработку данных дневника - // Если текущее состояние - начальное, создаем новое загруженное состояние - try { - await Future(() => emit(DiaryEditLoadedState( - currentMeal: SelectionPopupModel( - id: 1, title: "Прием пищи 1", isSelected: true), - portionController: SelectionPopupModel( - id: 0, title: "порций", isSelected: true), - wakeupExpanded: true, - moodExpanded: true, - moderationExpanded: false, - token: token, - meals: diary['meals'], - portions: diary['meals'][0]['portions'], - photos: diary['meals'][0]['photos'], - wakeupController: toTime(diary['wakeup'] ?? "09:00"), - retireController: toTime(diary['retire'] ?? "23:00"), - mealTimeController: - toTime(diary['meals'][0]['time'] ?? "10:00"), - selectedSatiety: diary['meals'][0]['satiety'], - selectedMood: diary['meals'][0]['mood'], - commentController: - TextEditingController(text: diary['comment']), - productNameController: TextEditingController(), - productQuantityController: TextEditingController(), - caloriesController: TextEditingController(), - proteinsController: TextEditingController(), - fatsController: TextEditingController(), - carbsController: TextEditingController(), - diaryId: diaryId, - diaryDate: diaryDate, - autocompleteList: [], - diaryEditModelObj: state.diaryEditModelObj?.copyWith( - mealList: fillMealList(), portionList: fillPortions())))); + final responseChart = await http.get( + Uri.parse(dotenv.env['SERVER_ROOT']! + + '/diary/$diaryId/dailyNutritionData/'), + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer $token', + }, + ); + if (responseChart.statusCode == 200) { + final recommendedChartValues = jsonDecode( + responseChart.body)['dailyNutritionRecommendation']; + final consumedChartValues = + jsonDecode(responseChart.body)['dailyNutritionIntake']; + try { + await Future(() => emit(DiaryEditLoadedState( + currentMeal: SelectionPopupModel( + id: 1, title: "Прием пищи 1", isSelected: true), + portionController: SelectionPopupModel( + id: 0, title: "порций", isSelected: true), + wakeupExpanded: true, + moodExpanded: true, + moderationExpanded: false, + token: token, + recommendedChartValues: recommendedChartValues.values + .map((value) => value as int) + .toList(), + consumedChartValues: consumedChartValues.values + .map((value) => value as int) + .toList(), + meals: diary['meals'], + portions: diary['meals'][0]['portions'], + photos: diary['meals'][0]['photos'], + wakeupController: toTime(diary['wakeup'] ?? "09:00"), + retireController: toTime(diary['retire'] ?? "23:00"), + mealTimeController: + toTime(diary['meals'][0]['time'] ?? "10:00"), + selectedSatiety: diary['meals'][0]['satiety'], + selectedMood: diary['meals'][0]['mood'], + commentController: + TextEditingController(text: diary['comment']), + productNameController: TextEditingController(), + productQuantityController: TextEditingController(), + caloriesController: TextEditingController(), + proteinsController: TextEditingController(), + fatsController: TextEditingController(), + carbsController: TextEditingController(), + diaryId: diaryId, + diaryDate: diaryDate, + autocompleteList: [], + diaryEditModelObj: state.diaryEditModelObj?.copyWith( + mealList: fillMealList(), + portionList: fillPortions())))); - print("Updated"); - } catch (e) { - print("Ошибка при создании нового состояния $e"); + print("Updated"); + } catch (e) { + print("Ошибка при создании нового состояния $e"); + } + } else { + emit(DiaryEditErrorState('Ошибка при декодировании данных КБЖУ')); } } else { emit(DiaryEditErrorState( diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_state.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_state.dart index 470b3268..58c6fd25 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_state.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_state.dart @@ -39,6 +39,8 @@ class DiaryEditLoadedState extends DiaryEditState { this.fatsController, this.proteinsController, this.carbsController, + required this.recommendedChartValues, + required this.consumedChartValues, required this.diaryId, required this.selectedSatiety, required this.moderationExpanded, @@ -53,6 +55,8 @@ class DiaryEditLoadedState extends DiaryEditState { List? portions; List? photos; List? autocompleteList; + List recommendedChartValues; + List consumedChartValues; SelectionPopupModel? currentMeal; SelectionPopupModel? portionController; TimeOfDay? wakeupController; @@ -79,6 +83,8 @@ class DiaryEditLoadedState extends DiaryEditState { meals, portions, photos, + recommendedChartValues, + consumedChartValues, autocompleteList, wakeupController, retireController, @@ -105,6 +111,8 @@ class DiaryEditLoadedState extends DiaryEditState { SelectionPopupModel? portionController, String? diaryDate, String? token, + List? recommendedChartValues, + List? consumedChartValues, List? meals, List? portions, List? photos, @@ -133,6 +141,9 @@ class DiaryEditLoadedState extends DiaryEditState { meals: meals ?? this.meals, autocompleteList: autocompleteList ?? this.autocompleteList, portions: portions ?? this.portions, + recommendedChartValues: + recommendedChartValues ?? this.recommendedChartValues, + consumedChartValues: consumedChartValues ?? this.consumedChartValues, wakeupController: wakeupController ?? this.wakeupController, retireController: retireController ?? this.retireController, mealTimeController: mealTimeController ?? this.mealTimeController, diff --git a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart index 52dffb50..e2bdbeee 100644 --- a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart +++ b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart @@ -79,7 +79,7 @@ class DiaryEditScreen extends StatelessWidget { SizedBox(height: 20.v), _buildMood(context, state), SizedBox(height: 30.v), - _buildNutritionChart(context), + _buildNutritionChart(context, state), SizedBox(height: 30.v), _buildComment(context, state), ], @@ -700,14 +700,10 @@ class DiaryEditScreen extends StatelessWidget { }; } - _buildNutritionChart(BuildContext context) { - final List recommendedValues = [ - 2000, - 70, - 50, - 300 - ]; // Рекомендуемые значения: калории, жиры, белки, углеводы - final List consumedValues = [1800, 60, 40, 250]; // + _buildNutritionChart(BuildContext context, DiaryEditLoadedState state) { + final List recommendedValues = state + .recommendedChartValues; // Рекомендуемые значения: калории, жиры, белки, углеводы + final List consumedValues = state.consumedChartValues; // return Container( margin: EdgeInsets.symmetric(horizontal: 16.h), padding: EdgeInsets.symmetric( @@ -1210,7 +1206,7 @@ class DiaryEditScreen extends StatelessWidget { } bool checkConsumedValues( - List recommendedValues, List consumedValues) { + List recommendedValues, List consumedValues) { for (int i = 0; i < recommendedValues.length; i++) { if (consumedValues[i] > recommendedValues[i]) { // Если хотя бы одно потребленное значение превышает рекомендованное diff --git a/lib/presentation/profile/my_profile_screen/bloc/my_profile_bloc.dart b/lib/presentation/profile/my_profile_screen/bloc/my_profile_bloc.dart index dad1ce9a..474e4705 100644 --- a/lib/presentation/profile/my_profile_screen/bloc/my_profile_bloc.dart +++ b/lib/presentation/profile/my_profile_screen/bloc/my_profile_bloc.dart @@ -4,7 +4,7 @@ import '/core/app_export.dart'; import 'package:eatvio_app/presentation/profile/my_profile_screen/models/my_profile_model.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; -import 'package:hive/hive.dart'; +//import 'package:hive/hive.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; part 'my_profile_event.dart'; diff --git a/lib/widgets/custom_expandable_list.dart b/lib/widgets/custom_expandable_list.dart index 786ed6be..bf299768 100644 --- a/lib/widgets/custom_expandable_list.dart +++ b/lib/widgets/custom_expandable_list.dart @@ -81,7 +81,7 @@ class _ExpandableListState extends State { } _buildForm(BuildContext context, MyProfileLoadedState state) { - List cities = [ + /*List cities = [ 'Москва', 'Санкт-Петербург', 'Новосибирск', @@ -115,7 +115,7 @@ class _ExpandableListState extends State { ]; List countries = [ 'Россия', - ]; + ];*/ final digitsOnly = FilteringTextInputFormatter.digitsOnly; return Column(children: [ TextField( diff --git a/test/diary_test.dart b/test/diary_test.dart index 722c457d..b539eb33 100644 --- a/test/diary_test.dart +++ b/test/diary_test.dart @@ -27,6 +27,8 @@ void main() { portions: [], wakeupExpanded: false, moderationExpanded: false, + recommendedChartValues: [10, 10, 10, 10], + consumedChartValues: [1, 2, 3, 4], moodExpanded: false); await tester.pumpWidget( From c5c7033ada003e79e1a045deda03d04ac800d2cf Mon Sep 17 00:00:00 2001 From: maxxkim Date: Thu, 4 Apr 2024 12:23:31 +0300 Subject: [PATCH 5/5] fix(profile): Error is not server related (Ivalid data in mySQL database - garbage seeded in city and country fields) --- .../profile/my_profile_screen/my_settings_screen.dart | 4 ++-- lib/widgets/custom_expandable_list.dart | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/presentation/profile/my_profile_screen/my_settings_screen.dart b/lib/presentation/profile/my_profile_screen/my_settings_screen.dart index 923597a6..b514939b 100644 --- a/lib/presentation/profile/my_profile_screen/my_settings_screen.dart +++ b/lib/presentation/profile/my_profile_screen/my_settings_screen.dart @@ -51,8 +51,8 @@ class MySettingsScreen extends StatelessWidget { padding: const EdgeInsets.all(16.0), child: ListView( children: [ - //SectionTitle('Язык'), - //LanguageDropdown(), + SectionTitle('Язык'), + LanguageDropdown(), SectionTitle('Уведомления'), NotificationSwitch('Уведомление об обновлениях'), NotificationSwitch('Напоминания о заполнении'), diff --git a/lib/widgets/custom_expandable_list.dart b/lib/widgets/custom_expandable_list.dart index bf299768..f20ac19e 100644 --- a/lib/widgets/custom_expandable_list.dart +++ b/lib/widgets/custom_expandable_list.dart @@ -81,7 +81,7 @@ class _ExpandableListState extends State { } _buildForm(BuildContext context, MyProfileLoadedState state) { - /*List cities = [ + List cities = [ 'Москва', 'Санкт-Петербург', 'Новосибирск', @@ -115,7 +115,7 @@ class _ExpandableListState extends State { ]; List countries = [ 'Россия', - ];*/ + ]; final digitsOnly = FilteringTextInputFormatter.digitsOnly; return Column(children: [ TextField( @@ -130,7 +130,7 @@ class _ExpandableListState extends State { decoration: InputDecoration(labelText: 'date_of_birth'.tr), controller: state.dateFormController, onTap: inputTime(context, state)), - /*DropdownButtonFormField( + DropdownButtonFormField( value: state.selectedCountry, hint: Text(state.selectedCountry ?? "Не выбрано"), onChanged: setCountry(state), @@ -153,7 +153,7 @@ class _ExpandableListState extends State { ); }).toList(), decoration: InputDecoration(labelText: 'city_of_living'.tr), - ),*/ + ), TextField( controller: state.weightFormController, decoration: InputDecoration(labelText: 'weight_measurements'.tr),