// ignore_for_file: unused_local_variable /*import 'bloc/diary_edit_bloc.dart'; import 'models/diary_edit_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:fl_chart/fl_chart.dart'; import 'package:image_picker/image_picker.dart'; import 'package:eatvio_app/core/app_export.dart'; import 'package:eatvio_app/widgets/custom_edit_text_form_field.dart'; import 'package:eatvio_app/widgets/custom_edit_drop_down.dart'; import 'package:eatvio_app/widgets/custom_outlined_button.dart'; import 'package:eatvio_app/widgets/custom_scale_element.dart'; import 'package:carousel_slider/carousel_slider.dart'; // ignore: must_be_immutable class DiaryEditScreen extends StatelessWidget { DiaryEditScreen({Key? key}) : super(key: key); static Widget builder(BuildContext context) { return BlocProvider( create: (context) => DiaryEditBloc(DiaryEditState(diaryEditModelObj: DiaryEditModel())) ..add(DiaryEditInitialEvent()), child: DiaryEditScreen(), ); } Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { if (state is DiaryEditInitialState) { // Это начальное состояние, данные ещё не загружены. return Container( color: Colors.white, ); } else if (state is DiaryEditLoadedState) { // Данные загружены, можно строить экран. return _buildDiaryEditScreen(context, state); } else if (state is DiaryEditErrorState) { // Произошла ошибка при загрузке данных. return Center(child: Text(state.errorMessage)); } else { // Другие состояния, если они есть. return Container(); // Пустой контейнер для необработанных состояний. } }, ); } Widget _buildDiaryEditScreen( BuildContext context, DiaryEditLoadedState state) { return RefreshIndicator( onRefresh: refreshPage(context), child: Stack( alignment: Alignment.bottomCenter, children: [ FormBuilder( child: Scaffold( appBar: AppBar( toolbarHeight: 0, automaticallyImplyLeading: false, ), backgroundColor: Color.fromARGB(255, 240, 242, 245), resizeToAvoidBottomInset: true, body: SizedBox( width: double.maxFinite, child: Column( children: [ Expanded( child: SingleChildScrollView( child: Padding( padding: EdgeInsets.only(bottom: 5.v), child: Column( children: [ _buildHeaderRow(context, state), SizedBox(height: 30.v), _buildWakupRetire(context, state), SizedBox(height: 30.v), _buildMeal(context, state), SizedBox(height: 20.v), _buildMood(context, state), SizedBox(height: 30.v), _buildNutritionChart(context, state), SizedBox(height: 30.v), _buildComment(context, state), ], ), ), ), ), ], ), ), ), ), _buildEndDay(context), ], ), ); } _buildEndDay(BuildContext context) { return CustomOutlinedButton( text: "Закончить день", margin: EdgeInsets.only( left: 16.h, right: 16.h, bottom: 16.v, ), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, decoration: BoxDecoration( color: Colors.transparent, ), onPressed: onFinishDayPressed(context), // Установите прозрачный фон ); } refreshPage(BuildContext context) { return () async { context.read().add(RefreshEvent()); }; } /// Section Widget _buildHeaderRow(BuildContext context, DiaryEditLoadedState state) { final day = state.diaryId; return Container( margin: EdgeInsets.symmetric(horizontal: 16.h, vertical: 16.h), padding: EdgeInsets.symmetric( horizontal: 24.h, vertical: 12.v, ), decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.all(Radius.circular(12)), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 2, blurRadius: 5, offset: Offset(0, 3), ), ], ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Padding( padding: EdgeInsets.only(top: 1.v), child: Column( children: [ Align( alignment: Alignment.centerRight, child: Text( "$day день", style: CustomTextStyles.titleMediumBlack, ), ), SizedBox(height: 2.v), Text( state.diaryDate.toString(), style: CustomTextStyles.bodyMediumBluegray800, ), ], ), ), ], ), ); } /// Section Widget _buildAddProduct(BuildContext context, DiaryEditLoadedState state) { return CustomOutlinedButton( text: "Добавить продукт", margin: EdgeInsets.symmetric(horizontal: 10.h), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, onPressed: addProduct(context), ); } addProduct(BuildContext context) { return () { context.read().add(AddPortionEvent()); }; } /// Section Widget _buildAddPhoto(BuildContext context, DiaryEditLoadedState state) { bool isLoading = state.isLoading; return GestureDetector( onTap: addImage(context, isLoading), child: Stack( children: [ if (!isLoading) Container( margin: EdgeInsets.symmetric(horizontal: 10.h), padding: EdgeInsets.symmetric( horizontal: 40.h, vertical: 80.v, ), decoration: AppDecoration.fillGray.copyWith( borderRadius: BorderRadiusStyle.roundedBorder5, ), child: Row( mainAxisAlignment: MainAxisAlignment.end, mainAxisSize: MainAxisSize.min, children: [ // Показывайте прелоадер, если загрузка активна Padding( padding: EdgeInsets.only( left: 7.h, top: 5.v, ), child: Text( "Добавить фото", selectionColor: appTheme.blueA400, ), ), Spacer(), Icon( Icons.photo_library, color: appTheme.blueGray300, ), ], ), ), if (isLoading) Container( margin: EdgeInsets.symmetric(horizontal: 10.h), padding: EdgeInsets.symmetric( horizontal: 40.h, vertical: 80.v, ), decoration: AppDecoration.fillGray.copyWith( borderRadius: BorderRadiusStyle.roundedBorder5, ), child: Center( child: CircularProgressIndicator( color: appTheme .blueGray300), // Замените на свой прелоадер при необходимости ), ), ], ), ); } addImage(BuildContext context, bool isLoading) { if (!isLoading) { return () async { final picker = ImagePicker(); List? images = await picker.pickMultiImage(); if (images.isNotEmpty) { for (var image in images) { context.read().add(UploadImages(image)); } } }; } } _buildMeal(BuildContext context, DiaryEditLoadedState state) { final digitsOnly = FilteringTextInputFormatter.digitsOnly; List _options = state.autocompleteList!.map((dynamic item) => item as String).toList(); //print(_options); FocusNode focusNodeName = FocusNode(); return Container( margin: EdgeInsets.symmetric(horizontal: 16.h), padding: EdgeInsets.symmetric( horizontal: 24.h, vertical: 12.v, ), decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.all(Radius.circular(12)), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 2, blurRadius: 5, offset: Offset(0, 3), ), ], ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Padding( padding: EdgeInsets.symmetric(horizontal: 10.h), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Время приема пищи", style: CustomTextStyles.bodyMediumBlack900, ), Expanded( // Adding Expanded widget child: Padding( padding: EdgeInsets.symmetric(horizontal: 10.h), child: ConstrainedBox( constraints: BoxConstraints( maxWidth: MediaQuery.of(context).size.width - 260, ), child: GestureDetector( onTap: () => _selectMealTime(context, state), child: AbsorbPointer( child: CustomTextFormField( hintText: state.mealTimeController ?.format(context) .toString(), autofocus: false, ), ), ), ), ), ), ], ), ), SizedBox(height: 20.v), Padding( padding: EdgeInsets.symmetric(horizontal: 10.h), child: BlocSelector( selector: (state) => state.diaryEditModelObj, builder: (context, diaryEditModelObj) { return CustomDropDown( hintText: "Прием пищи", items: diaryEditModelObj?.mealList, contentPadding: EdgeInsets.symmetric( horizontal: 10.h, vertical: 9.v, ), defaultValue: diaryEditModelObj?.mealList[0], onChanged: changeMeal(context, state), ); }, ), ), SizedBox(height: 20.v), Padding( padding: EdgeInsets.symmetric(horizontal: 10.h), child: RawAutocomplete( optionsBuilder: buildOptions(_options), fieldViewBuilder: ( BuildContext context, TextEditingController productEditingController, FocusNode focusNodeName, VoidCallback onFieldSubmitted, ) { if (state.isAdded) { print("Clear"); } return CustomTextFormField( hintText: "Введите название продукта", controller: productEditingController, focusNode: focusNodeName, onChanged: getAutocomplete(context, focusNodeName), ); }, optionsViewBuilder: ( BuildContext context, AutocompleteOnSelected onSelected, Iterable options, ) { return Align( alignment: Alignment.topLeft, child: Material( elevation: 4.0, child: SizedBox( height: 200.0, child: ListView.builder( padding: const EdgeInsets.all(8.0), itemCount: options.length, itemBuilder: (BuildContext context, int index) { final String option = options.elementAt(index); return GestureDetector( onTap: selectProduct(onSelected, option, state), child: ListTile( title: Text(option), ), ); }, ), ), ), ); }, ), ), SizedBox(height: 20.v), if (state.moderationExpanded) Padding( padding: EdgeInsets.symmetric(horizontal: 10.h), child: GestureDetector( onTap: () => openCaloriesDialog(context, state), child: Text("Отправить на модерацию"), ), ), SizedBox(height: 20.v), Padding( padding: EdgeInsets.symmetric(horizontal: 10.h), 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), _buildAddProduct(context, state), SizedBox(height: 30.v), ...state.portions! .map((portion) => _buildProduct(context, portion)) .toList(), SizedBox(height: 30.v), /*...state.photos != null ? state.photos!.isEmpty ? [Text('Фото пока нет')] : state.photos! .map((photo) => _buildPhoto(context, photo)) .toList() : [Text('Фото нет')],*/ _buildCarousel(context, state), SizedBox(height: 20.v), _buildAddPhoto(context, state), SizedBox(height: 30.v), Text( "Ваша сытость после приёма пищи", style: CustomTextStyles.bodyMediumBlack900, ), SizedBox(height: 15.v), BlocBuilder( builder: (context, state) { if (state is DiaryEditLoadedState) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text("😭"), ScaleElement( color: Colors.red, isSelected: state.selectedSatiety == 0, onTap: changeSatiety(context, 0), ), ScaleElement( color: Colors.orange, isSelected: state.selectedSatiety == 1, onTap: changeSatiety(context, 1), ), ScaleElement( color: Colors.yellow, isSelected: state.selectedSatiety == 2, onTap: changeSatiety(context, 2), ), ScaleElement( color: Colors.lime, isSelected: state.selectedSatiety == 3, onTap: changeSatiety(context, 3), ), ScaleElement( color: Colors.lightGreen, isSelected: state.selectedSatiety == 4, onTap: changeSatiety(context, 4), ), ScaleElement( color: Colors.green, isSelected: state.selectedSatiety == 5, onTap: changeSatiety(context, 5), ), Text("😊"), // Остальные элементы шкалы ], ); } else { return Container(); // Возвращаем пустой контейнер, если состояние не является DiaryEditLoadedState } }, ), ], ), ); } openCaloriesDialog(BuildContext context, DiaryEditLoadedState state) { showDialog( context: context, builder: (BuildContext dialogContext) { return AlertDialog( title: Text('Введите информацию о продукте'), content: Column( mainAxisSize: MainAxisSize.min, children: [ CustomTextFormField( hintText: "Название", controller: state.productNameController, ), SizedBox(height: 10.v), CustomTextFormField( hintText: "Энергетическая ценность на 100", keyboardType: TextInputType.number, controller: state.caloriesController, ), SizedBox(height: 10.v), CustomTextFormField( hintText: "Белки на 100г", keyboardType: TextInputType.number, controller: state.proteinsController, ), SizedBox(height: 10.v), CustomTextFormField( hintText: "Жиры на 100г", keyboardType: TextInputType.number, controller: state.fatsController, ), SizedBox(height: 10.v), CustomTextFormField( hintText: "Углеводы на 100г", keyboardType: TextInputType.number, controller: state.carbsController, ), ], ), actions: [ TextButton( onPressed: popDialog(context), child: Text('Отмена'), ), TextButton( onPressed: triggerModeration( context, state.productNameController!.text, state.caloriesController!.text, state.proteinsController!.text, state.fatsController!.text, state.carbsController!.text, dialogContext, ), child: Text('Отправить'), ), ], ); }, ); } triggerModeration( BuildContext context, String name, String energyOn100gr, String proteinsOn100gr, String fatsOn100gr, String carbohydratesOn100gr, BuildContext dialogContext, ) { return () { // Call function to send moderation with the entered values context.read().add( SendModeration( name: name, energyOn100gr: energyOn100gr, proteinsOn100gr: proteinsOn100gr, fatsOn100gr: fatsOn100gr, carbohydratesOn100gr: carbohydratesOn100gr, ), ); Navigator.of(dialogContext).pop(); // Dismiss the dialog }; } popDialog(BuildContext dialogContext) { return () { Navigator.of(dialogContext) .pop(); // Dismiss the dialog on Cancel button press }; } changeSatiety(BuildContext context, int satiety) { return () { context.read().add(ChangeSatiety(satiety)); }; } selectProduct(AutocompleteOnSelected onSelected, String option, DiaryEditLoadedState state) { state.productNameController?.text = option; return () { onSelected(option); }; } getAutocomplete(BuildContext context, FocusNode focusNode) { return (value) { /*print(state.autocompleteList ?.map((dynamic item) => item as String) .toList());*/ if (value.length > 2) { context.read().add(ProductInput(value)); } }; } buildOptions(List _options) { return (TextEditingValue textEditingValue) { return _options.where((String option) { return true; }); }; } changeMeal(BuildContext context, DiaryEditLoadedState state) { return (value) { context .read() .add(ChangeMeal(meals: state.meals, value: value)); }; } changePortion(BuildContext context, DiaryEditLoadedState state) { return (value) { context.read().add(ChangePortion(value: value)); }; } _buildCarousel(BuildContext context, DiaryEditLoadedState state) { if (state.photos!.isEmpty) { return Text("Фото нет"); } else { return CarouselSlider( options: CarouselOptions(height: 340.0), items: state.photos!.map((photo) { return _buildPhoto( context, photo); // Assuming photos are stored as strings }).toList(), ); } } _buildProduct(BuildContext context, Map portion) { return Container( margin: EdgeInsets.symmetric(horizontal: 10.h), padding: EdgeInsets.symmetric( horizontal: 8.h, vertical: 6.v, ), decoration: AppDecoration.fillGray.copyWith( borderRadius: BorderRadiusStyle.roundedBorder5, ), child: Row( mainAxisAlignment: MainAxisAlignment.end, mainAxisSize: MainAxisSize.min, children: [ Padding( padding: EdgeInsets.only( left: 7.h, top: 5.v, ), child: Text( portion['product_name'].length > 8 ? portion['product_name'].substring(0, 8) : portion['product_name'], style: CustomTextStyles.titleMedium16, ), ), Padding( padding: EdgeInsets.only( left: 20.h, top: 3.v, bottom: 3.v, ), child: Text( portion['quantity'].toString() + ' ' + portion['portion'].toString().tr, ), ), Spacer(), GestureDetector( onTap: removePortion(context, portion), child: Padding( padding: const EdgeInsets.only(right: 10), child: Icon( Icons.close, color: appTheme.blueGray300, ), ), ), ], ), ); } _buildPhoto(BuildContext context, Map photo) { return Stack( children: [ Container( margin: EdgeInsets.symmetric(horizontal: 10.h, vertical: 10.h), decoration: AppDecoration.fillGray.copyWith( borderRadius: BorderRadiusStyle.roundedBorder5, ), child: Image.network( baseUrl + '/storage/' + 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, ), ), ), ), ], ); } removePortion(BuildContext context, Map portion) { return () { context.read().add(RemovePortionEvent(portion['id'])); }; } removePhoto(BuildContext context, Map photo) { return () { context .read() .add(RemoveImageEvent(photo['id'].toString(), photo['path'])); }; } _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( horizontal: 10.h, vertical: 16.v, ), decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.all(Radius.circular(12)), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 2, blurRadius: 5, offset: Offset(0, 3), ), ], ), child: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox(height: 3.v), Text( "Ваш КБЖУ", style: theme.textTheme.titleMedium, ), SizedBox(height: 8.v), Text( "От дневной суточной нормы", style: CustomTextStyles.bodyMediumBluegray800, ), SizedBox(height: 19.v), Align( alignment: Alignment.centerRight, child: Padding( padding: EdgeInsets.only( left: 30.h, right: 12.h, ), child: AspectRatio( aspectRatio: 1.5, child: BarChart( BarChartData( alignment: BarChartAlignment.spaceAround, barTouchData: BarTouchData(enabled: false), titlesData: FlTitlesData( show: true, bottomTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, //getTitlesWidget: (value, meta) => newMethod(value), ), ), ), borderData: FlBorderData(show: false), barGroups: [ BarChartGroupData( x: 0, barRods: [ BarChartRodData( toY: consumedValues[0] / recommendedValues[0] * 100, color: checkConsumedValues( [recommendedValues[0]], [consumedValues[1]]) ? Colors.red : Colors.blue, ), ], ), BarChartGroupData( x: 1, barRods: [ BarChartRodData( toY: consumedValues[1] / recommendedValues[1] * 100, color: checkConsumedValues( [recommendedValues[1]], [consumedValues[1]]) ? Colors.red : Colors.blue, ), ], ), BarChartGroupData( x: 2, barRods: [ BarChartRodData( toY: consumedValues[2] / recommendedValues[2] * 100, color: checkConsumedValues( [recommendedValues[2]], [consumedValues[2]]) ? Colors.red : Colors.blue, ), ], ), BarChartGroupData( x: 3, barRods: [ BarChartRodData( toY: consumedValues[3] / recommendedValues[3] * 100, color: checkConsumedValues( [recommendedValues[3]], [consumedValues[3]]) ? Colors.red : Colors.blue, ), ], ), ], ), ), ), ), ), SizedBox(height: 8.v), SizedBox(height: 2.v), Padding( padding: EdgeInsets.only( left: 10.h, right: 2.h, ), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Калорий", style: theme.textTheme.bodySmall, ), Padding( padding: EdgeInsets.only( left: 25.h, bottom: 11.v, ), child: Text( "Белков", style: theme.textTheme.bodySmall, ), ), Padding( padding: EdgeInsets.only( left: 19.h, bottom: 11.v, ), child: Text( "Жиров", style: theme.textTheme.bodySmall, ), ), Padding( padding: EdgeInsets.only( left: 14.h, bottom: 11.v, ), child: Text( "Углеводов", style: theme.textTheme.bodySmall, ), ), ], ), ), SizedBox(height: 2.v), Padding( padding: EdgeInsets.only( left: 10.h, right: 2.h, ), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "${consumedValues[0].toInt()} из ${recommendedValues[0].toInt()}", style: theme.textTheme.bodySmall, ), Padding( padding: EdgeInsets.only( left: 25.h, bottom: 11.v, ), child: Text( "${consumedValues[1].toInt()} из ${recommendedValues[1].toInt()}", style: theme.textTheme.bodySmall, ), ), Padding( padding: EdgeInsets.only( left: 19.h, bottom: 11.v, ), child: Text( "${consumedValues[2].toInt()} из ${recommendedValues[2].toInt()}", style: theme.textTheme.bodySmall, ), ), Padding( padding: EdgeInsets.only( left: 14.h, bottom: 11.v, ), child: Text( "${consumedValues[3].toInt()} из ${recommendedValues[3].toInt()}", style: theme.textTheme.bodySmall, ), ), ], ), ), SizedBox(height: 19.v), if (checkConsumedValues(recommendedValues, consumedValues)) Text( "*Превышенная суточная норма", style: theme.textTheme.labelLarge, ), ], ), ); } /// Section Widget _buildComment(BuildContext context, DiaryEditLoadedState state) { return Container( margin: EdgeInsets.symmetric(horizontal: 16.h), padding: EdgeInsets.symmetric( horizontal: 24.h, vertical: 12.v, ), decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.all(Radius.circular(12)), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 2, blurRadius: 5, offset: Offset(0, 3), ), ], ), child: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "Дополнительная информация для консультанта", style: theme.textTheme.titleMedium, textAlign: TextAlign.center, ), SizedBox(height: 20.v), Container( width: 320.h, child: CustomTextFormField( autofocus: false, hintText: "Введите информацию для консультанта", maxLines: 7, borderDecoration: InputBorder.none, controller: state.commentController, ), ), ], ), ); } _buildWakupRetire(BuildContext context, DiaryEditLoadedState state) { return Container( margin: EdgeInsets.symmetric(horizontal: 16.h), padding: EdgeInsets.symmetric( horizontal: 24.h, vertical: 12.v, ), decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.all(Radius.circular(12)), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 2, blurRadius: 5, offset: Offset(0, 3), ), ], ), child: Column( children: [ GestureDetector( onTap: toggleWakeup(context), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( r"Подъем \ отход ко сну", style: CustomTextStyles.bodyMediumBlack900, ), Icon(state.wakeupExpanded ? Icons.arrow_drop_up : Icons.arrow_drop_down), ], ), ), if (state.wakeupExpanded) Padding( padding: const EdgeInsets.only(left: 16.0), child: Column( children: [ SizedBox(height: 20.v), GestureDetector( onTap: () => _selectWakeupTime(context, state), child: AbsorbPointer( child: CustomTextFormField( hintText: state.wakeupController?.format(context).toString(), prefix: Icon(Icons.sunny), autofocus: false, ), ), ), SizedBox(height: 20.v), GestureDetector( onTap: () => _selectRetireTime(context, state), child: AbsorbPointer( child: CustomTextFormField( hintText: state.retireController?.format(context).toString(), prefix: Icon(Icons.bed), autofocus: false, ), ), ), SizedBox(height: 20.v), ], ), ), ], ), ); } toggleWakeup(BuildContext context) { return () { BlocProvider.of(context).add(ToggleWakeupExpandedEvent()); }; } /// Section Widget Function() onFinishDayPressed(BuildContext context) { return () { showDialog( context: context, builder: (BuildContext dialogContext) { return AlertDialog( title: Text("Подтвердите действие"), content: Text("Вы уверены, что хотите завершить день?"), actions: [ TextButton( child: Text("Отмена"), onPressed: closeDialog(dialogContext), ), TextButton( child: Text("Подтвердить"), onPressed: sendFinishDayData(dialogContext, context), ), ], ); }, ); }; } Function() sendFinishDayData( BuildContext dialogContext, BuildContext context) { return () { closeDialog(dialogContext); context.read().add(FinishDay()); }; } Function() closeDialog(BuildContext dialogContext) { return () { Navigator.of(dialogContext).pop(); }; } _buildMood(BuildContext context, DiaryEditLoadedState state) { return Container( margin: EdgeInsets.symmetric(horizontal: 16.h), padding: EdgeInsets.symmetric( horizontal: 24.h, vertical: 12.v, ), decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.all(Radius.circular(12)), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 2, blurRadius: 5, offset: Offset(0, 3), ), ], ), child: Column( children: [ GestureDetector( onTap: toggleMood(context), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Ваше настроение после приема пищи", style: CustomTextStyles.bodyMediumBlack900, ), Icon(state.moodExpanded ? Icons.arrow_drop_up : Icons.arrow_drop_down), ], ), ), if (state.moodExpanded) Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text("😭"), ScaleElement( color: Colors.red, isSelected: state.selectedMood == 0, onTap: changeMood(context, 0), ), ScaleElement( color: Colors.orange, isSelected: state.selectedMood == 1, onTap: changeMood(context, 1), ), ScaleElement( color: Colors.yellow, isSelected: state.selectedMood == 2, onTap: changeMood(context, 2), ), ScaleElement( color: Colors.lime, isSelected: state.selectedMood == 3, onTap: changeMood(context, 3), ), ScaleElement( color: Colors.lightGreen, isSelected: state.selectedMood == 4, onTap: changeMood(context, 4), ), ScaleElement( color: Colors.green, isSelected: state.selectedMood == 5, onTap: changeMood(context, 5), ), Text("😊"), // Остальные элементы шкалы ], ), ], ), ); } changeMood(BuildContext context, int satiety) { return () { context.read().add(ChangeMood(satiety)); }; } toggleMood(BuildContext context) { return () { BlocProvider.of(context).add(ToggleMoodExpandedEvent()); }; } Future _selectWakeupTime( BuildContext context, DiaryEditLoadedState state) async { final TimeOfDay? pickedTime = await showTimePicker( context: context, initialTime: state.wakeupController ?? TimeOfDay.now(), ); if (pickedTime != null && pickedTime != state.wakeupController) { state.wakeupController = pickedTime; context.read().add(WakeupEvent(pickedTime)); } } Future _selectRetireTime( BuildContext context, DiaryEditLoadedState state) async { final TimeOfDay? pickedTime = await showTimePicker( context: context, initialTime: state.retireController ?? TimeOfDay.now(), ); if (pickedTime != null && pickedTime != state.retireController) { state.retireController = pickedTime; context.read().add(RetireEvent(pickedTime)); } } Future _selectMealTime( BuildContext context, DiaryEditLoadedState state) async { final TimeOfDay? pickedTime = await showTimePicker( context: context, initialTime: state.mealTimeController ?? TimeOfDay.now(), ); if (pickedTime != null && pickedTime != state.mealTimeController) { state.mealTimeController = pickedTime; context.read().add(ChangeMealTime(pickedTime)); } } } bool checkConsumedValues( List recommendedValues, List consumedValues) { for (int i = 0; i < recommendedValues.length; i++) { if (consumedValues[i] > recommendedValues[i]) { // Если хотя бы одно потребленное значение превышает рекомендованное return true; // Возвращаем false } } // Если ни одно потребленное значение не превышает рекомендованное с соответствующим индексом return false; // Возвращаем true } */