forked from eatvio/eatvio_app
feat(diary): кбжу
This commit is contained in:
@@ -1,16 +1,15 @@
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/features/diary/models/diary_day_model.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/meal_summary_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class MealButtonWidget extends StatefulWidget {
|
||||
final int mealNumber;
|
||||
const MealButtonWidget({
|
||||
super.key,
|
||||
required this.mealNumber,
|
||||
});
|
||||
const MealButtonWidget({super.key, required this.mealNumber});
|
||||
|
||||
@override
|
||||
State<MealButtonWidget> createState() => _MealButtonWidgetState();
|
||||
@@ -22,9 +21,7 @@ class _MealButtonWidgetState extends State<MealButtonWidget> {
|
||||
return BlocBuilder<DiaryCubit, DiaryState>(
|
||||
builder: (context, state) {
|
||||
if (state is DiaryStateLoaded) {
|
||||
final consultantComment = state.consultantReview?.consultantComments.mealsComments.firstWhereOrNull(
|
||||
(element) => element.typeNo == widget.mealNumber,
|
||||
);
|
||||
final consultantComment = state.consultantReview?.consultantComments.mealsComments.firstWhereOrNull((element) => element.typeNo == widget.mealNumber);
|
||||
|
||||
final Color bgColor;
|
||||
if (state.selectedMeal == widget.mealNumber) {
|
||||
@@ -34,55 +31,84 @@ class _MealButtonWidgetState extends State<MealButtonWidget> {
|
||||
} else {
|
||||
bgColor = const Color(0xFFF1F2F6);
|
||||
}
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
context.read<DiaryCubit>().setSelectedMeal(widget.mealNumber);
|
||||
},
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
child: Ink(
|
||||
width: MediaQuery.of(context).size.width / 5 - (96 / 5),
|
||||
height: 32,
|
||||
decoration: BoxDecoration(
|
||||
|
||||
final mealIndex = widget.mealNumber - 1;
|
||||
final portions = mealIndex < state.diary.meals.length ? state.diary.meals[mealIndex].portions : <PortionModel>[];
|
||||
final totals = MealSummaryWidget.calculateMealTotals(portions);
|
||||
final calories = totals['calories']!.round();
|
||||
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
context.read<DiaryCubit>().setSelectedMeal(widget.mealNumber);
|
||||
},
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
color: bgColor,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'${widget.mealNumber}',
|
||||
style: TextStyle(
|
||||
color: state.selectedMeal == widget.mealNumber ? Colors.white : const Color(0xFF6D6F71),
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
child: Ink(
|
||||
width: MediaQuery.of(context).size.width / 5 - (96 / 5),
|
||||
height: 32,
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(100), color: bgColor),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'${widget.mealNumber}',
|
||||
style: TextStyle(
|
||||
color: state.selectedMeal == widget.mealNumber ? Colors.white : const Color(0xFF6D6F71),
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
calories > 0 ? '$calories ккал' : '— ккал',
|
||||
style: const TextStyle(color: Color(0xFF6D6F71), fontSize: 12, fontWeight: FontWeight.w500),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
if (state is DiaryStateLoadedTomorrowWithDiet) {
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
context.read<DiaryCubit>().setSelectedMeal(widget.mealNumber);
|
||||
},
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
child: Ink(
|
||||
width: MediaQuery.of(context).size.width / 5 - (96 / 5),
|
||||
height: 32,
|
||||
decoration: BoxDecoration(
|
||||
|
||||
final mealIndex = widget.mealNumber - 1;
|
||||
final portions = mealIndex < state.diary.meals.length ? state.diary.meals[mealIndex].portions : <PortionModel>[];
|
||||
final totals = MealSummaryWidget.calculateMealTotals(portions);
|
||||
final calories = totals['calories']!.round();
|
||||
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
context.read<DiaryCubit>().setSelectedMeal(widget.mealNumber);
|
||||
},
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
color: state.selectedMeal == widget.mealNumber ? appTheme.blueA400 : const Color(0xFFF1F2F6),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'${widget.mealNumber}',
|
||||
style: TextStyle(
|
||||
color: state.selectedMeal == widget.mealNumber ? Colors.white : const Color(0xFF6D6F71),
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
child: Ink(
|
||||
width: MediaQuery.of(context).size.width / 5 - (96 / 5),
|
||||
height: 32,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
color: state.selectedMeal == widget.mealNumber ? appTheme.blueA400 : const Color(0xFFF1F2F6),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'${widget.mealNumber}',
|
||||
style: TextStyle(
|
||||
color: state.selectedMeal == widget.mealNumber ? Colors.white : const Color(0xFF6D6F71),
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
calories > 0 ? '$calories ккал' : '— ккал',
|
||||
style: const TextStyle(color: Color(0xFF6D6F71), fontSize: 12, fontWeight: FontWeight.w500),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
|
||||
112
lib/features/diary/presentation/widgets/meal_summary_widget.dart
Normal file
112
lib/features/diary/presentation/widgets/meal_summary_widget.dart
Normal file
@@ -0,0 +1,112 @@
|
||||
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MealSummaryWidget extends StatelessWidget {
|
||||
final List<PortionModel> portions;
|
||||
final int mealNumber;
|
||||
|
||||
const MealSummaryWidget({super.key, required this.portions, required this.mealNumber});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final totals = _calculateTotals();
|
||||
|
||||
if (totals['calories'] == 0 && totals['proteins'] == 0 && totals['fats'] == 0 && totals['carbohydrates'] == 0) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(top: 8),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(color: const Color(0xFF2F80ED), width: 2),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Прием $mealNumber',
|
||||
style: const TextStyle(color: Color(0xFF323F4B), fontSize: 16, fontWeight: FontWeight.w600),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
_buildNutritionChip('К', totals['calories']!.round()),
|
||||
const SizedBox(width: 4),
|
||||
_buildNutritionChip('Б', totals['proteins']!.round()),
|
||||
const SizedBox(width: 4),
|
||||
_buildNutritionChip('Ж', totals['fats']!.round()),
|
||||
const SizedBox(width: 4),
|
||||
_buildNutritionChip('У', totals['carbohydrates']!.round()),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildNutritionChip(String label, int value) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
|
||||
decoration: BoxDecoration(color: const Color(0xFFF6FAFF), borderRadius: BorderRadius.circular(12)),
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: '$label ',
|
||||
style: const TextStyle(color: Color(0xFF2F80ED), fontSize: 12, fontWeight: FontWeight.w600),
|
||||
),
|
||||
TextSpan(
|
||||
text: '$value',
|
||||
style: const TextStyle(color: Color(0xFF6D6F71), fontSize: 12, fontWeight: FontWeight.w600),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, double> _calculateTotals() {
|
||||
return calculateMealTotals(portions);
|
||||
}
|
||||
|
||||
static Map<String, double> calculateMealTotals(List<PortionModel> portions) {
|
||||
double totalCalories = 0;
|
||||
double totalProteins = 0;
|
||||
double totalFats = 0;
|
||||
double totalCarbohydrates = 0;
|
||||
|
||||
for (final portion in portions) {
|
||||
if (portion.portionState == PortionState.eatenDeleted) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final caloriesInfo = portion.productCaloriesInfo;
|
||||
if (caloriesInfo == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double calories, proteins, fats, carbohydrates;
|
||||
|
||||
if (portion.portion == 'gr') {
|
||||
calories = (caloriesInfo.calories * portion.quantity) / 100;
|
||||
proteins = (caloriesInfo.proteins * portion.quantity) / 100;
|
||||
fats = (caloriesInfo.fats * portion.quantity) / 100;
|
||||
carbohydrates = (caloriesInfo.carbohydrates * portion.quantity) / 100;
|
||||
} else {
|
||||
calories = caloriesInfo.energyOnPortion;
|
||||
proteins = caloriesInfo.proteinsOnPortion;
|
||||
fats = caloriesInfo.fatsOnPortion;
|
||||
carbohydrates = caloriesInfo.carbohydratesOnPortion;
|
||||
}
|
||||
|
||||
totalCalories += calories;
|
||||
totalProteins += proteins;
|
||||
totalFats += fats;
|
||||
totalCarbohydrates += carbohydrates;
|
||||
}
|
||||
|
||||
return {'calories': totalCalories, 'proteins': totalProteins, 'fats': totalFats, 'carbohydrates': totalCarbohydrates};
|
||||
}
|
||||
}
|
||||
@@ -40,11 +40,7 @@ class _MealWidgetState extends State<MealWidget> {
|
||||
children: [
|
||||
const Text(
|
||||
'Прием пищи',
|
||||
style: TextStyle(
|
||||
color: Color(0xFF323F4B),
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
style: TextStyle(color: Color(0xFF323F4B), fontSize: 18, fontWeight: FontWeight.w500),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const Row(
|
||||
@@ -57,23 +53,17 @@ class _MealWidgetState extends State<MealWidget> {
|
||||
MealButtonWidget(mealNumber: 5),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
const SizedBox(height: 16),
|
||||
const TimeOfMealPickerWidget(),
|
||||
const ChosenDietWidget(),
|
||||
const ChosenPlanWidget(),
|
||||
const ProductsListWidget(),
|
||||
if (widget.showAddButton) ...[
|
||||
const SizedBox(height: 12),
|
||||
const AddProductButtonWidget(),
|
||||
],
|
||||
if (widget.showAddButton) ...[const SizedBox(height: 12), const AddProductButtonWidget()],
|
||||
const SizedBox(height: 12),
|
||||
const PhotoGalleryWidget(),
|
||||
const SizedBox(height: 12),
|
||||
const SatietyRatingWidget(),
|
||||
if (widget.showMood) ...[
|
||||
const SizedBox(height: 12),
|
||||
const MoodRatingWidget(),
|
||||
],
|
||||
if (widget.showMood) ...[const SizedBox(height: 12), const MoodRatingWidget()],
|
||||
BlocBuilder<DiaryCubit, DiaryState>(
|
||||
builder: (context, state) {
|
||||
if (state is DiaryStateLoaded && state.isConsultantView && !state.isDiaryCommented) {
|
||||
@@ -91,10 +81,7 @@ class _MealWidgetState extends State<MealWidget> {
|
||||
if (consultantCommentOfMeal != null) {
|
||||
return Column(
|
||||
children: [
|
||||
Text(
|
||||
'${s.mealComment} ${state.selectedMeal}',
|
||||
style: TextStyles.textLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
Text('${s.mealComment} ${state.selectedMeal}', style: TextStyles.textLSemibold.copyWith(color: appTheme.black)),
|
||||
const SizedBox(height: 12),
|
||||
CommentContainer(comment: consultantCommentOfMeal.comment),
|
||||
],
|
||||
@@ -103,7 +90,7 @@ class _MealWidgetState extends State<MealWidget> {
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:dotted_border/dotted_border.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
@@ -15,10 +16,7 @@ import 'package:flutter_svg/flutter_svg.dart';
|
||||
class ProductWidget extends StatefulWidget {
|
||||
final PortionModel portion;
|
||||
|
||||
const ProductWidget({
|
||||
super.key,
|
||||
required this.portion,
|
||||
});
|
||||
const ProductWidget({super.key, required this.portion});
|
||||
|
||||
@override
|
||||
State<ProductWidget> createState() => _ProductWidgetState();
|
||||
@@ -37,6 +35,60 @@ class _ProductWidgetState extends State<ProductWidget> {
|
||||
isEaten = widget.portion.portionState == PortionState.eatenFromDiet ? true : false;
|
||||
}
|
||||
|
||||
Widget _buildNutritionalInfo() {
|
||||
if (widget.portion.productNutritionalValueId == null) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(12)),
|
||||
child: const Text(
|
||||
'Продукт отправлен на модерацию',
|
||||
style: TextStyle(color: Color(0xFF2F80ED), fontSize: 12, fontWeight: FontWeight.w500),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final caloriesInfo = widget.portion.productCaloriesInfo;
|
||||
if (caloriesInfo == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
double calories, proteins, fats, carbohydrates;
|
||||
|
||||
if (widget.portion.portion == 'gr') {
|
||||
calories = (caloriesInfo.calories * widget.portion.quantity) / 100;
|
||||
proteins = (caloriesInfo.proteins * widget.portion.quantity) / 100;
|
||||
fats = (caloriesInfo.fats * widget.portion.quantity) / 100;
|
||||
carbohydrates = (caloriesInfo.carbohydrates * widget.portion.quantity) / 100;
|
||||
} else {
|
||||
calories = caloriesInfo.energyOnPortion;
|
||||
proteins = caloriesInfo.proteinsOnPortion;
|
||||
fats = caloriesInfo.fatsOnPortion;
|
||||
carbohydrates = caloriesInfo.carbohydratesOnPortion;
|
||||
}
|
||||
|
||||
return Row(
|
||||
children: [
|
||||
_buildNutritionChip('К', calories.round()),
|
||||
const SizedBox(width: 4),
|
||||
_buildNutritionChip('Б', proteins.round()),
|
||||
const SizedBox(width: 4),
|
||||
_buildNutritionChip('Ж', fats.round()),
|
||||
const SizedBox(width: 4),
|
||||
_buildNutritionChip('У', carbohydrates.round()),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildNutritionChip(String label, int value) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Text(
|
||||
'$label $value',
|
||||
style: const TextStyle(color: Color(0xFF6D6F71), fontSize: 12, fontWeight: FontWeight.w500),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(ProductWidget oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
@@ -48,15 +100,9 @@ class _ProductWidgetState extends State<ProductWidget> {
|
||||
return showModalBottomSheet(
|
||||
useRootNavigator: true,
|
||||
context: context,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(12)),
|
||||
),
|
||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(12))),
|
||||
isScrollControlled: true,
|
||||
builder: (context) => AddProductModal(
|
||||
state: state,
|
||||
portion: portion,
|
||||
diaryCubit: diaryCubit,
|
||||
),
|
||||
builder: (context) => AddProductModal(state: state, portion: portion, diaryCubit: diaryCubit),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -69,15 +115,21 @@ class _ProductWidgetState extends State<ProductWidget> {
|
||||
horizontalTitleGap: 0,
|
||||
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(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('${widget.portion.quantity} ${widget.portion.portion == 'gr' ? 'гр' : 'шт'}'),
|
||||
const SizedBox(height: 4),
|
||||
_buildNutritionalInfo(),
|
||||
],
|
||||
),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
||||
tileColor: const Color(0xFFF6FAFF),
|
||||
);
|
||||
}
|
||||
if (state is DiaryStateLoaded) {
|
||||
final isDiaryCommented = state.diary.typeOfDiary.diaryState == DiaryStateEnum.commented ||
|
||||
final isDiaryCommented =
|
||||
state.diary.typeOfDiary.diaryState == DiaryStateEnum.commented ||
|
||||
state.diary.typeOfDiary.diaryState == DiaryStateEnum.lastDayCommented ||
|
||||
state.diary.typeOfDiary.diaryState == DiaryStateEnum.reviewedByUser;
|
||||
final isDiaryFinished =
|
||||
@@ -99,21 +151,20 @@ class _ProductWidgetState extends State<ProductWidget> {
|
||||
color: Color(0xFF6D6F71),
|
||||
),
|
||||
child: ListTile(
|
||||
onTap: () => diaryCubit.restore(
|
||||
diaryId: state.diary.id,
|
||||
mealId: state.selectedMeal,
|
||||
portionId: widget.portion.id,
|
||||
),
|
||||
trailing: SvgPicture.asset(
|
||||
'assets/icons/revert_product.svg',
|
||||
),
|
||||
onTap: () => diaryCubit.restore(diaryId: state.diary.id, mealId: state.selectedMeal, portionId: widget.portion.id),
|
||||
trailing: SvgPicture.asset('assets/icons/revert_product.svg'),
|
||||
horizontalTitleGap: 0,
|
||||
contentPadding: widget.portion.fromDiet ? const EdgeInsets.only(right: 24, left: 4) : null,
|
||||
title: Text(widget.portion.productName),
|
||||
subtitle: Text('${widget.portion.quantity} ${widget.portion.portion == 'gr' ? 'гр' : 'шт'}'),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('${widget.portion.quantity} ${widget.portion.portion == 'gr' ? 'гр' : 'шт'}'),
|
||||
const SizedBox(height: 4),
|
||||
_buildNutritionalInfo(),
|
||||
],
|
||||
),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
||||
// ignore: use_full_hex_values_for_flutter_colors
|
||||
tileColor: const Color(0xfff6faff03).withValues(alpha: 0.01),
|
||||
),
|
||||
@@ -122,12 +173,13 @@ class _ProductWidgetState extends State<ProductWidget> {
|
||||
Widget? trailing;
|
||||
if (state.isConsultantView && !isDiaryCommented) {
|
||||
trailing = GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
showCommentWidget = !showCommentWidget;
|
||||
});
|
||||
},
|
||||
child: SvgPicture.asset('assets/icons/edit.svg'));
|
||||
onTap: () {
|
||||
setState(() {
|
||||
showCommentWidget = !showCommentWidget;
|
||||
});
|
||||
},
|
||||
child: SvgPicture.asset('assets/icons/edit.svg'),
|
||||
);
|
||||
} else if (!isDiaryCommented && !widget.portion.fromDiet) {
|
||||
trailing = const Icon(Icons.more_vert_rounded);
|
||||
}
|
||||
@@ -147,47 +199,36 @@ class _ProductWidgetState extends State<ProductWidget> {
|
||||
isEaten = value!;
|
||||
});
|
||||
if (isEaten) {
|
||||
diaryCubit.markEaten(
|
||||
diaryId: state.diary.id,
|
||||
mealId: state.selectedMeal,
|
||||
portionId: widget.portion.id,
|
||||
);
|
||||
diaryCubit.markEaten(diaryId: state.diary.id, mealId: state.selectedMeal, portionId: widget.portion.id);
|
||||
} else {
|
||||
diaryCubit.unmarkEaten(
|
||||
diaryId: state.diary.id,
|
||||
mealId: state.selectedMeal,
|
||||
portionId: widget.portion.id,
|
||||
);
|
||||
diaryCubit.unmarkEaten(diaryId: state.diary.id, mealId: state.selectedMeal, portionId: widget.portion.id);
|
||||
}
|
||||
}
|
||||
: null,
|
||||
activeColor: appTheme.blueA400,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
side: const BorderSide(
|
||||
color: Color(0xFF809CB9),
|
||||
),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)),
|
||||
side: const BorderSide(color: Color(0xFF809CB9)),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
horizontalTitleGap: 0,
|
||||
contentPadding: widget.portion.fromDiet ? const EdgeInsets.only(right: 24, left: 4) : null,
|
||||
title: Text(widget.portion.productName),
|
||||
subtitle: Text('${widget.portion.quantity} ${widget.portion.portion == 'gr' ? 'гр' : 'шт'}'),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('${widget.portion.quantity} ${widget.portion.portion == 'gr' ? 'гр' : 'шт'}'),
|
||||
const SizedBox(height: 4),
|
||||
_buildNutritionalInfo(),
|
||||
],
|
||||
),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
||||
tileColor: const Color(0xFFF6FAFF),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: PortionCommentWidget(
|
||||
enabled: showCommentWidget,
|
||||
portionId: widget.portion.id,
|
||||
comment: portionComment?.comment,
|
||||
),
|
||||
)
|
||||
child: PortionCommentWidget(enabled: showCommentWidget, portionId: widget.portion.id, comment: portionComment?.comment),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
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/meal_summary_widget.dart';
|
||||
import 'package:eatvio_app/features/diary/presentation/widgets/product_loader_widget.dart';
|
||||
import 'package:eatvio_app/features/diary/presentation/widgets/product_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -16,33 +17,33 @@ class _ProductsListWidgetState extends State<ProductsListWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<DiaryCubit, DiaryState>(
|
||||
builder: (BuildContext context, DiaryState state) {
|
||||
builder: (BuildContext context, DiaryState state) {
|
||||
if (state is DiaryStateLoaded) {
|
||||
int mealIndex = state.selectedMeal - 1;
|
||||
final portions = state.diary.meals[mealIndex].portions;
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
for (int i = 0; i < state.diary.meals[mealIndex].portions.length; i++) ...[
|
||||
ProductWidget(portion: state.diary.meals[mealIndex].portions[i]),
|
||||
i < state.diary.meals[mealIndex].portions.length - 1 ? const SizedBox(height: 8) : const SizedBox.shrink(),
|
||||
for (int i = 0; i < portions.length; i++) ...[
|
||||
ProductWidget(portion: portions[i]),
|
||||
i < portions.length - 1 ? const SizedBox(height: 8) : const SizedBox.shrink(),
|
||||
],
|
||||
if (state.isLoadingAddingProductInMeal)
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(top: 8),
|
||||
child: ProductLoaderWidget(),
|
||||
),
|
||||
if (portions.isNotEmpty) MealSummaryWidget(portions: portions, mealNumber: state.selectedMeal),
|
||||
if (state.isLoadingAddingProductInMeal) const Padding(padding: EdgeInsets.only(top: 8), child: ProductLoaderWidget()),
|
||||
],
|
||||
);
|
||||
}
|
||||
if (state is DiaryStateLoadedTomorrowWithDiet) {
|
||||
int mealIndex = state.selectedMeal - 1;
|
||||
final portions = state.diary.meals[mealIndex].portions;
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
for (int i = 0; i < state.diary.meals[mealIndex].portions.length; i++) ...[
|
||||
ProductWidget(portion: state.diary.meals[mealIndex].portions[i]),
|
||||
i < state.diary.meals[mealIndex].portions.length - 1 ? const SizedBox(height: 8) : const SizedBox.shrink(),
|
||||
for (int i = 0; i < portions.length; i++) ...[
|
||||
ProductWidget(portion: portions[i]),
|
||||
i < portions.length - 1 ? const SizedBox(height: 8) : const SizedBox.shrink(),
|
||||
],
|
||||
if (portions.isNotEmpty) MealSummaryWidget(portions: portions, mealNumber: state.selectedMeal),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user