diff --git a/lib/features/diary/entities/diary_day_entity.dart b/lib/features/diary/entities/diary_day_entity.dart index 65f45570..e533dda7 100644 --- a/lib/features/diary/entities/diary_day_entity.dart +++ b/lib/features/diary/entities/diary_day_entity.dart @@ -18,5 +18,8 @@ abstract class DiaryDayEntity with _$DiaryDayEntity { @JsonKey(name: "day_of_chosen_diet") required int? dayOfChosenDiet, @JsonKey(name: "chosen_diet", fromJson: parseDiet) required DiaryDietModel? diet, }) = _DiaryDayEntity; - + + const DiaryDayEntity._(); + + bool get hasProducts => meals.any((meal) => meal.portions.isNotEmpty); } diff --git a/lib/features/diary/presentation/pages/diary_screen.dart b/lib/features/diary/presentation/pages/diary_screen.dart index 607e97d2..c7f832d4 100644 --- a/lib/features/diary/presentation/pages/diary_screen.dart +++ b/lib/features/diary/presentation/pages/diary_screen.dart @@ -127,6 +127,7 @@ class _DiaryScreenContentState extends State { child: _isDiaryFinishing ? const Center(child: Loader()) : FinishDayButtonWidget( + hasProducts: state.diary.hasProducts, onPressed: () async { setState(() { _isDiaryFinishing = true; 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 af58216a..ba13dd96 100644 --- a/lib/features/diary/presentation/widgets/finish_day_button_widget.dart +++ b/lib/features/diary/presentation/widgets/finish_day_button_widget.dart @@ -1,20 +1,89 @@ +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/bottom_sheet_handler_bar.dart'; +import 'package:eatvio_app/core/widgets/bottom_sheet_with_blur.dart'; +import 'package:eatvio_app/core/widgets/custom_outlined_button.dart'; +import 'package:eatvio_app/core/widgets/show_error_dialog.dart'; import 'package:flutter/material.dart'; class FinishDayButtonWidget extends StatefulWidget { final Future Function() onPressed; + final bool hasProducts; - const FinishDayButtonWidget({super.key, required this.onPressed}); + const FinishDayButtonWidget({super.key, required this.onPressed, required this.hasProducts}); @override State createState() => _FinishDayButtonWidgetState(); } class _FinishDayButtonWidgetState extends State { + void _onTap() { + if (!widget.hasProducts) { + showErrorDialog( + context, + title: 'Не добавлено продуктов', + description: 'Добавьте хотя бы один продукт в любой из приёмов пищи, чтобы закончить день.', + ); + return; + } + _showConfirmationBottomSheet(); + } + + void _showConfirmationBottomSheet() { + showBottomSheetWithBlur( + context: context, + height: null, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox(height: 8), + const BottomSheetHandlerBar(), + const SizedBox(height: 20), + Text('Закончить день', style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black)), + const SizedBox(height: 16), + Text( + 'После завершения дня, его уже нельзя будет отредактировать', + style: TextStyles.textSMedium.copyWith(color: appTheme.black), + textAlign: TextAlign.center, + ), + const SizedBox(height: 16), + CustomOutlinedButton( + text: 'Закончить', + height: 52, + buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700), + buttonStyle: ButtonStyle( + side: const WidgetStatePropertyAll(BorderSide.none), + backgroundColor: WidgetStatePropertyAll(appTheme.blueA400), + ), + onPressed: () async { + Navigator.of(context).pop(); + await widget.onPressed(); + }, + ), + const SizedBox(height: 8), + CustomOutlinedButton( + text: 'Отмена', + height: 52, + buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.black), + buttonStyle: const ButtonStyle( + side: WidgetStatePropertyAll(BorderSide.none), + backgroundColor: WidgetStatePropertyAll(Color(0xFFEAEAEA)), + ), + onPressed: () => Navigator.of(context).pop(), + ), + const SizedBox(height: 40), + ], + ), + ), + ); + } + @override Widget build(BuildContext context) { return InkWell( - onTap: widget.onPressed, + onTap: _onTap, borderRadius: BorderRadius.circular(20), child: Ink( padding: const EdgeInsets.symmetric(horizontal: 8), diff --git a/test/features/diary/presentation/widgets/basic_widget_test.dart b/test/features/diary/presentation/widgets/basic_widget_test.dart index 02c97f23..c68b8164 100644 --- a/test/features/diary/presentation/widgets/basic_widget_test.dart +++ b/test/features/diary/presentation/widgets/basic_widget_test.dart @@ -220,7 +220,7 @@ void main() { testWidgets('should display FinishDayButtonWidget', (WidgetTester tester) async { // Arrange - final widget = FinishDayButtonWidget(onPressed: () async {}); + final widget = FinishDayButtonWidget(onPressed: () async {}, hasProducts: true); // Act await tester.pumpWidget(createTestWidget(widget)); @@ -234,7 +234,7 @@ void main() { // Arrange diaryCubit.emit(DiaryState.loaded(diary: testDiaryEntity, nutrition: testNutrition, selectedDay: DateTime(2024, 1, 15), selectedMeal: 1)); - final widget = FinishDayButtonWidget(onPressed: () async {}); + final widget = FinishDayButtonWidget(onPressed: () async {}, hasProducts: true); await tester.pumpWidget(createTestWidget(widget)); await tester.pumpAndSettle(); diff --git a/test/features/diary/presentation/widgets/finish_day_button_widget_test.dart b/test/features/diary/presentation/widgets/finish_day_button_widget_test.dart index 6eee2102..7b6f29bb 100644 --- a/test/features/diary/presentation/widgets/finish_day_button_widget_test.dart +++ b/test/features/diary/presentation/widgets/finish_day_button_widget_test.dart @@ -13,7 +13,7 @@ void main() { } testWidgets('renders finish day button widget', (tester) async { - await tester.pumpWidget(wrap(FinishDayButtonWidget(onPressed: () async {}))); + await tester.pumpWidget(wrap(FinishDayButtonWidget(onPressed: () async {}, hasProducts: true))); await tester.pump(); expect(find.byType(FinishDayButtonWidget), findsOneWidget);