forked from eatvio/eatvio_app
added diets to diary
This commit is contained in:
@@ -114,7 +114,7 @@ Future<void> init() async {
|
||||
sl.registerFactory<PlansCubit>(() => PlansCubit(feedRepository: sl(), planRepository: sl()));
|
||||
sl.registerFactory<SettingsCubit>(() => SettingsCubit(profileRepository: sl(), settingsRepository: sl()));
|
||||
sl.registerFactory<RegisterConsultantCubit>(() => RegisterConsultantCubit(consultantRepository: sl()));
|
||||
sl.registerFactory<DiaryCubit>(() => DiaryCubit(diaryRepository: sl(), glossaryRepository: sl(), profileRepository: sl()));
|
||||
sl.registerFactory<DiaryCubit>(() => DiaryCubit(diaryRepository: sl(), glossaryRepository: sl(), profileRepository: sl(), dietRepository: sl()));
|
||||
sl.registerFactory<AboutDietCubit>(() => AboutDietCubit(dietsRepository: sl(), profileRepository: sl()));
|
||||
sl.registerFactory<BlogPostCreateCubit>(() => BlogPostCreateCubit(blogPostRepository: sl()));
|
||||
sl.registerFactory<SubCubit>(() => SubCubit(profileRepository: sl()));
|
||||
|
||||
@@ -196,6 +196,12 @@ abstract class TextStyles {
|
||||
height: 1.255,
|
||||
);
|
||||
|
||||
static const textLMedium = TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: 1.255,
|
||||
);
|
||||
|
||||
static const textMSemibold = TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
|
||||
@@ -44,7 +44,8 @@ class DiaryDayModel with _$DiaryDayModel {
|
||||
@JsonKey(name: "state") required TypeOfDiaryModel typeOfDiary,
|
||||
@JsonKey(name: "meals") required List<MealModel> meals,
|
||||
@JsonKey(name: "chosen_plan_id") required int? chosenPlanId,
|
||||
@JsonKey(name: "day_of_chosen_diet") required int? dayOfChosenDiet,
|
||||
@JsonKey(name: "day_of_chosen_diet") required int? dayOfChosenDiet,
|
||||
@JsonKey(name: "chosen_diet", fromJson: _parseDiet) required DiaryDietModel? diet,
|
||||
}) = _DiaryDayModel;
|
||||
|
||||
factory DiaryDayModel.fromJson(Map<String, dynamic> json) => _$DiaryDayModelFromJson(json);
|
||||
@@ -56,11 +57,29 @@ class DiaryFutureDietDayModel with _$DiaryFutureDietDayModel {
|
||||
@JsonKey(name: "date") required String date,
|
||||
@JsonKey(name: "state", fromJson: _parseDayTypeForFutureDay) required TypeOfDiaryModel typeOfDiary,
|
||||
@JsonKey(name: "meals") required List<MealModel> meals,
|
||||
@JsonKey(name: "chosen_diet", fromJson: _parseDiet) required DiaryDietModel? diet,
|
||||
@JsonKey(name: "day_of_chosen_diet") required int? dayOfChosenDiet,
|
||||
}) = _DiaryFutureDietDayModel;
|
||||
|
||||
factory DiaryFutureDietDayModel.fromJson(Map<String, dynamic> json) => _$DiaryFutureDietDayModelFromJson(json);
|
||||
}
|
||||
|
||||
DiaryDietModel? _parseDiet(json) {
|
||||
if (json == null) return null;
|
||||
return DiaryDietModel.fromJson(json['diet']);
|
||||
}
|
||||
|
||||
@freezed
|
||||
class DiaryDietModel with _$DiaryDietModel {
|
||||
const factory DiaryDietModel({
|
||||
required int id,
|
||||
required int duration,
|
||||
required String name,
|
||||
}) = _DiaryDietModel;
|
||||
|
||||
factory DiaryDietModel.fromJson(Map<String, dynamic> json) => _$DiaryDietModelFromJson(json);
|
||||
}
|
||||
|
||||
TypeOfDiaryModel _parseDayTypeForFutureDay(json) {
|
||||
return TypeOfDiaryModel(
|
||||
hasChosenDiet: json['has_chosen_diet'] as bool,
|
||||
|
||||
@@ -9,6 +9,7 @@ import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
|
||||
import 'package:eatvio_app/features/diary/models/nutrition_model.dart';
|
||||
import 'package:eatvio_app/features/diary/presentation/bloc/diary_state.dart';
|
||||
import 'package:eatvio_app/features/diary/repositories/diary_repository.dart';
|
||||
import 'package:eatvio_app/features/diets/repositories/diet_repository.dart';
|
||||
import 'package:eatvio_app/features/glossary/models/glossary_model.dart';
|
||||
import 'package:eatvio_app/features/glossary/repositories/glossary_repository.dart';
|
||||
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
|
||||
@@ -21,12 +22,10 @@ class DiaryCubit extends Cubit<DiaryState> {
|
||||
final DiaryRepository diaryRepository;
|
||||
final GlossaryRepository glossaryRepository;
|
||||
final ProfileRepository profileRepository;
|
||||
final DietRepository dietRepository;
|
||||
int? diaryId;
|
||||
DiaryCubit({
|
||||
required this.diaryRepository,
|
||||
required this.glossaryRepository,
|
||||
required this.profileRepository,
|
||||
}) : super(const DiaryState.loading()) {
|
||||
DiaryCubit({required this.diaryRepository, required this.glossaryRepository, required this.profileRepository, required this.dietRepository})
|
||||
: super(const DiaryState.loading()) {
|
||||
today = DateTime.now();
|
||||
selectedDay = today;
|
||||
diaryRepository.forceFetchStream.listen((_) {
|
||||
@@ -36,13 +35,14 @@ class DiaryCubit extends Cubit<DiaryState> {
|
||||
|
||||
String comment = '';
|
||||
|
||||
setSelectedDay(DateTime day, {bool? forDietOnly}) async {
|
||||
Future<bool?> setSelectedDay(DateTime day, {bool? forDietOnly}) async {
|
||||
selectedDay = day;
|
||||
if (forDietOnly ?? false) {
|
||||
await fetchDiaryForDietOnly();
|
||||
return;
|
||||
final result = await fetchDiaryForDietOnly();
|
||||
return result;
|
||||
}
|
||||
await fetchDiary(true);
|
||||
return null;
|
||||
}
|
||||
|
||||
setSelectedMeal(int meal) {
|
||||
@@ -55,10 +55,93 @@ class DiaryCubit extends Cubit<DiaryState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fetchDiaryForDietOnly() async {
|
||||
Future<bool> fetchDiaryForDietOnly() async {
|
||||
final stringDate = selectedDay.format('yyyy-MM-dd');
|
||||
final diaryDay = await diaryRepository.getDiaryByDateForDietOnly(stringDate);
|
||||
emit(DiaryState.loadedTomorrowWithDiet(diary: diaryDay, selectedDay: selectedDay, selectedMeal: selectedMeal));
|
||||
if (!diaryDay.typeOfDiary.hasChosenDiet) {
|
||||
return false;
|
||||
}
|
||||
emit(const DiaryState.loading());
|
||||
if (diaryDay.diet?.id != null && diaryDay.dayOfChosenDiet != null) {
|
||||
final diet = await dietRepository.getDiet((diaryDay.diet?.id)!);
|
||||
final meals = diet.dailySchedule[diaryDay.dayOfChosenDiet];
|
||||
final firstMealPortions = meals?[1]?.values.map((elem) {
|
||||
return PortionModel(
|
||||
id: 0,
|
||||
productName: elem.name,
|
||||
quantity: elem.quantity,
|
||||
portion: elem.portion.getValue(),
|
||||
fromDiet: true,
|
||||
portionState: PortionState.filledDiet,
|
||||
);
|
||||
}).toList();
|
||||
|
||||
final secondMealPortions = meals?[2]?.values.map((elem) {
|
||||
return PortionModel(
|
||||
id: 0,
|
||||
productName: elem.name,
|
||||
quantity: elem.quantity,
|
||||
portion: elem.portion.getValue(),
|
||||
fromDiet: true,
|
||||
portionState: PortionState.filledDiet,
|
||||
);
|
||||
}).toList();
|
||||
|
||||
final thirdMealPortions = meals?[3]?.values.map((elem) {
|
||||
return PortionModel(
|
||||
id: 0,
|
||||
productName: elem.name,
|
||||
quantity: elem.quantity,
|
||||
portion: elem.portion.getValue(),
|
||||
fromDiet: true,
|
||||
portionState: PortionState.filledDiet,
|
||||
);
|
||||
}).toList();
|
||||
|
||||
final fourthMealPortions = meals?[4]?.values.map((elem) {
|
||||
return PortionModel(
|
||||
id: 0,
|
||||
productName: elem.name,
|
||||
quantity: elem.quantity,
|
||||
portion: elem.portion.getValue(),
|
||||
fromDiet: true,
|
||||
portionState: PortionState.filledDiet,
|
||||
);
|
||||
}).toList();
|
||||
|
||||
final fifthMealPortions = meals?[5]?.values.map((elem) {
|
||||
return PortionModel(
|
||||
id: 0,
|
||||
productName: elem.name,
|
||||
quantity: elem.quantity,
|
||||
portion: elem.portion.getValue(),
|
||||
fromDiet: true,
|
||||
portionState: PortionState.filledDiet,
|
||||
);
|
||||
}).toList();
|
||||
final firstMeal = MealModel(id: 0, time: '0', typeNumber: 1, satiety: 0, mood: 0, portions: firstMealPortions ?? [], photos: []);
|
||||
final secondMeal = MealModel(id: 0, time: '0', typeNumber: 2, satiety: 0, mood: 0, portions: secondMealPortions ?? [], photos: []);
|
||||
final thirdMeal = MealModel(id: 0, time: '0', typeNumber: 3, satiety: 0, mood: 0, portions: thirdMealPortions ?? [], photos: []);
|
||||
final fourthMeal = MealModel(id: 0, time: '0', typeNumber: 4, satiety: 0, mood: 0, portions: fourthMealPortions ?? [], photos: []);
|
||||
final fifthMeal = MealModel(id: 0, time: '0', typeNumber: 5, satiety: 0, mood: 0, portions: fifthMealPortions ?? [], photos: []);
|
||||
emit(
|
||||
DiaryState.loadedTomorrowWithDiet(
|
||||
diary: diaryDay.copyWith(
|
||||
meals: [
|
||||
firstMeal,
|
||||
secondMeal,
|
||||
thirdMeal,
|
||||
fourthMeal,
|
||||
fifthMeal,
|
||||
],
|
||||
),
|
||||
selectedDay: selectedDay,
|
||||
selectedMeal: selectedMeal,
|
||||
),
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fetchDiary([bool needLoading = false, int? diaryId]) async {
|
||||
|
||||
@@ -49,12 +49,13 @@ class _CalendarWidgetState extends State<CalendarWidget> {
|
||||
leftChevronVisible: false,
|
||||
rightChevronVisible: false,
|
||||
),
|
||||
onDaySelected: (selectedDay, focusedDay) {
|
||||
onDaySelected: (selectedDay, focusedDay) async {
|
||||
if (!isSameDay(_selectedDay, selectedDay)) {
|
||||
final today = DateTime.now();
|
||||
if (selectedDay.isAfter(today)) {
|
||||
if ((state is DiaryStateLoaded)) {
|
||||
if (!state.diary.typeOfDiary.hasChosenDiet) {
|
||||
final result = await context.read<DiaryCubit>().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;
|
||||
}
|
||||
@@ -62,11 +63,11 @@ class _CalendarWidgetState extends State<CalendarWidget> {
|
||||
_selectedDay = selectedDay;
|
||||
_focusedDay = focusedDay;
|
||||
});
|
||||
context.read<DiaryCubit>().setSelectedDay(_selectedDay, forDietOnly: true);
|
||||
return;
|
||||
}
|
||||
if (state is DiaryStateLoadedTomorrowWithDiet) {
|
||||
if (!state.diary.typeOfDiary.hasChosenDiet) {
|
||||
final result = await context.read<DiaryCubit>().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;
|
||||
}
|
||||
@@ -74,7 +75,6 @@ class _CalendarWidgetState extends State<CalendarWidget> {
|
||||
_selectedDay = selectedDay;
|
||||
_focusedDay = focusedDay;
|
||||
});
|
||||
context.read<DiaryCubit>().setSelectedDay(_selectedDay, forDietOnly: true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_divider.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';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class ChosenDietWidget extends StatelessWidget {
|
||||
const ChosenDietWidget({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<DiaryCubit, DiaryState>(builder: (context, state) {
|
||||
if (state is DiaryStateLoaded) {
|
||||
if (state.diary.typeOfDiary.hasChosenDiet) {
|
||||
return ChosenDietWidgetContent(
|
||||
currentDietDay: state.diary.dayOfChosenDiet ?? 0,
|
||||
dietName: state.diary.diet?.name ?? '',
|
||||
dietDuration: state.diary.diet?.duration ?? 0,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (state is DiaryStateLoadedTomorrowWithDiet) {
|
||||
if (state.diary.typeOfDiary.hasChosenDiet) {
|
||||
return Column(
|
||||
children: [
|
||||
const CustomDivider(),
|
||||
const SizedBox(height: 16),
|
||||
ChosenDietWidgetContent(
|
||||
currentDietDay: state.diary.dayOfChosenDiet ?? 0,
|
||||
dietName: state.diary.diet?.name ?? '',
|
||||
dietDuration: state.diary.diet?.duration ?? 0,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return const SizedBox.shrink();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class ChosenDietWidgetContent extends StatelessWidget {
|
||||
const ChosenDietWidgetContent({
|
||||
super.key,
|
||||
required this.currentDietDay,
|
||||
required this.dietName,
|
||||
required this.dietDuration,
|
||||
});
|
||||
final int currentDietDay;
|
||||
final String dietName;
|
||||
final int dietDuration;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final size = MediaQuery.sizeOf(context);
|
||||
final s = S.of(context);
|
||||
return Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: size.width * 0.4,
|
||||
child: Text(dietName, style: TextStyles.textLMedium.copyWith(color: appTheme.black)),
|
||||
),
|
||||
const Spacer(),
|
||||
Container(
|
||||
decoration: BoxDecoration(color: appTheme.dividerColor, borderRadius: BorderRadius.circular(12)),
|
||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
|
||||
child: Text('${s.day} $currentDietDay из $dietDuration', style: TextStyles.textMSemibold.copyWith(color: appTheme.gray)),
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import 'package:eatvio_app/core/theme/theme_helper.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/features/diary/presentation/widgets/add_product_button_widget.dart';
|
||||
import 'package:eatvio_app/features/diary/presentation/widgets/chosen_diet_widget.dart';
|
||||
import 'package:eatvio_app/features/diary/presentation/widgets/comment_container.dart';
|
||||
import 'package:eatvio_app/features/diary/presentation/widgets/meal_button_widget.dart';
|
||||
import 'package:eatvio_app/features/diary/presentation/widgets/meal_comment_widget.dart';
|
||||
@@ -57,7 +58,8 @@ class _MealWidgetState extends State<MealWidget> {
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
const TimeOfMealPickerWidget(),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
const ChosenDietWidget(),
|
||||
const ProductsListWidget(),
|
||||
if (widget.showAddButton) ...[
|
||||
const SizedBox(height: 12),
|
||||
|
||||
@@ -67,7 +67,7 @@ class _ProductWidgetState extends State<ProductWidget> {
|
||||
if (state is DiaryStateLoadedTomorrowWithDiet) {
|
||||
return ListTile(
|
||||
horizontalTitleGap: 0,
|
||||
contentPadding: widget.portion.fromDiet ? const EdgeInsets.only(right: 24, left: 4) : null,
|
||||
contentPadding: widget.portion.fromDiet ? const EdgeInsets.only(right: 24, left: 12) : null,
|
||||
title: Text(widget.portion.productName),
|
||||
subtitle: Text('${widget.portion.quantity} ${widget.portion.portion == 'gr' ? 'гр' : 'шт'}'),
|
||||
shape: RoundedRectangleBorder(
|
||||
|
||||
@@ -124,6 +124,7 @@ class _TimeOfMealPickerWidgetState extends State<TimeOfMealPickerWidget> {
|
||||
),
|
||||
),
|
||||
const CustomDivider(),
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -693,7 +693,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"Ожидайте начала плана питания",
|
||||
),
|
||||
"want_to_see_tomorrow": MessageLookupByLibrary.simpleMessage(
|
||||
"Хотите заглянуть в завтра?",
|
||||
"Хотите заглянуть в будущее?",
|
||||
),
|
||||
"weapon": MessageLookupByLibrary.simpleMessage("Оружие"),
|
||||
"weight": MessageLookupByLibrary.simpleMessage("Вес"),
|
||||
|
||||
@@ -2865,10 +2865,10 @@ class S {
|
||||
);
|
||||
}
|
||||
|
||||
/// `Хотите заглянуть в завтра?`
|
||||
/// `Хотите заглянуть в будущее?`
|
||||
String get want_to_see_tomorrow {
|
||||
return Intl.message(
|
||||
'Хотите заглянуть в завтра?',
|
||||
'Хотите заглянуть в будущее?',
|
||||
name: 'want_to_see_tomorrow',
|
||||
desc: '',
|
||||
args: [],
|
||||
|
||||
@@ -349,7 +349,7 @@
|
||||
"try_again_2": "Попробуйте ещё раз",
|
||||
"sorry_we_did_not_find_the_plan": "Извините, план где-то потерялся, мы уже ищем его",
|
||||
"can_not_see_next_day": "Просмотр последующего дня возможен только при прохождении диеты",
|
||||
"want_to_see_tomorrow": "Хотите заглянуть в завтра?",
|
||||
"want_to_see_tomorrow": "Хотите заглянуть в будущее?",
|
||||
"you_can_not_start_plan_until_end_of_prev_one": "Вы не можете начать план, пока не закончите прохождение предыдущего",
|
||||
"end_previous_plan": "Закончите прохождение предыдущего плана",
|
||||
"you_can_not_open_this_day": "Вы не можете перейти в этот день",
|
||||
|
||||
Reference in New Issue
Block a user