Files
eatvio_app/lib/features/diary/presentation/pages/diary_screen.dart
2024-07-15 17:06:13 +03:00

1300 lines
43 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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<DiaryEditBloc>(
create: (context) =>
DiaryEditBloc(DiaryEditState(diaryEditModelObj: DiaryEditModel()))
..add(DiaryEditInitialEvent()),
child: DiaryEditScreen(),
);
}
Widget build(BuildContext context) {
return BlocBuilder<DiaryEditBloc, DiaryEditState>(
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<DiaryEditBloc>().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<DiaryEditBloc>().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<XFile>? images = await picker.pickMultiImage();
if (images.isNotEmpty) {
for (var image in images) {
context.read<DiaryEditBloc>().add(UploadImages(image));
}
}
};
}
}
_buildMeal(BuildContext context, DiaryEditLoadedState state) {
final digitsOnly = FilteringTextInputFormatter.digitsOnly;
List<String> _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<DiaryEditBloc, DiaryEditState, DiaryEditModel?>(
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<String>(
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<String> onSelected,
Iterable<String> 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: <TextInputFormatter>[digitsOnly],
),
Padding(
padding: EdgeInsets.only(left: 30.h),
child: BlocSelector<DiaryEditBloc, DiaryEditState,
DiaryEditModel?>(
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<DiaryEditBloc, DiaryEditState>(
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: <Widget>[
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<DiaryEditBloc>().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<DiaryEditBloc>().add(ChangeSatiety(satiety));
};
}
selectProduct(AutocompleteOnSelected<String> 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<DiaryEditBloc>().add(ProductInput(value));
}
};
}
buildOptions(List<String> _options) {
return (TextEditingValue textEditingValue) {
return _options.where((String option) {
return true;
});
};
}
changeMeal(BuildContext context, DiaryEditLoadedState state) {
return (value) {
context
.read<DiaryEditBloc>()
.add(ChangeMeal(meals: state.meals, value: value));
};
}
changePortion(BuildContext context, DiaryEditLoadedState state) {
return (value) {
context.read<DiaryEditBloc>().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<Widget>((photo) {
return _buildPhoto(
context, photo); // Assuming photos are stored as strings
}).toList(),
);
}
}
_buildProduct(BuildContext context, Map<String, dynamic> 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<String, dynamic> 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<String, dynamic> portion) {
return () {
context.read<DiaryEditBloc>().add(RemovePortionEvent(portion['id']));
};
}
removePhoto(BuildContext context, Map<String, dynamic> photo) {
return () {
context
.read<DiaryEditBloc>()
.add(RemoveImageEvent(photo['id'].toString(), photo['path']));
};
}
_buildNutritionChart(BuildContext context, DiaryEditLoadedState state) {
final List<int> recommendedValues = state
.recommendedChartValues; // Рекомендуемые значения: калории, жиры, белки, углеводы
final List<int> 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<DiaryEditBloc>(context).add(ToggleWakeupExpandedEvent());
};
}
/// Section Widget
Function() onFinishDayPressed(BuildContext context) {
return () {
showDialog(
context: context,
builder: (BuildContext dialogContext) {
return AlertDialog(
title: Text("Подтвердите действие"),
content: Text("Вы уверены, что хотите завершить день?"),
actions: <Widget>[
TextButton(
child: Text("Отмена"),
onPressed: closeDialog(dialogContext),
),
TextButton(
child: Text("Подтвердить"),
onPressed: sendFinishDayData(dialogContext, context),
),
],
);
},
);
};
}
Function() sendFinishDayData(
BuildContext dialogContext, BuildContext context) {
return () {
closeDialog(dialogContext);
context.read<DiaryEditBloc>().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<DiaryEditBloc>().add(ChangeMood(satiety));
};
}
toggleMood(BuildContext context) {
return () {
BlocProvider.of<DiaryEditBloc>(context).add(ToggleMoodExpandedEvent());
};
}
Future<void> _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<DiaryEditBloc>().add(WakeupEvent(pickedTime));
}
}
Future<void> _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<DiaryEditBloc>().add(RetireEvent(pickedTime));
}
}
Future<void> _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<DiaryEditBloc>().add(ChangeMealTime(pickedTime));
}
}
}
bool checkConsumedValues(
List<int> recommendedValues, List<int> consumedValues) {
for (int i = 0; i < recommendedValues.length; i++) {
if (consumedValues[i] > recommendedValues[i]) {
// Если хотя бы одно потребленное значение превышает рекомендованное
return true; // Возвращаем false
}
}
// Если ни одно потребленное значение не превышает рекомендованное с соответствующим индексом
return false; // Возвращаем true
}
*/