From 8d3ae151125ad3fcf1a307ca31bfdf96ea783e84 Mon Sep 17 00:00:00 2001 From: misha Date: Thu, 18 Sep 2025 18:47:07 +0300 Subject: [PATCH 1/5] feat(diary): added v2 methods for diary --- ios/Runner.xcodeproj/project.pbxproj | 3 + lib/core/utils/date_time_utils.dart | 11 +++ .../diary/entities/diary_day_entity.dart | 22 +++++ .../diary_future_diet_day_entity.dart | 18 ++++ .../diary/models/create_day_model.dart | 11 +++ .../diary/models/diary_day_model.dart | 55 +++++++---- lib/features/diary/models/get_day_model.dart | 11 +++ .../diary/presentation/bloc/diary_cubit.dart | 93 ++++++++++++------- .../diary/presentation/bloc/diary_state.dart | 15 ++- .../presentation/pages/diary_screen.dart | 80 +++++----------- .../widgets/finish_day_button_widget.dart | 4 +- .../widgets/photo_gallery_widget.dart | 4 +- .../diary/repositories/diary_repository.dart | 26 ++++-- .../diary/services/diary_service.dart | 9 +- .../presentation/pages/profile_screen.dart | 1 + lib/generated/l10n.dart | 7 +- 16 files changed, 237 insertions(+), 133 deletions(-) create mode 100644 lib/features/diary/entities/diary_day_entity.dart create mode 100644 lib/features/diary/entities/diary_future_diet_day_entity.dart create mode 100644 lib/features/diary/models/create_day_model.dart create mode 100644 lib/features/diary/models/get_day_model.dart diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 198e6f7b..668075b4 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -410,6 +410,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.eatvioapp.app; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.eatvioapp.app 1747050044"; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; @@ -560,6 +561,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.eatvioapp.app; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.eatvioapp.app 1747050044"; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -598,6 +600,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.eatvioapp.app; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.eatvioapp.app 1747050044"; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; diff --git a/lib/core/utils/date_time_utils.dart b/lib/core/utils/date_time_utils.dart index 701fa80e..9b3085c1 100644 --- a/lib/core/utils/date_time_utils.dart +++ b/lib/core/utils/date_time_utils.dart @@ -46,6 +46,17 @@ extension DateTimeExtension on DateTime { final now = DateTime.now(); return now.year == localDate.year && now.month == localDate.month && now.day == localDate.day; } + + String toISO8601WithTimeZoneOffset() { + final formatter = DateFormat("yyyy-MM-ddTHH:mm:ss"); + final formatted = formatter.format(this); + final offset = timeZoneOffset; + final hours = offset.inHours.abs().toString().padLeft(2, '0'); + final minutes = (offset.inMinutes.abs() % 60).toString().padLeft(2, '0'); + final sign = offset.isNegative ? '-' : '+'; + + return "$formatted$sign$hours:$minutes"; + } } String calculateDifference(DateTime dateTime, [String? format]) { diff --git a/lib/features/diary/entities/diary_day_entity.dart b/lib/features/diary/entities/diary_day_entity.dart new file mode 100644 index 00000000..65f45570 --- /dev/null +++ b/lib/features/diary/entities/diary_day_entity.dart @@ -0,0 +1,22 @@ +import 'package:eatvio_app/features/diary/models/diary_day_model.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'diary_day_entity.freezed.dart'; + +@freezed +abstract class DiaryDayEntity with _$DiaryDayEntity { + factory DiaryDayEntity({ + @JsonKey(name: "id") required int id, + @JsonKey(name: "date") required String date, + @JsonKey(name: "wakeup") String? wakeup, + @JsonKey(name: "retire") String? retire, + @JsonKey(name: "closed") required int closed, + @JsonKey(name: "comment") required String comment, + @JsonKey(name: "state") required TypeOfDiaryModel typeOfDiary, + @JsonKey(name: "meals") required List meals, + @JsonKey(name: "chosen_plan_id") required int? chosenPlanId, + @JsonKey(name: "day_of_chosen_diet") required int? dayOfChosenDiet, + @JsonKey(name: "chosen_diet", fromJson: parseDiet) required DiaryDietModel? diet, + }) = _DiaryDayEntity; + +} diff --git a/lib/features/diary/entities/diary_future_diet_day_entity.dart b/lib/features/diary/entities/diary_future_diet_day_entity.dart new file mode 100644 index 00000000..4247cecf --- /dev/null +++ b/lib/features/diary/entities/diary_future_diet_day_entity.dart @@ -0,0 +1,18 @@ +import 'package:eatvio_app/features/diary/models/diary_day_model.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'diary_future_diet_day_entity.freezed.dart'; + + + +@freezed +abstract class DiaryFutureDietDayEntity with _$DiaryFutureDietDayEntity { + const factory DiaryFutureDietDayEntity({ + required String date, + required TypeOfDiaryModel typeOfDiary, + required List meals, + required DiaryDietModel? diet, + required int? dayOfChosenDiet, + }) = _DiaryFutureDietDayEntity; + +} diff --git a/lib/features/diary/models/create_day_model.dart b/lib/features/diary/models/create_day_model.dart new file mode 100644 index 00000000..9d3eabbd --- /dev/null +++ b/lib/features/diary/models/create_day_model.dart @@ -0,0 +1,11 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'create_day_model.freezed.dart'; +part 'create_day_model.g.dart'; + +@freezed +abstract class CreateDayModel with _$CreateDayModel { + factory CreateDayModel({required String day}) = _CreateDayModel; + + factory CreateDayModel.fromJson(Map json) => _$CreateDayModelFromJson(json); +} diff --git a/lib/features/diary/models/diary_day_model.dart b/lib/features/diary/models/diary_day_model.dart index e1ad4572..19099ded 100644 --- a/lib/features/diary/models/diary_day_model.dart +++ b/lib/features/diary/models/diary_day_model.dart @@ -1,4 +1,6 @@ import 'package:eatvio_app/features/consultations/models/consultation_model.dart'; +import 'package:eatvio_app/features/diary/entities/diary_day_entity.dart'; +import 'package:eatvio_app/features/diary/entities/diary_future_diet_day_entity.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'diary_day_model.freezed.dart'; @@ -30,7 +32,7 @@ abstract class DiaryDayWrapperModel with _$DiaryDayWrapperModel { @freezed abstract class DiaryDayModel with _$DiaryDayModel { const factory DiaryDayModel({ - @JsonKey(name: "id") required int id, + @JsonKey(name: "id") required int? id, @JsonKey(name: "date") required String date, @JsonKey(name: "wakeup") String? wakeup, @JsonKey(name: "retire") String? retire, @@ -40,26 +42,43 @@ abstract class DiaryDayModel with _$DiaryDayModel { @JsonKey(name: "meals") required List meals, @JsonKey(name: "chosen_plan_id") required int? chosenPlanId, @JsonKey(name: "day_of_chosen_diet") required int? dayOfChosenDiet, - @JsonKey(name: "chosen_diet", fromJson: _parseDiet) required DiaryDietModel? diet, + @JsonKey(name: "chosen_diet", fromJson: parseDiet) required DiaryDietModel? diet, }) = _DiaryDayModel; - + const DiaryDayModel._(); factory DiaryDayModel.fromJson(Map json) => _$DiaryDayModelFromJson(json); + + DiaryDayEntity? toEntity() { + if (id == null) { + return null; + } + return DiaryDayEntity( + id: id!, + date: date, + closed: closed, + comment: comment, + typeOfDiary: typeOfDiary, + meals: meals, + chosenPlanId: chosenPlanId, + dayOfChosenDiet: dayOfChosenDiet, + diet: diet, + ); + } + + DiaryFutureDietDayEntity toDiaryFutureDayEntity() { + + return DiaryFutureDietDayEntity( + date: date, + typeOfDiary: typeOfDiary, + meals: meals, + dayOfChosenDiet: dayOfChosenDiet, + diet: diet, + ); + } } -@freezed -abstract class DiaryFutureDietDayModel with _$DiaryFutureDietDayModel { - const factory DiaryFutureDietDayModel({ - @JsonKey(name: "date") required String date, - @JsonKey(name: "state", fromJson: _parseDayTypeForFutureDay) required TypeOfDiaryModel typeOfDiary, - @JsonKey(name: "meals") required List meals, - @JsonKey(name: "chosen_diet", fromJson: _parseDiet) required DiaryDietModel? diet, - @JsonKey(name: "day_of_chosen_diet") required int? dayOfChosenDiet, - }) = _DiaryFutureDietDayModel; - factory DiaryFutureDietDayModel.fromJson(Map json) => _$DiaryFutureDietDayModelFromJson(json); -} -DiaryDietModel? _parseDiet(dynamic json) { +DiaryDietModel? parseDiet(dynamic json) { if (json == null) return null; return DiaryDietModel.fromJson(json['diet']); } @@ -71,10 +90,6 @@ abstract class DiaryDietModel with _$DiaryDietModel { factory DiaryDietModel.fromJson(Map json) => _$DiaryDietModelFromJson(json); } -TypeOfDiaryModel _parseDayTypeForFutureDay(dynamic json) { - return TypeOfDiaryModel(hasChosenDiet: json['has_chosen_diet'] as bool, hasChosenPlan: json['has_chosen_plan'] as bool, diaryState: DiaryStateEnum.init); -} - @freezed abstract class MealModel with _$MealModel { const factory MealModel({ @@ -141,7 +156,7 @@ abstract class TypeOfDiaryModel with _$TypeOfDiaryModel { const factory TypeOfDiaryModel({ @JsonKey(name: "has_chosen_diet") required bool hasChosenDiet, @JsonKey(name: "has_chosen_plan") required bool hasChosenPlan, - @JsonKey(name: "last_state") required DiaryStateEnum diaryState, + @JsonKey(name: "last_state") required DiaryStateEnum? diaryState, }) = _TypeOfDiaryModel; factory TypeOfDiaryModel.fromJson(Map json) => _$TypeOfDiaryModelFromJson(json); diff --git a/lib/features/diary/models/get_day_model.dart b/lib/features/diary/models/get_day_model.dart new file mode 100644 index 00000000..bf9d285d --- /dev/null +++ b/lib/features/diary/models/get_day_model.dart @@ -0,0 +1,11 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'get_day_model.freezed.dart'; +part 'get_day_model.g.dart'; + +@freezed +abstract class GetDayModel with _$GetDayModel { + factory GetDayModel({required String day}) = _GetDayModel; + + factory GetDayModel.fromJson(Map json) => _$GetDayModelFromJson(json); +} diff --git a/lib/features/diary/presentation/bloc/diary_cubit.dart b/lib/features/diary/presentation/bloc/diary_cubit.dart index 6e6f8891..644837ac 100644 --- a/lib/features/diary/presentation/bloc/diary_cubit.dart +++ b/lib/features/diary/presentation/bloc/diary_cubit.dart @@ -1,10 +1,13 @@ import 'dart:developer'; import 'dart:io'; +import 'package:dio/dio.dart'; import 'package:eatvio_app/core/image_compressing/image_compress_utility.dart'; import 'package:eatvio_app/core/utils/date_time_utils.dart'; import 'package:eatvio_app/features/chat/repositories/chat_repository.dart'; import 'package:eatvio_app/features/consultations/models/consultation_model.dart'; +import 'package:eatvio_app/features/diary/entities/diary_day_entity.dart'; +import 'package:eatvio_app/features/diary/entities/diary_future_diet_day_entity.dart'; import 'package:eatvio_app/features/diary/models/consultant_review_model.dart'; import 'package:eatvio_app/features/diary/models/diary_day_model.dart'; import 'package:eatvio_app/features/diary/models/nutrition_model.dart'; @@ -39,20 +42,50 @@ class DiaryCubit extends Cubit { today = DateTime.now(); selectedDay = today; diaryRepository.forceFetchStream.listen((_) { - fetchDiary(true, diaryId); + fetchDiaryV2(needLoading: true, diaryId: diaryId); }); } String comment = ''; - Future setSelectedDay(DateTime day, {bool? forDietOnly}) async { + Future setSelectedDay(DateTime day, {bool? forDietOnly}) async { selectedDay = day; if (forDietOnly ?? false) { - final result = await fetchDiaryForDietOnly(); + final result = await fetchDiaryV2(); return result; } - await fetchDiary(true); - return null; + await fetchDiaryV2(needLoading: true); + return true; + } + + Future fetchDiaryV2({bool needLoading = false, int? diaryId, int? currentDay}) async { + final (diaryDay, error) = await qwe(); + if (error != null) { + if (error == DiaryFetchingErrors.canNotCreateFutureDays) { + return false; + } + emit(DiaryState.error(errorMessage: error.toString())); + } + + if (diaryDay != null) { + final diaryEntity = diaryDay.toEntity(); + if (diaryEntity != null) { + setDiary(diaryDay: diaryEntity); + return true; + } + setDiaryForDietOnly(diaryDay.toDiaryFutureDayEntity()); + } + return true; + } + + Future<(DiaryDayModel?, DiaryFetchingErrors?)> qwe() async { + try { + final diaryDay = await diaryRepository.getDiaryDayV2(day: selectedDay.toISO8601WithTimeZoneOffset()); + } on DioException catch (e) { + + } + + return (null, null); } void setSelectedMeal(int meal) { @@ -65,9 +98,7 @@ class DiaryCubit extends Cubit { } } - Future fetchDiaryForDietOnly() async { - final stringDate = selectedDay.format('yyyy-MM-dd'); - final diaryDay = await diaryRepository.getDiaryByDateForDietOnly(stringDate); + Future setDiaryForDietOnly(DiaryFutureDietDayEntity diaryDay) async { if (!diaryDay.typeOfDiary.hasChosenDiet) { return false; } @@ -146,13 +177,9 @@ class DiaryCubit extends Cubit { return false; } - Future fetchDiary([bool needLoading = false, int? diaryId, int? currentDay]) async { + Future setDiary({int? diaryId, int? currentDay, required DiaryDayEntity diaryDay}) async { this.diaryId ??= diaryId; final isConsultantView = this.diaryId != null; - if (needLoading) { - emit(const DiaryState.loading()); - selectedMeal = 1; - } try { final DiaryDayModel diaryDay; bool isMoodEnabled = false; @@ -174,14 +201,14 @@ class DiaryCubit extends Cubit { final chosenPlanModel = await chatRepository.getChosenPlan(id: diaryDay.chosenPlanId!); if (!isConsultantView && (diaryDay.typeOfDiary.diaryState == DiaryStateEnum.lastDayCommented || diaryDay.typeOfDiary.diaryState == DiaryStateEnum.commented)) { - await diaryRepository.viewCommentOfDiaryDayByConsultant(diaryId: diaryDay.id); + await diaryRepository.viewCommentOfDiaryDayByConsultant(diaryId: diaryDay.id!); } - consultantReview = await diaryRepository.getDiaryComments(planId: diaryDay.chosenPlanId!, diaryId: diaryDay.id); + consultantReview = await diaryRepository.getDiaryComments(planId: diaryDay.chosenPlanId!, diaryId: diaryDay.id!); planDuration = chosenPlanModel.plan.duration; planName = chosenPlanModel.plan.name; currentPlanDay = consultantReview.currentPlanDay; } - final nutrition = await getNutrition(diaryDay.id); + final nutrition = await getNutrition(diaryDay.id!); final isDiaryFinished = diaryDay.typeOfDiary.diaryState == DiaryStateEnum.finished || diaryDay.typeOfDiary.diaryState == DiaryStateEnum.lastDayFinished; @@ -191,7 +218,7 @@ class DiaryCubit extends Cubit { diaryDay.typeOfDiary.diaryState == DiaryStateEnum.reviewedByUser; emit( DiaryState.loaded( - diary: diaryDay, + diary: diaryDay.toEntity()!, nutrition: nutrition, selectedDay: selectedDay, selectedMeal: selectedMeal, @@ -214,7 +241,7 @@ class DiaryCubit extends Cubit { Future finishDiaryDay({required int diaryId, required String wakeUp, required String retire}) async { await diaryRepository.finishDiaryDay(diaryId: diaryId, wakeUp: wakeUp, retire: retire, comment: comment.isEmpty ? null : comment); - await fetchDiary(); + await fetchDiaryV2(); } Future getNutrition(int index) async { @@ -238,7 +265,7 @@ class DiaryCubit extends Cubit { quantity: quantity, productNutritionalValueId: productNutritionalValueId, ); - await fetchDiary(); + await fetchDiaryV2(); } Future updateProductInMeal({ @@ -272,27 +299,27 @@ class DiaryCubit extends Cubit { portionState: portionState, ); } - await fetchDiary(); + await fetchDiaryV2(); } Future markEaten({required int diaryId, required int mealId, required int portionId}) async { await diaryRepository.markEaten(diaryId: diaryId, mealId: mealId, portionId: portionId); - await fetchDiary(); + await fetchDiaryV2(); } Future unmarkEaten({required int diaryId, required int mealId, required int portionId}) async { await diaryRepository.unmarkEaten(diaryId: diaryId, mealId: mealId, portionId: portionId); - await fetchDiary(); + await fetchDiaryV2(); } Future restore({required int diaryId, required int mealId, required int portionId}) async { await diaryRepository.restore(diaryId: diaryId, mealId: mealId, portionId: portionId); - await fetchDiary(); + await fetchDiaryV2(); } Future deleteProductFromMeal({required int diaryId, required int mealId, required int portionId}) async { await diaryRepository.deleteProductFromMeal(diaryId: diaryId, mealId: mealId, portionId: portionId); - await fetchDiary(); + await fetchDiaryV2(); } Future> getGlossaryListByQuery(String query) async { @@ -301,12 +328,12 @@ class DiaryCubit extends Cubit { Future uploadPhotos({required List files, required int diaryId}) async { await diaryRepository.uploadPhotos(files: await ImageCompressUtility.compressFilesList(files), diaryId: diaryId, mealId: selectedMeal); - await fetchDiary(); + await fetchDiaryV2(); } Future deletePhoto({required DiaryPhotoModel photo, required int diaryId}) async { await diaryRepository.deletePhoto(photo: photo, diaryId: diaryId, mealId: selectedMeal); - await fetchDiary(); + await fetchDiaryV2(); } Future sendProductToModeration({ @@ -326,30 +353,34 @@ class DiaryCubit extends Cubit { Future fillTime({required int diaryId, required String time}) async { await diaryRepository.fillTime(diaryId: diaryId, mealId: selectedMeal, time: time); - await fetchDiary(); + await fetchDiaryV2(); } Future fillWakeup({required int diaryId, required String time}) async { await diaryRepository.fillWakeup(diaryId: diaryId, time: time); - await fetchDiary(); + await fetchDiaryV2(); } Future fillRetire({required int diaryId, required String time}) async { await diaryRepository.fillRetire(diaryId: diaryId, time: time); - await fetchDiary(); + await fetchDiaryV2(); } Future fillSatiety({required int diaryId, required int satiety}) async { await diaryRepository.fillSatiety(diaryId: diaryId, mealId: selectedMeal, satiety: satiety); - await fetchDiary(); + await fetchDiaryV2(); } Future fillMood({required int diaryId, required int mood}) async { await diaryRepository.fillMood(diaryId: diaryId, mealId: selectedMeal, mood: mood); - await fetchDiary(); + await fetchDiaryV2(); } void fillComment(String comment) { this.comment = comment; } + + } + +enum DiaryFetchingErrors { canNotCreateFutureDays, dayAlreadyExists } diff --git a/lib/features/diary/presentation/bloc/diary_state.dart b/lib/features/diary/presentation/bloc/diary_state.dart index 4779e2ea..771ebb31 100644 --- a/lib/features/diary/presentation/bloc/diary_state.dart +++ b/lib/features/diary/presentation/bloc/diary_state.dart @@ -1,3 +1,5 @@ +import 'package:eatvio_app/features/diary/entities/diary_day_entity.dart'; +import 'package:eatvio_app/features/diary/entities/diary_future_diet_day_entity.dart'; import 'package:eatvio_app/features/diary/models/consultant_review_model.dart'; import 'package:eatvio_app/features/diary/models/diary_day_model.dart'; import 'package:eatvio_app/features/diary/models/nutrition_model.dart'; @@ -11,12 +13,10 @@ abstract class DiaryState with _$DiaryState { const factory DiaryState.loading() = DiaryStateLoading; - const factory DiaryState.error({ - required String errorMessage, - }) = DiaryStateError; + const factory DiaryState.error({required String errorMessage}) = DiaryStateError; const factory DiaryState.loaded({ - required DiaryDayModel diary, + required DiaryDayEntity diary, required NutritionDataModel nutrition, required DateTime selectedDay, required int selectedMeal, @@ -32,9 +32,6 @@ abstract class DiaryState with _$DiaryState { @Default(false) bool isLoadingAddingProductInMeal, }) = DiaryStateLoaded; - const factory DiaryState.loadedTomorrowWithDiet({ - required DiaryFutureDietDayModel diary, - required DateTime selectedDay, - required int selectedMeal, - }) = DiaryStateLoadedTomorrowWithDiet; + const factory DiaryState.loadedTomorrowWithDiet({required DiaryFutureDietDayEntity diary, required DateTime selectedDay, required int selectedMeal}) = + DiaryStateLoadedTomorrowWithDiet; } diff --git a/lib/features/diary/presentation/pages/diary_screen.dart b/lib/features/diary/presentation/pages/diary_screen.dart index fb1987ef..4ec74e16 100644 --- a/lib/features/diary/presentation/pages/diary_screen.dart +++ b/lib/features/diary/presentation/pages/diary_screen.dart @@ -35,19 +35,12 @@ class DiaryScreen extends StatelessWidget { class UserDiaryScreen extends StatelessWidget { static const path = '/user-diary-screen'; static const name = 'userDiaryScreen'; - const UserDiaryScreen({ - super.key, - required this.diaryId, - required this.currentPlanDay, - }); + const UserDiaryScreen({super.key, required this.diaryId, required this.currentPlanDay}); final int diaryId; final int currentPlanDay; @override Widget build(BuildContext context) { - return DiaryScreenContent( - diaryId: diaryId, - currentPlanDay: currentPlanDay, - ); + return DiaryScreenContent(diaryId: diaryId, currentPlanDay: currentPlanDay); } } @@ -60,12 +53,8 @@ class DiaryScreenContent extends StatelessWidget { final s = S.of(context); return MultiBlocProvider( providers: [ - BlocProvider( - create: (BuildContext context) => sl()..fetchDiary(true, diaryId, currentPlanDay), - ), - BlocProvider( - create: (context) => sl(), - ), + BlocProvider(create: (BuildContext context) => sl()..fetchDiaryV2(needLoading: true, diaryId: diaryId, currentDay: currentPlanDay)), + BlocProvider(create: (context) => sl()), ], child: BlocBuilder( builder: (BuildContext context, DiaryState state) { @@ -73,17 +62,13 @@ class DiaryScreenContent extends StatelessWidget { log(state.diary.id.toString()); } if (state is DiaryStateError) { - return Scaffold( - body: DataErrorWidget(onReload: () => context.read().fetchDiary(false, diaryId)), - ); + return Scaffold(body: DataErrorWidget(onReload: () => context.read().fetchDiaryV2(needLoading: false, diaryId: diaryId))); } return Scaffold( backgroundColor: Colors.grey.shade200, appBar: diaryId == null - ? AppBar( - toolbarHeight: 0, - ) + ? AppBar(toolbarHeight: 0) : AppBar( title: Text( state is DiaryStateLoaded ? DateTime.parse(state.diary.date).toLocal().format('d MMMM') : '', @@ -97,12 +82,7 @@ class DiaryScreenContent extends StatelessWidget { child: Column( children: [ if (diaryId == null) const CalendarWidget(), - if (state is DiaryStateLoading) ...[ - const SizedBox( - height: 60, - ), - const Loader() - ], + if (state is DiaryStateLoading) ...[const SizedBox(height: 60), const Loader()], if (state is DiaryStateLoaded) WakeupAndRetireWidget( isEnabled: state.diary.typeOfDiary.hasChosenPlan || state.isConsultantView || state.isWakeUpAndRetireEnabled, @@ -114,40 +94,31 @@ class DiaryScreenContent extends StatelessWidget { showMood: state.diary.typeOfDiary.hasChosenPlan || state.isConsultantView || state.isMoodEnabled, showAddButton: !state.isConsultantView && !state.isDiaryFinished && !state.isDiaryCommented, ), - if (state is DiaryStateLoadedTomorrowWithDiet) - const MealWidget( - showMood: false, - showAddButton: false, - ), + if (state is DiaryStateLoadedTomorrowWithDiet) const MealWidget(showMood: false, showAddButton: false), if (state is DiaryStateLoaded) const CaloriesChartWidget(), const SizedBox(height: 12), - Builder(builder: (context) { - if (state is DiaryStateLoaded && state.diary.typeOfDiary.hasChosenPlan) { - if (state.diary.comment.isNotEmpty) { - return CommentForConsultantWidget( - comment: state.diary.comment, - ); + Builder( + builder: (context) { + if (state is DiaryStateLoaded && state.diary.typeOfDiary.hasChosenPlan) { + if (state.diary.comment.isNotEmpty) { + return CommentForConsultantWidget(comment: state.diary.comment); + } + if (state.isDiaryCommented || state.isDiaryFinished) { + return const SizedBox.shrink(); + } + return const CommentForConsultantWidget(); } - if (state.isDiaryCommented || state.isDiaryFinished) { - return const SizedBox.shrink(); - } - return const CommentForConsultantWidget(); - } - return const SizedBox.shrink(); - }), + return const SizedBox.shrink(); + }, + ), if (state is DiaryStateLoaded && !state.isConsultantView && !state.isDiaryFinished && !state.isDiaryCommented) Padding( padding: const EdgeInsets.only(top: 12), - child: FinishDayButtonWidget( - diaryDay: state.diary, - ), + child: FinishDayButtonWidget(diaryDay: state.diary), ), if (state is DiaryStateLoaded && state.isConsultantView && !state.isDiaryCommented) ...[ const SizedBox(height: 16), - const MainBackgroundBouble( - padding: EdgeInsets.all(16), - child: DayCommentWidget(), - ) + const MainBackgroundBouble(padding: EdgeInsets.all(16), child: DayCommentWidget()), ], if (state is DiaryStateLoaded && state.consultantReview?.consultantComments.dayComment != null) ...[ const SizedBox(height: 12), @@ -155,10 +126,7 @@ class DiaryScreenContent extends StatelessWidget { padding: const EdgeInsets.all(16), child: Column( children: [ - Text( - s.dayComment, - style: TextStyles.textLSemibold.copyWith(color: appTheme.black), - ), + Text(s.dayComment, style: TextStyles.textLSemibold.copyWith(color: appTheme.black)), const SizedBox(height: 12), CommentContainer(comment: state.consultantReview?.consultantComments.dayComment ?? ''), ], diff --git a/lib/features/diary/presentation/widgets/finish_day_button_widget.dart b/lib/features/diary/presentation/widgets/finish_day_button_widget.dart index 042c418c..b3f170ec 100644 --- a/lib/features/diary/presentation/widgets/finish_day_button_widget.dart +++ b/lib/features/diary/presentation/widgets/finish_day_button_widget.dart @@ -1,11 +1,11 @@ -import 'package:eatvio_app/features/diary/models/diary_day_model.dart'; +import 'package:eatvio_app/features/diary/entities/diary_day_entity.dart'; import 'package:eatvio_app/features/diary/presentation/bloc/diary_cubit.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class FinishDayButtonWidget extends StatefulWidget { - final DiaryDayModel diaryDay; + final DiaryDayEntity diaryDay; const FinishDayButtonWidget({super.key, required this.diaryDay}); diff --git a/lib/features/diary/presentation/widgets/photo_gallery_widget.dart b/lib/features/diary/presentation/widgets/photo_gallery_widget.dart index 352b6519..a058ba61 100644 --- a/lib/features/diary/presentation/widgets/photo_gallery_widget.dart +++ b/lib/features/diary/presentation/widgets/photo_gallery_widget.dart @@ -5,7 +5,7 @@ import 'package:eatvio_app/core/app_router.dart'; import 'package:eatvio_app/core/const.dart'; import 'package:eatvio_app/core/permission_handler/permission_handler.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; -import 'package:eatvio_app/features/diary/models/diary_day_model.dart'; +import 'package:eatvio_app/features/diary/entities/diary_day_entity.dart'; import 'package:eatvio_app/features/diary/presentation/bloc/diary_cubit.dart'; import 'package:eatvio_app/features/diary/presentation/bloc/diary_state.dart'; import 'package:eatvio_app/generated/l10n.dart'; @@ -34,7 +34,7 @@ class _PhotoGalleryWidgetState extends State { diaryCubit = context.read(); } - void showImagePicker(DiaryDayModel diaryDay) { + void showImagePicker(DiaryDayEntity diaryDay) { showCupertinoModalPopup( context: context, builder: (context) { diff --git a/lib/features/diary/repositories/diary_repository.dart b/lib/features/diary/repositories/diary_repository.dart index 0165ad7f..d385ed75 100644 --- a/lib/features/diary/repositories/diary_repository.dart +++ b/lib/features/diary/repositories/diary_repository.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:io'; import 'package:eatvio_app/features/diary/models/consultant_comment_model.dart'; import 'package:eatvio_app/features/diary/models/consultant_review_model.dart'; +import 'package:eatvio_app/features/diary/models/create_day_model.dart'; import 'package:eatvio_app/features/diary/models/diary_day_model.dart'; import 'package:eatvio_app/features/diary/models/finish_diary_day_model.dart'; import 'package:eatvio_app/features/diary/models/nutrition_model.dart'; @@ -69,14 +70,6 @@ class DiaryRepository { } } - Future getDiaryByDateForDietOnly(String date) async { - try { - return (await diaryService.getDiaryIndexByDateForDietOnly(date: date)).last; - } catch (e) { - rethrow; - } - } - Future> getDiaryIndexByDate(String date) async { return (await diaryService.getDiaryIndexByDate(date: date)); } @@ -254,4 +247,21 @@ class DiaryRepository { rethrow; } } + + Future getDiaryDayV2({required String day}) async { + try { + return await diaryService.getDiaryDayV2(day: day); + } catch (e) { + rethrow; + } + } + + Future createDiaryDay({required String day}) async { + try { + await diaryService.createDay(body: CreateDayModel(day: day)); + await getDiaryByDate(day); + } catch (e) { + rethrow; + } + } } diff --git a/lib/features/diary/services/diary_service.dart b/lib/features/diary/services/diary_service.dart index 8cba6f33..985fb885 100644 --- a/lib/features/diary/services/diary_service.dart +++ b/lib/features/diary/services/diary_service.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:dio/dio.dart'; import 'package:eatvio_app/features/diary/models/consultant_comment_model.dart'; import 'package:eatvio_app/features/diary/models/consultant_review_model.dart'; +import 'package:eatvio_app/features/diary/models/create_day_model.dart'; import 'package:eatvio_app/features/diary/models/diary_day_model.dart'; import 'package:eatvio_app/features/diary/models/finish_diary_day_model.dart'; import 'package:eatvio_app/features/diary/models/nutrition_model.dart'; @@ -17,8 +18,6 @@ abstract class DiaryService { @GET('/api/diary/index/{date}') Future> getDiaryIndexByDate({@Path('date') required String date}); - @GET('/api/diary/index/{date}') - Future> getDiaryIndexByDateForDietOnly({@Path('date') required String date}); @GET('/api/diary/{diary}/show') Future getDiaryDay({@Path('diary') required int diary}); @@ -103,4 +102,10 @@ abstract class DiaryService { @GET('/api/glossaries/index') Future getGlossariesIndex({@Queries() Map? filters}); + + @POST('/api/v2/diary/create/day') + Future createDay({@Body() required CreateDayModel body}); + + @GET('/api/v2/diary/index/{day?}') + Future getDiaryDayV2({@Query('day') required String day}); } diff --git a/lib/features/profile/presentation/pages/profile_screen.dart b/lib/features/profile/presentation/pages/profile_screen.dart index cc8f7245..0167fce9 100644 --- a/lib/features/profile/presentation/pages/profile_screen.dart +++ b/lib/features/profile/presentation/pages/profile_screen.dart @@ -110,6 +110,7 @@ class _ProfileScreenState extends State { Text( 'Пользователь ограничил доступ к своей странице', textAlign: TextAlign.center, + style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500, color: Colors.grey[600]), ), ], diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index 85f74918..6144d39c 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -28,9 +28,10 @@ class S { static const AppLocalizationDelegate delegate = AppLocalizationDelegate(); static Future load(Locale locale) { - final name = (locale.countryCode?.isEmpty ?? false) - ? locale.languageCode - : locale.toString(); + final name = + (locale.countryCode?.isEmpty ?? false) + ? locale.languageCode + : locale.toString(); final localeName = Intl.canonicalizedLocale(name); return initializeMessages(localeName).then((_) { Intl.defaultLocale = localeName; From a8994eecf4a2aa8f90e77a1d6e71b291c74df8aa Mon Sep 17 00:00:00 2001 From: misha Date: Mon, 22 Sep 2025 10:52:29 +0300 Subject: [PATCH 2/5] feat(diary): fixed bugs fod diary with v2 methods --- .../diary/models/diary_day_model.dart | 13 +- .../diary/presentation/bloc/diary_cubit.dart | 120 ++++++++++-------- .../diary/presentation/bloc/diary_state.dart | 1 - .../presentation/pages/diary_screen.dart | 2 +- .../presentation/widgets/calendar_widget.dart | 75 +++-------- .../presentation/pages/profile_screen.dart | 1 - 6 files changed, 92 insertions(+), 120 deletions(-) diff --git a/lib/features/diary/models/diary_day_model.dart b/lib/features/diary/models/diary_day_model.dart index 19099ded..c602111f 100644 --- a/lib/features/diary/models/diary_day_model.dart +++ b/lib/features/diary/models/diary_day_model.dart @@ -60,24 +60,17 @@ abstract class DiaryDayModel with _$DiaryDayModel { meals: meals, chosenPlanId: chosenPlanId, dayOfChosenDiet: dayOfChosenDiet, + wakeup: wakeup, + retire: retire, diet: diet, ); } DiaryFutureDietDayEntity toDiaryFutureDayEntity() { - - return DiaryFutureDietDayEntity( - date: date, - typeOfDiary: typeOfDiary, - meals: meals, - dayOfChosenDiet: dayOfChosenDiet, - diet: diet, - ); + return DiaryFutureDietDayEntity(date: date, typeOfDiary: typeOfDiary, meals: meals, dayOfChosenDiet: dayOfChosenDiet, diet: diet); } } - - DiaryDietModel? parseDiet(dynamic json) { if (json == null) return null; return DiaryDietModel.fromJson(json['diet']); diff --git a/lib/features/diary/presentation/bloc/diary_cubit.dart b/lib/features/diary/presentation/bloc/diary_cubit.dart index 644837ac..d23cb8d4 100644 --- a/lib/features/diary/presentation/bloc/diary_cubit.dart +++ b/lib/features/diary/presentation/bloc/diary_cubit.dart @@ -23,7 +23,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; class DiaryCubit extends Cubit { late final DateTime today; late DateTime selectedDay; - late int selectedMeal; + int selectedMeal = 1; final DiaryRepository diaryRepository; final GlossaryRepository glossaryRepository; final ProfileRepository profileRepository; @@ -48,44 +48,70 @@ class DiaryCubit extends Cubit { String comment = ''; - Future setSelectedDay(DateTime day, {bool? forDietOnly}) async { - selectedDay = day; - if (forDietOnly ?? false) { - final result = await fetchDiaryV2(); - return result; + Future setSelectedDay(DateTime day) async { + final canSelect = await fetchDiaryV2(needLoading: true); + if (canSelect) { + selectedDay = day; } - await fetchDiaryV2(needLoading: true); - return true; + return canSelect; } - Future fetchDiaryV2({bool needLoading = false, int? diaryId, int? currentDay}) async { - final (diaryDay, error) = await qwe(); - if (error != null) { - if (error == DiaryFetchingErrors.canNotCreateFutureDays) { - return false; - } - emit(DiaryState.error(errorMessage: error.toString())); + Future fetchDiaryV2({bool needLoading = false, int? diaryId}) async { + final currentState = state; + if (needLoading) { + emit(const DiaryState.loading()); } - - if (diaryDay != null) { - final diaryEntity = diaryDay.toEntity(); + if (diaryId != null) { + final diaryDayById = await diaryRepository.getDiaryDay(diaryId); + final diaryEntity = diaryDayById.toEntity(); if (diaryEntity != null) { - setDiary(diaryDay: diaryEntity); + setDiary(diaryDay: diaryEntity, diaryId: diaryId); return true; } - setDiaryForDietOnly(diaryDay.toDiaryFutureDayEntity()); } - return true; + final diaryDay = await getDiary(); + if (diaryDay == null) { + emit(const DiaryState.error(errorMessage: 'Diary not found')); + return true; + } + + final diaryEntity = diaryDay.toEntity(); + if (diaryEntity != null) { + setDiary(diaryDay: diaryEntity, diaryId: diaryId); + return true; + } + if (diaryDay.typeOfDiary.hasChosenDiet == true && diaryDay.typeOfDiary.diaryState == null) { + setDiaryForDietOnly(diaryDay.toDiaryFutureDayEntity()); + return true; + } + emit(currentState); + return false; } - Future<(DiaryDayModel?, DiaryFetchingErrors?)> qwe() async { + Future updateCurrentDiary() async { try { final diaryDay = await diaryRepository.getDiaryDayV2(day: selectedDay.toISO8601WithTimeZoneOffset()); - } on DioException catch (e) { - + final diaryEntity = diaryDay.toEntity(); + if (diaryEntity != null) { + setDiary(diaryDay: diaryEntity, diaryId: diaryId); + } + } catch (e) { + log(e.toString()); } + } - return (null, null); + Future getDiary() async { + try { + await diaryRepository.createDiaryDay(day: selectedDay.toISO8601WithTimeZoneOffset()); + final diaryDay = await diaryRepository.getDiaryDayV2(day: selectedDay.toISO8601WithTimeZoneOffset()); + return diaryDay; + } on DioException catch (e) { + if (e.response?.statusCode == 422) { + final diaryDay = await diaryRepository.getDiaryDayV2(day: selectedDay.toISO8601WithTimeZoneOffset()); + return diaryDay; + } + } + return null; } void setSelectedMeal(int meal) { @@ -177,18 +203,14 @@ class DiaryCubit extends Cubit { return false; } - Future setDiary({int? diaryId, int? currentDay, required DiaryDayEntity diaryDay}) async { + Future setDiary({int? diaryId, required DiaryDayEntity diaryDay}) async { this.diaryId ??= diaryId; final isConsultantView = this.diaryId != null; try { - final DiaryDayModel diaryDay; bool isMoodEnabled = false; bool isWakeUpAndRetireTimeEnabled = false; if (diaryId != null) { - diaryDay = await diaryRepository.getDiaryDay(diaryId); } else { - final stringDate = selectedDay.format('yyyy-MM-dd'); - diaryDay = await diaryRepository.getDiaryByDate(stringDate); final profileSettings = await settingsRepository.getProfileSettings(); isMoodEnabled = profileSettings.isMoodFillable; isWakeUpAndRetireTimeEnabled = profileSettings.isBedtimeFillable; @@ -201,14 +223,14 @@ class DiaryCubit extends Cubit { final chosenPlanModel = await chatRepository.getChosenPlan(id: diaryDay.chosenPlanId!); if (!isConsultantView && (diaryDay.typeOfDiary.diaryState == DiaryStateEnum.lastDayCommented || diaryDay.typeOfDiary.diaryState == DiaryStateEnum.commented)) { - await diaryRepository.viewCommentOfDiaryDayByConsultant(diaryId: diaryDay.id!); + await diaryRepository.viewCommentOfDiaryDayByConsultant(diaryId: diaryDay.id); } - consultantReview = await diaryRepository.getDiaryComments(planId: diaryDay.chosenPlanId!, diaryId: diaryDay.id!); + consultantReview = await diaryRepository.getDiaryComments(planId: diaryDay.chosenPlanId!, diaryId: diaryDay.id); planDuration = chosenPlanModel.plan.duration; planName = chosenPlanModel.plan.name; currentPlanDay = consultantReview.currentPlanDay; } - final nutrition = await getNutrition(diaryDay.id!); + final nutrition = await getNutrition(diaryDay.id); final isDiaryFinished = diaryDay.typeOfDiary.diaryState == DiaryStateEnum.finished || diaryDay.typeOfDiary.diaryState == DiaryStateEnum.lastDayFinished; @@ -218,7 +240,7 @@ class DiaryCubit extends Cubit { diaryDay.typeOfDiary.diaryState == DiaryStateEnum.reviewedByUser; emit( DiaryState.loaded( - diary: diaryDay.toEntity()!, + diary: diaryDay, nutrition: nutrition, selectedDay: selectedDay, selectedMeal: selectedMeal, @@ -241,7 +263,7 @@ class DiaryCubit extends Cubit { Future finishDiaryDay({required int diaryId, required String wakeUp, required String retire}) async { await diaryRepository.finishDiaryDay(diaryId: diaryId, wakeUp: wakeUp, retire: retire, comment: comment.isEmpty ? null : comment); - await fetchDiaryV2(); + await updateCurrentDiary(); } Future getNutrition(int index) async { @@ -265,7 +287,7 @@ class DiaryCubit extends Cubit { quantity: quantity, productNutritionalValueId: productNutritionalValueId, ); - await fetchDiaryV2(); + await updateCurrentDiary(); } Future updateProductInMeal({ @@ -299,27 +321,27 @@ class DiaryCubit extends Cubit { portionState: portionState, ); } - await fetchDiaryV2(); + await updateCurrentDiary(); } Future markEaten({required int diaryId, required int mealId, required int portionId}) async { await diaryRepository.markEaten(diaryId: diaryId, mealId: mealId, portionId: portionId); - await fetchDiaryV2(); + await updateCurrentDiary(); } Future unmarkEaten({required int diaryId, required int mealId, required int portionId}) async { await diaryRepository.unmarkEaten(diaryId: diaryId, mealId: mealId, portionId: portionId); - await fetchDiaryV2(); + await updateCurrentDiary(); } Future restore({required int diaryId, required int mealId, required int portionId}) async { await diaryRepository.restore(diaryId: diaryId, mealId: mealId, portionId: portionId); - await fetchDiaryV2(); + await updateCurrentDiary(); } Future deleteProductFromMeal({required int diaryId, required int mealId, required int portionId}) async { await diaryRepository.deleteProductFromMeal(diaryId: diaryId, mealId: mealId, portionId: portionId); - await fetchDiaryV2(); + await updateCurrentDiary(); } Future> getGlossaryListByQuery(String query) async { @@ -328,12 +350,12 @@ class DiaryCubit extends Cubit { Future uploadPhotos({required List files, required int diaryId}) async { await diaryRepository.uploadPhotos(files: await ImageCompressUtility.compressFilesList(files), diaryId: diaryId, mealId: selectedMeal); - await fetchDiaryV2(); + await updateCurrentDiary(); } Future deletePhoto({required DiaryPhotoModel photo, required int diaryId}) async { await diaryRepository.deletePhoto(photo: photo, diaryId: diaryId, mealId: selectedMeal); - await fetchDiaryV2(); + await updateCurrentDiary(); } Future sendProductToModeration({ @@ -353,34 +375,32 @@ class DiaryCubit extends Cubit { Future fillTime({required int diaryId, required String time}) async { await diaryRepository.fillTime(diaryId: diaryId, mealId: selectedMeal, time: time); - await fetchDiaryV2(); + await updateCurrentDiary(); } Future fillWakeup({required int diaryId, required String time}) async { await diaryRepository.fillWakeup(diaryId: diaryId, time: time); - await fetchDiaryV2(); + await updateCurrentDiary(); } Future fillRetire({required int diaryId, required String time}) async { await diaryRepository.fillRetire(diaryId: diaryId, time: time); - await fetchDiaryV2(); + await updateCurrentDiary(); } Future fillSatiety({required int diaryId, required int satiety}) async { await diaryRepository.fillSatiety(diaryId: diaryId, mealId: selectedMeal, satiety: satiety); - await fetchDiaryV2(); + await updateCurrentDiary(); } Future fillMood({required int diaryId, required int mood}) async { await diaryRepository.fillMood(diaryId: diaryId, mealId: selectedMeal, mood: mood); - await fetchDiaryV2(); + await updateCurrentDiary(); } void fillComment(String comment) { this.comment = comment; } - - } enum DiaryFetchingErrors { canNotCreateFutureDays, dayAlreadyExists } diff --git a/lib/features/diary/presentation/bloc/diary_state.dart b/lib/features/diary/presentation/bloc/diary_state.dart index 771ebb31..02209371 100644 --- a/lib/features/diary/presentation/bloc/diary_state.dart +++ b/lib/features/diary/presentation/bloc/diary_state.dart @@ -1,7 +1,6 @@ import 'package:eatvio_app/features/diary/entities/diary_day_entity.dart'; import 'package:eatvio_app/features/diary/entities/diary_future_diet_day_entity.dart'; import 'package:eatvio_app/features/diary/models/consultant_review_model.dart'; -import 'package:eatvio_app/features/diary/models/diary_day_model.dart'; import 'package:eatvio_app/features/diary/models/nutrition_model.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; diff --git a/lib/features/diary/presentation/pages/diary_screen.dart b/lib/features/diary/presentation/pages/diary_screen.dart index 4ec74e16..6b636857 100644 --- a/lib/features/diary/presentation/pages/diary_screen.dart +++ b/lib/features/diary/presentation/pages/diary_screen.dart @@ -53,7 +53,7 @@ class DiaryScreenContent extends StatelessWidget { final s = S.of(context); return MultiBlocProvider( providers: [ - BlocProvider(create: (BuildContext context) => sl()..fetchDiaryV2(needLoading: true, diaryId: diaryId, currentDay: currentPlanDay)), + BlocProvider(create: (BuildContext context) => sl()..fetchDiaryV2(needLoading: true, diaryId: diaryId)), BlocProvider(create: (context) => sl()), ], child: BlocBuilder( diff --git a/lib/features/diary/presentation/widgets/calendar_widget.dart b/lib/features/diary/presentation/widgets/calendar_widget.dart index b0e5c442..cce80a55 100644 --- a/lib/features/diary/presentation/widgets/calendar_widget.dart +++ b/lib/features/diary/presentation/widgets/calendar_widget.dart @@ -43,46 +43,24 @@ class _CalendarWidgetState extends State { locale: 'ru_RU', startingDayOfWeek: StartingDayOfWeek.monday, calendarFormat: _calendarFormat, - headerStyle: const HeaderStyle( - titleCentered: true, - formatButtonVisible: false, - leftChevronVisible: false, - rightChevronVisible: false, - ), + headerStyle: const HeaderStyle(titleCentered: true, formatButtonVisible: false, leftChevronVisible: false, rightChevronVisible: false), onDaySelected: (selectedDay, focusedDay) async { if (!isSameDay(_selectedDay, selectedDay)) { - final today = DateTime.now(); - if (selectedDay.isAfter(today)) { - if ((state is DiaryStateLoaded)) { - final result = await context.read().setSelectedDay(_selectedDay, forDietOnly: true); - if (result == false && context.mounted) { - showErrorDialog(context, title: s.want_to_see_tomorrow, description: s.can_not_see_next_day); - return; - } - setState(() { - _selectedDay = selectedDay; - _focusedDay = focusedDay; - }); - return; - } - if (state is DiaryStateLoadedTomorrowWithDiet) { - final result = await context.read().setSelectedDay(_selectedDay, forDietOnly: true); - if (result == false && context.mounted) { - showErrorDialog(context, title: s.want_to_see_tomorrow, description: s.can_not_see_next_day); - return; - } - setState(() { - _selectedDay = selectedDay; - _focusedDay = focusedDay; - }); - return; - } - } + final previousSelectedDay = _selectedDay; + final previousFocusedDay = _selectedDay; setState(() { _selectedDay = selectedDay; _focusedDay = focusedDay; }); - context.read().setSelectedDay(_selectedDay); + final canOpenNextDay = await context.read().setSelectedDay(selectedDay); + if (!canOpenNextDay && context.mounted) { + showErrorDialog(context, title: s.want_to_see_tomorrow, description: s.can_not_see_next_day); + setState(() { + _selectedDay = previousSelectedDay; + _focusedDay = previousFocusedDay; + }); + return; + } } }, selectedDayPredicate: (day) { @@ -101,26 +79,12 @@ class _CalendarWidgetState extends State { } }, calendarStyle: CalendarStyle( - weekendDecoration: const BoxDecoration( - color: Colors.white, - shape: BoxShape.circle, - ), - defaultDecoration: const BoxDecoration( - color: Colors.white, - shape: BoxShape.circle, - ), - selectedDecoration: BoxDecoration( - color: appTheme.blueA400, - shape: BoxShape.circle, - ), - todayTextStyle: const TextStyle( - color: Colors.black, - ), + weekendDecoration: const BoxDecoration(color: Colors.white, shape: BoxShape.circle), + defaultDecoration: const BoxDecoration(color: Colors.white, shape: BoxShape.circle), + selectedDecoration: BoxDecoration(color: appTheme.blueA400, shape: BoxShape.circle), + todayTextStyle: const TextStyle(color: Colors.black), todayDecoration: BoxDecoration( - border: Border.all( - color: appTheme.blueA400, - width: 2, - ), + border: Border.all(color: appTheme.blueA400, width: 2), color: Colors.white, shape: BoxShape.circle, ), @@ -152,10 +116,7 @@ class _CalendarWidgetState extends State { child: Container( width: double.infinity, padding: const EdgeInsets.only(top: 8, bottom: 16), - child: Icon( - _calendarFormat == CalendarFormat.month ? Icons.keyboard_arrow_up_rounded : Icons.keyboard_arrow_down_rounded, - color: Colors.grey.shade600, - ), + child: Icon(_calendarFormat == CalendarFormat.month ? Icons.keyboard_arrow_up_rounded : Icons.keyboard_arrow_down_rounded, color: Colors.grey.shade600), ), ); } diff --git a/lib/features/profile/presentation/pages/profile_screen.dart b/lib/features/profile/presentation/pages/profile_screen.dart index 0167fce9..1ea45b7c 100644 --- a/lib/features/profile/presentation/pages/profile_screen.dart +++ b/lib/features/profile/presentation/pages/profile_screen.dart @@ -1,4 +1,3 @@ -import 'dart:developer'; import 'dart:io'; import 'package:cached_network_image/cached_network_image.dart'; From 782f75d26b9398fb2649833986a5c1a285cf52c1 Mon Sep 17 00:00:00 2001 From: misha Date: Mon, 29 Sep 2025 09:49:59 +0300 Subject: [PATCH 3/5] feat(diary): fixed cpfc for v2 diary --- .../diary/repositories/diary_repository.dart | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/lib/features/diary/repositories/diary_repository.dart b/lib/features/diary/repositories/diary_repository.dart index ddc9c74a..642a8121 100644 --- a/lib/features/diary/repositories/diary_repository.dart +++ b/lib/features/diary/repositories/diary_repository.dart @@ -296,7 +296,8 @@ class DiaryRepository { Future getDiaryDayV2({required String day}) async { try { - return await diaryService.getDiaryDayV2(day: day); + final diaryDay = await diaryService.getDiaryDayV2(day: day); + return setCPFCToDiary(diaryDay); } catch (e) { rethrow; } @@ -310,4 +311,51 @@ class DiaryRepository { rethrow; } } + + Future setCPFCToDiary(DiaryDayModel diaryDay) async { + Set ids = {}; + for (var meal in diaryDay.meals) { + for (var portion in meal.portions) { + if (portion.productNutritionalValueId != null) { + ids.add(portion.productNutritionalValueId!); + } + } + } + if (ids.isNotEmpty) { + final glossary = await getGlossariesIndex(ids: ids.toList()); + final List updatedMeals = List.from(diaryDay.meals); + for (var mealIndex = 0; mealIndex < updatedMeals.length; mealIndex++) { + final meal = updatedMeals[mealIndex]; + final updatedPortions = meal.portions.map((portion) { + if (portion.productNutritionalValueId != null) { + try { + final glossaryItem = glossary.glossariesList.firstWhere((g) => g.id == portion.productNutritionalValueId); + return portion.copyWith( + productCaloriesInfo: ProductCaloriesInfoModel( + id: glossaryItem.id, + productName: glossaryItem.name, + calories: glossaryItem.energyOn100Gr, + proteins: glossaryItem.proteinsOn100Gr, + fats: glossaryItem.fatsOn100Gr, + carbohydrates: glossaryItem.carbohydratesOn100Gr, + energyOnPortion: glossaryItem.energyOnPortion, + proteinsOnPortion: glossaryItem.proteinsOnPortion, + fatsOnPortion: glossaryItem.fatsOnPortion, + carbohydratesOnPortion: glossaryItem.carbohydratesOnPortion, + ), + ); + } catch (e) { + return portion; + } + } + return portion; + }).toList(); + + updatedMeals[mealIndex] = meal.copyWith(portions: updatedPortions); + } + final updatedDiaryDay = diaryDay.copyWith(meals: updatedMeals); + return updatedDiaryDay; + } + return diaryDay; + } } From 5ee86ddc9200d5e19504bb3cff6fd9826025ffda Mon Sep 17 00:00:00 2001 From: misha Date: Fri, 3 Oct 2025 15:40:05 +0300 Subject: [PATCH 4/5] feat(diary): fixed wrong cpfc loading after changing a portion --- ...otlin-compiler-10039299475187077818.salive | 0 .../presentation/pages/diary_screen.dart | 4 +- .../widgets/add_product_modal.dart | 34 +++--- ...ssary_moderation_request_modal_widget.dart | 115 +++++------------- .../diary/repositories/diary_repository.dart | 2 +- 5 files changed, 53 insertions(+), 102 deletions(-) delete mode 100644 android/.kotlin/sessions/kotlin-compiler-10039299475187077818.salive diff --git a/android/.kotlin/sessions/kotlin-compiler-10039299475187077818.salive b/android/.kotlin/sessions/kotlin-compiler-10039299475187077818.salive deleted file mode 100644 index e69de29b..00000000 diff --git a/lib/features/diary/presentation/pages/diary_screen.dart b/lib/features/diary/presentation/pages/diary_screen.dart index 6b636857..ae6f9e10 100644 --- a/lib/features/diary/presentation/pages/diary_screen.dart +++ b/lib/features/diary/presentation/pages/diary_screen.dart @@ -62,7 +62,9 @@ class DiaryScreenContent extends StatelessWidget { log(state.diary.id.toString()); } if (state is DiaryStateError) { - return Scaffold(body: DataErrorWidget(onReload: () => context.read().fetchDiaryV2(needLoading: false, diaryId: diaryId))); + return Scaffold( + body: DataErrorWidget(onReload: () => context.read().fetchDiaryV2(needLoading: false, diaryId: diaryId)), + ); } return Scaffold( diff --git a/lib/features/diary/presentation/widgets/add_product_modal.dart b/lib/features/diary/presentation/widgets/add_product_modal.dart index 9b6c2536..4b0a3806 100644 --- a/lib/features/diary/presentation/widgets/add_product_modal.dart +++ b/lib/features/diary/presentation/widgets/add_product_modal.dart @@ -25,26 +25,30 @@ class _AddProductModalState extends State { final quantityController = TextEditingController(); GlossaryModel? selectedGlossary; List glossariesList = []; - + late final String? _previousProductName; @override void initState() { super.initState(); if (widget.portion != null) { + _previousProductName = widget.portion!.productName; productNameController.text = widget.portion!.productName; quantityController.text = '${widget.portion!.quantity}'; - selectedGlossary = GlossaryModel( - id: widget.portion!.id, - name: widget.portion!.productName, - grInPortion: widget.portion!.portion == 'gr' ? 0 : 1, - energyOn100Gr: 0, - proteinsOn100Gr: 0, - fatsOn100Gr: 0, - carbohydratesOn100Gr: 0, - energyOnPortion: 0, - proteinsOnPortion: 0, - fatsOnPortion: 0, - carbohydratesOnPortion: 0, - ); + final productNutritionalValueId = widget.portion?.productNutritionalValueId; + if (productNutritionalValueId != null) { + selectedGlossary = GlossaryModel( + id: productNutritionalValueId, + name: widget.portion!.productName, + grInPortion: widget.portion!.portion == 'gr' ? 0 : 1, + energyOn100Gr: 0, + proteinsOn100Gr: 0, + fatsOn100Gr: 0, + carbohydratesOn100Gr: 0, + energyOnPortion: 0, + proteinsOnPortion: 0, + fatsOnPortion: 0, + carbohydratesOnPortion: 0, + ); + } } } @@ -191,7 +195,7 @@ class _AddProductModalState extends State { ); } Navigator.of(context).pop(); - if (selectedGlossary == null) { + if (selectedGlossary == null && _previousProductName != productNameController.text) { showModalBottomSheet( isScrollControlled: true, useRootNavigator: true, diff --git a/lib/features/diary/presentation/widgets/glossary_moderation_request_modal_widget.dart b/lib/features/diary/presentation/widgets/glossary_moderation_request_modal_widget.dart index 69b316a7..c9359cd9 100644 --- a/lib/features/diary/presentation/widgets/glossary_moderation_request_modal_widget.dart +++ b/lib/features/diary/presentation/widgets/glossary_moderation_request_modal_widget.dart @@ -9,11 +9,7 @@ class GlossaryModerationRequestModalWidget extends StatefulWidget { final DiaryCubit diaryCubit; final String productName; - const GlossaryModerationRequestModalWidget({ - super.key, - required this.productName, - required this.diaryCubit, - }); + const GlossaryModerationRequestModalWidget({super.key, required this.productName, required this.diaryCubit}); @override State createState() => _GlossaryModerationRequestModalWidgetState(); @@ -55,21 +51,13 @@ class _GlossaryModerationRequestModalWidgetState extends State data = ProductInMeal(productName: productName, portion: portion, quantity: quantity).toJson(); - data['product_nutritional_value_id'] = productNutritionalValueId; + if (productNutritionalValueId != null) data['product_nutritional_value_id'] = productNutritionalValueId; data['state'] = portionState.name; return await diaryService.updateProductInMeal(diary: diaryId, typeNo: mealId, portionModel: portionId, productInMeal: data); } From f35cdd26a3abbce88ddbcc92601ec602d15ce1d2 Mon Sep 17 00:00:00 2001 From: misha Date: Mon, 6 Oct 2025 13:33:12 +0300 Subject: [PATCH 5/5] feat(diary): fexed wrong day selecting logic --- lib/features/diary/presentation/bloc/diary_cubit.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/features/diary/presentation/bloc/diary_cubit.dart b/lib/features/diary/presentation/bloc/diary_cubit.dart index d23cb8d4..53beebe0 100644 --- a/lib/features/diary/presentation/bloc/diary_cubit.dart +++ b/lib/features/diary/presentation/bloc/diary_cubit.dart @@ -49,10 +49,14 @@ class DiaryCubit extends Cubit { String comment = ''; Future setSelectedDay(DateTime day) async { + final prevDay = selectedDay; + selectedDay = day; final canSelect = await fetchDiaryV2(needLoading: true); - if (canSelect) { - selectedDay = day; + + if (!canSelect) { + selectedDay = prevDay; } + return canSelect; }