From 87925775e862100c5221afb6c552006bc29d6aec Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 1 Dec 2024 23:54:16 +0300 Subject: [PATCH] feat: add satiety --- .../diary/presentation/bloc/diary_cubit.dart | 11 + .../presentation/widgets/meal_widget.dart | 3 + .../widgets/satiety_rating_widget.dart | 348 +++++++++--------- 3 files changed, 197 insertions(+), 165 deletions(-) diff --git a/lib/features/diary/presentation/bloc/diary_cubit.dart b/lib/features/diary/presentation/bloc/diary_cubit.dart index 8d029ce6..54128921 100644 --- a/lib/features/diary/presentation/bloc/diary_cubit.dart +++ b/lib/features/diary/presentation/bloc/diary_cubit.dart @@ -182,4 +182,15 @@ class DiaryCubit extends Cubit { ); await fetchDiary(); } + + fillSatiety({ + required int diaryId, + required int satiety, + }) async { + await diaryRepository.fillSatiety( + diaryId: diaryId, + mealId: selectedMeal, + satiety: satiety, + ); + } } diff --git a/lib/features/diary/presentation/widgets/meal_widget.dart b/lib/features/diary/presentation/widgets/meal_widget.dart index 1314410d..43f7976c 100644 --- a/lib/features/diary/presentation/widgets/meal_widget.dart +++ b/lib/features/diary/presentation/widgets/meal_widget.dart @@ -2,6 +2,7 @@ import 'package:eatvio_app/features/diary/presentation/widgets/add_product_butto import 'package:eatvio_app/features/diary/presentation/widgets/meal_button_widget.dart'; import 'package:eatvio_app/features/diary/presentation/widgets/photo_gallery_widget.dart'; import 'package:eatvio_app/features/diary/presentation/widgets/products_list_widget.dart'; +import 'package:eatvio_app/features/diary/presentation/widgets/satiety_rating_widget.dart'; import 'package:eatvio_app/features/diary/presentation/widgets/time_of_meal_picker_widget.dart'; import 'package:flutter/material.dart'; @@ -50,6 +51,8 @@ class _MealWidgetState extends State { AddProductButtonWidget(), const SizedBox(height: 12), PhotoGalleryWidget(), + const SizedBox(height: 12), + SatietyRatingWidget(), ], ), ), diff --git a/lib/features/diary/presentation/widgets/satiety_rating_widget.dart b/lib/features/diary/presentation/widgets/satiety_rating_widget.dart index 8eab2866..89404fcc 100644 --- a/lib/features/diary/presentation/widgets/satiety_rating_widget.dart +++ b/lib/features/diary/presentation/widgets/satiety_rating_widget.dart @@ -1,181 +1,199 @@ +import 'package:easy_debounce/easy_debounce.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:flutter/cupertino.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; import 'package:flutter_svg/flutter_svg.dart'; class SatietyRatingWidget extends StatefulWidget { - final List currentSelectedSatietyRating; - final int diaryId; - final int meal; - - const SatietyRatingWidget({ - super.key, - required this.currentSelectedSatietyRating, - required this.diaryId, - required this.meal, - }); - @override State createState() => _SatietyRatingWidgetState(); } class _SatietyRatingWidgetState extends State { + late double currentSelectedRating; + bool isFirstFetch = true; + @override Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(top: 24), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - 'Ваша сытость после приёма пищи', - style: TextStyle( - fontSize: 16, + return BlocBuilder( + builder: (BuildContext context, DiaryState state) { + if (state is DiaryStateLoaded) { + if (isFirstFetch) { + currentSelectedRating = state.diary.meals[state.selectedMeal - 1].satiety.toDouble(); + isFirstFetch = false; + } + return Padding( + padding: const EdgeInsets.only(top: 24), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Ваша сытость после приёма пищи', + style: TextStyle( + fontSize: 16, + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SvgPicture.asset( + 'assets/icons/satiety_emoji_left.svg', + height: 32, + width: 32, + ), + RatingBar.builder( + initialRating: state.diary.meals[state.selectedMeal - 1].satiety.toDouble(), + itemCount: 6, + itemSize: MediaQuery.of(context).size.width / 6 - (124 / 6), + updateOnDrag: true, + itemBuilder: (context, index) { + switch (index) { + case 0: + return Container( + width: MediaQuery.of(context).size.width / 6, + height: 24, + margin: currentSelectedRating == 1 ? EdgeInsets.symmetric(horizontal: 2) : null, + decoration: BoxDecoration( + color: Color(0xFFC82222), + border: currentSelectedRating == 1 + ? Border.all( + width: 2, + color: Color(0xFFAA3333), + strokeAlign: BorderSide.strokeAlignOutside, + ) + : null, + borderRadius: currentSelectedRating == 1 + ? BorderRadius.horizontal( + left: Radius.circular(8), + right: Radius.circular(2), + ) + : BorderRadius.horizontal( + left: Radius.circular(8), + ), + ), + ); + case 1: + return Container( + width: MediaQuery.of(context).size.width / 6, + height: 24, + margin: currentSelectedRating == 2 ? EdgeInsets.symmetric(horizontal: 2) : null, + decoration: BoxDecoration( + color: Color(0xFFFF3E3E), + border: currentSelectedRating == 2 + ? Border.all( + width: 2, + color: Color(0xFF550000), + strokeAlign: BorderSide.strokeAlignOutside, + ) + : null, + borderRadius: currentSelectedRating == 2 ? BorderRadius.circular(2) : null, + ), + ); + case 2: + return Container( + width: MediaQuery.of(context).size.width / 6, + height: 24, + margin: currentSelectedRating == 3 ? EdgeInsets.symmetric(horizontal: 2) : null, + decoration: BoxDecoration( + color: Color(0xFFF8C926), + border: currentSelectedRating == 3 + ? Border.all( + width: 2, + color: Color(0xFF8C5D00), + strokeAlign: BorderSide.strokeAlignOutside, + ) + : null, + borderRadius: currentSelectedRating == 3 ? BorderRadius.circular(2) : null, + ), + ); + case 3: + return Container( + width: MediaQuery.of(context).size.width / 6, + height: 24, + margin: currentSelectedRating == 4 ? EdgeInsets.symmetric(horizontal: 2) : null, + decoration: BoxDecoration( + color: Color(0xFFFFF3BF), + border: currentSelectedRating == 4 + ? Border.all( + width: 2, + color: Color(0xFFB5911B), + strokeAlign: BorderSide.strokeAlignOutside, + ) + : null, + borderRadius: currentSelectedRating == 4 ? BorderRadius.circular(2) : null, + ), + ); + case 4: + return Container( + width: MediaQuery.of(context).size.width / 6, + height: 24, + margin: currentSelectedRating == 5 ? EdgeInsets.symmetric(horizontal: 2) : null, + decoration: BoxDecoration( + color: Color(0xFF62E833), + border: currentSelectedRating == 5 + ? Border.all( + width: 2, + color: Color(0xFF276918), + strokeAlign: BorderSide.strokeAlignOutside, + ) + : null, + borderRadius: currentSelectedRating == 5 ? BorderRadius.circular(2) : null, + ), + ); + default: + return Container( + width: MediaQuery.of(context).size.width / 6, + height: 24, + margin: currentSelectedRating == 6 ? EdgeInsets.symmetric(horizontal: 2) : null, + decoration: BoxDecoration( + color: Color(0xFF4DCE20), + border: currentSelectedRating == 6 + ? Border.all( + width: 2, + color: Color(0xFF184D12), + strokeAlign: BorderSide.strokeAlignOutside, + ) + : null, + borderRadius: currentSelectedRating == 6 + ? BorderRadius.horizontal( + left: Radius.circular(2), + right: Radius.circular(8), + ) + : BorderRadius.horizontal( + right: Radius.circular(8), + ), + ), + ); + } + }, + onRatingUpdate: (value) { + setState(() { + currentSelectedRating = value; + }); + EasyDebounce.debounce( + 'change-satiety', + Duration(milliseconds: 250), + () { + context.read().fillSatiety(diaryId: state.diary.id, satiety: currentSelectedRating.toInt()); + }, + ); + }, + ), + SvgPicture.asset( + 'assets/icons/satiety_emoji_right.svg', + height: 32, + width: 32, + ), + ], + ), + ], ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - SvgPicture.asset( - 'assets/icons/satiety_emoji_left.svg', - height: 32, - width: 32, - ), - RatingBar.builder( - initialRating: widget.currentSelectedSatietyRating[widget.meal - 1].toDouble() + 1, - itemCount: 6, - itemSize: MediaQuery.of(context).size.width / 6 - (124 / 6), - updateOnDrag: true, - itemBuilder: (context, index) { - switch (index) { - case 0: - return Container( - width: MediaQuery.of(context).size.width / 6, - height: 24, - margin: widget.currentSelectedSatietyRating[widget.meal - 1].toDouble() + 1 == 1 ? EdgeInsets.symmetric(horizontal: 2) : null, - decoration: BoxDecoration( - color: Color(0xFFC82222), - border: widget.currentSelectedSatietyRating[widget.meal - 1].toDouble() + 1 == 1 - ? Border.all( - width: 2, - color: Color(0xFFAA3333), - strokeAlign: BorderSide.strokeAlignOutside, - ) - : null, - borderRadius: widget.currentSelectedSatietyRating[widget.meal - 1].toDouble() + 1 == 1 - ? BorderRadius.horizontal( - left: Radius.circular(8), - right: Radius.circular(2), - ) - : BorderRadius.horizontal( - left: Radius.circular(8), - ), - ), - ); - case 1: - return Container( - width: MediaQuery.of(context).size.width / 6, - height: 24, - margin: widget.currentSelectedSatietyRating[widget.meal - 1].toDouble() + 1 == 2 ? EdgeInsets.symmetric(horizontal: 2) : null, - decoration: BoxDecoration( - color: Color(0xFFFF3E3E), - border: widget.currentSelectedSatietyRating[widget.meal - 1].toDouble() + 1 == 2 - ? Border.all( - width: 2, - color: Color(0xFF550000), - strokeAlign: BorderSide.strokeAlignOutside, - ) - : null, - borderRadius: widget.currentSelectedSatietyRating[widget.meal - 1].toDouble() + 1 == 2 ? BorderRadius.circular(2) : null, - ), - ); - case 2: - return Container( - width: MediaQuery.of(context).size.width / 6, - height: 24, - margin: widget.currentSelectedSatietyRating[widget.meal - 1].toDouble() + 1 == 3 ? EdgeInsets.symmetric(horizontal: 2) : null, - decoration: BoxDecoration( - color: Color(0xFFF8C926), - border: widget.currentSelectedSatietyRating[widget.meal - 1].toDouble() + 1 == 3 - ? Border.all( - width: 2, - color: Color(0xFF8C5D00), - strokeAlign: BorderSide.strokeAlignOutside, - ) - : null, - borderRadius: widget.currentSelectedSatietyRating[widget.meal - 1].toDouble() + 1 == 3 ? BorderRadius.circular(2) : null, - ), - ); - case 3: - return Container( - width: MediaQuery.of(context).size.width / 6, - height: 24, - margin: widget.currentSelectedSatietyRating[widget.meal - 1].toDouble() + 1 == 4 ? EdgeInsets.symmetric(horizontal: 2) : null, - decoration: BoxDecoration( - color: Color(0xFFFFF3BF), - border: widget.currentSelectedSatietyRating[widget.meal - 1].toDouble() + 1 == 4 - ? Border.all( - width: 2, - color: Color(0xFFB5911B), - strokeAlign: BorderSide.strokeAlignOutside, - ) - : null, - borderRadius: widget.currentSelectedSatietyRating[widget.meal - 1].toDouble() + 1 == 4 ? BorderRadius.circular(2) : null, - ), - ); - case 4: - return Container( - width: MediaQuery.of(context).size.width / 6, - height: 24, - margin: widget.currentSelectedSatietyRating[widget.meal - 1].toDouble() + 1 == 5 ? EdgeInsets.symmetric(horizontal: 2) : null, - decoration: BoxDecoration( - color: Color(0xFF62E833), - border: widget.currentSelectedSatietyRating[widget.meal - 1].toDouble() + 1 == 5 - ? Border.all( - width: 2, - color: Color(0xFF276918), - strokeAlign: BorderSide.strokeAlignOutside, - ) - : null, - borderRadius: widget.currentSelectedSatietyRating[widget.meal - 1].toDouble() + 1 == 5 ? BorderRadius.circular(2) : null, - ), - ); - default: - return Container( - width: MediaQuery.of(context).size.width / 6, - height: 24, - margin: widget.currentSelectedSatietyRating[widget.meal - 1].toDouble() + 1 == 6 ? EdgeInsets.symmetric(horizontal: 2) : null, - decoration: BoxDecoration( - color: Color(0xFF4DCE20), - border: widget.currentSelectedSatietyRating[widget.meal - 1].toDouble() + 1 == 6 - ? Border.all( - width: 2, - color: Color(0xFF184D12), - strokeAlign: BorderSide.strokeAlignOutside, - ) - : null, - borderRadius: widget.currentSelectedSatietyRating[widget.meal - 1].toDouble() + 1 == 6 - ? BorderRadius.horizontal( - left: Radius.circular(2), - right: Radius.circular(8), - ) - : BorderRadius.horizontal( - right: Radius.circular(8), - ), - ), - ); - } - }, - onRatingUpdate: (value) {}, - ), - SvgPicture.asset( - 'assets/icons/satiety_emoji_right.svg', - height: 32, - width: 32, - ), - ], - ), - ], - ), + ); + } + return const SizedBox.shrink(); + }, ); } }