feat(feed, profile): добавлен переход на страинцу автора в посте, рецепте и дете. при нажатии на изображение в рецепте и диеты теперь переход на страницу с подробнее.

This commit is contained in:
mso7nueh
2024-08-14 11:34:29 +03:00
parent 1e992e9dd6
commit 919035a455
77 changed files with 3943 additions and 2745 deletions

View File

@@ -1,14 +1,16 @@
import 'dart:async';
import 'package:eatvio_app/features/diary/models/diary_model.dart';
import 'package:eatvio_app/features/diary/models/meal.dart';
import 'package:eatvio_app/features/diary/models/product.dart';
import 'package:eatvio_app/features/diary/presentation/bloc/diary_state.dart';
import 'package:eatvio_app/features/diary/repositories/diary_repository.dart';
import 'package:intl/intl.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import '/core/app_export.dart';
import 'package:image_picker/image_picker.dart';
import 'package:eatvio_app/features/diary/presentation/bloc/diary_state.dart';
import 'package:intl/intl.dart';
import '/core/app_export.dart';
part 'diary_event.dart';
@@ -16,8 +18,7 @@ part 'diary_event.dart';
class DiaryBloc extends Bloc<DiaryEvent, DiaryState> {
final DiaryRepository diaryRepository;
DiaryBloc({required this.diaryRepository})
: super(const DiaryState.loading()) {
DiaryBloc({required this.diaryRepository}) : super(const DiaryState.loading()) {
on<LoadDiary>(loadDiary);
on<LoadDiaryById>(loadDiaryById);
on<ChangeSatiety>(_changeSatiety); // пользователь нажимает на шкалу сытости
@@ -55,29 +56,15 @@ class DiaryBloc extends Bloc<DiaryEvent, DiaryState> {
final DiaryModel diary = await diaryRepository.getDiary(diaryID ?? 45);
final Meal currentMeal = diary.meals[0];
List<SelectionPopupModel> portionList = [
SelectionPopupModel(title: "gr"),
SelectionPopupModel(title: "pcs")
];
List<SelectionPopupModel> portionList = [SelectionPopupModel(title: "gr"), SelectionPopupModel(title: "pcs")];
final Map<String, dynamic> chartData =
await diaryRepository.getChartData(diaryID ?? 45);
final Map<String, dynamic> dailyNutritionIntake =
chartData['dailyNutritionIntake']!;
final Map<String, dynamic> dailyNutritionRecommendations =
chartData['dailyNutritionRecommendation']!;
final double ccal = dailyNutritionIntake['energy']! /
dailyNutritionRecommendations['energy']! *
50;
final double proteins = dailyNutritionIntake['proteins']! /
dailyNutritionRecommendations['proteins']! *
50;
final double fats = dailyNutritionIntake['fats']! /
dailyNutritionRecommendations['fats']! *
50;
final double carbs = dailyNutritionIntake['carbohydrates']! /
dailyNutritionRecommendations['carbohydrates']! *
50;
final Map<String, dynamic> chartData = await diaryRepository.getChartData(diaryID ?? 45);
final Map<String, dynamic> dailyNutritionIntake = chartData['dailyNutritionIntake']!;
final Map<String, dynamic> dailyNutritionRecommendations = chartData['dailyNutritionRecommendation']!;
final double ccal = dailyNutritionIntake['energy']! / dailyNutritionRecommendations['energy']! * 50;
final double proteins = dailyNutritionIntake['proteins']! / dailyNutritionRecommendations['proteins']! * 50;
final double fats = dailyNutritionIntake['fats']! / dailyNutritionRecommendations['fats']! * 50;
final double carbs = dailyNutritionIntake['carbohydrates']! / dailyNutritionRecommendations['carbohydrates']! * 50;
Color getColor(double value) {
if (value >= 99.1) {
@@ -145,29 +132,15 @@ class DiaryBloc extends Bloc<DiaryEvent, DiaryState> {
final DiaryModel diary = await diaryRepository.getDiary(diaryID);
final Meal currentMeal = diary.meals[0];
List<SelectionPopupModel> portionList = [
SelectionPopupModel(title: "gr"),
SelectionPopupModel(title: "pcs")
];
List<SelectionPopupModel> portionList = [SelectionPopupModel(title: "gr"), SelectionPopupModel(title: "pcs")];
final Map<String, dynamic> chartData =
await diaryRepository.getChartData(diaryID);
final Map<String, dynamic> dailyNutritionIntake =
chartData['dailyNutritionIntake']!;
final Map<String, dynamic> dailyNutritionRecommendations =
chartData['dailyNutritionRecommendation']!;
final double ccal = dailyNutritionIntake['energy']! /
dailyNutritionRecommendations['energy']! *
50;
final double proteins = dailyNutritionIntake['proteins']! /
dailyNutritionRecommendations['proteins']! *
50;
final double fats = dailyNutritionIntake['fats']! /
dailyNutritionRecommendations['fats']! *
50;
final double carbs = dailyNutritionIntake['carbohydrates']! /
dailyNutritionRecommendations['carbohydrates']! *
50;
final Map<String, dynamic> chartData = await diaryRepository.getChartData(diaryID);
final Map<String, dynamic> dailyNutritionIntake = chartData['dailyNutritionIntake']!;
final Map<String, dynamic> dailyNutritionRecommendations = chartData['dailyNutritionRecommendation']!;
final double ccal = dailyNutritionIntake['energy']! / dailyNutritionRecommendations['energy']! * 50;
final double proteins = dailyNutritionIntake['proteins']! / dailyNutritionRecommendations['proteins']! * 50;
final double fats = dailyNutritionIntake['fats']! / dailyNutritionRecommendations['fats']! * 50;
final double carbs = dailyNutritionIntake['carbohydrates']! / dailyNutritionRecommendations['carbohydrates']! * 50;
Color getColor(double value) {
if (value >= 99.1) {
@@ -269,11 +242,9 @@ class DiaryBloc extends Bloc<DiaryEvent, DiaryState> {
) async {
if (state is DiaryStateLoaded) {
var currentState = state as DiaryStateLoaded;
var updatedState =
currentState.copyWith(wakeupController: event.selectedTime);
var updatedState = currentState.copyWith(wakeupController: event.selectedTime);
final DateFormat formatter = DateFormat('HH:mm');
final String wakeupString = formatter.format(DateTime(
2022, 1, 1, event.selectedTime.hour, event.selectedTime.minute));
final String wakeupString = formatter.format(DateTime(2022, 1, 1, event.selectedTime.hour, event.selectedTime.minute));
await diaryRepository.changeWakeup(
currentState.diary.id,
wakeupString,
@@ -288,11 +259,9 @@ class DiaryBloc extends Bloc<DiaryEvent, DiaryState> {
) async {
if (state is DiaryStateLoaded) {
var currentState = state as DiaryStateLoaded;
var updatedState =
currentState.copyWith(retireController: event.selectedTime);
var updatedState = currentState.copyWith(retireController: event.selectedTime);
final DateFormat formatter = DateFormat('HH:mm');
final String retireString = formatter.format(DateTime(
2022, 1, 1, event.selectedTime.hour, event.selectedTime.minute));
final String retireString = formatter.format(DateTime(2022, 1, 1, event.selectedTime.hour, event.selectedTime.minute));
await diaryRepository.changeRetire(
currentState.diary.id,
retireString,
@@ -318,8 +287,7 @@ class DiaryBloc extends Bloc<DiaryEvent, DiaryState> {
) async {
if (state is DiaryStateLoaded) {
final currentState = state as DiaryStateLoaded;
final Meal meal = currentState.diary.meals
.firstWhere((meal) => meal.type == event.value.id);
final Meal meal = currentState.diary.meals.firstWhere((meal) => meal.type == event.value.id);
DiaryStateLoaded updatedState = currentState.copyWith(
currentMeal: meal,
portions: meal.portions,
@@ -338,12 +306,10 @@ class DiaryBloc extends Bloc<DiaryEvent, DiaryState> {
if (state is DiaryStateLoaded) {
var currentState = state as DiaryStateLoaded;
final Map<String, List<Product>> productNutritionalValues =
await diaryRepository.inputProduct(event.input);
final Map<String, List<Product>> productNutritionalValues = await diaryRepository.inputProduct(event.input);
var updatedState = currentState.copyWith(
product_nameController: TextEditingController(text: event.input),
autocompleteList:
productNutritionalValues['product_nutritional_value'] ?? [],
autocompleteList: productNutritionalValues['product_nutritional_value'] ?? [],
);
if (event.input.length > 3) {
updatedState = updatedState.copyWith(moderationExpanded: true);

View File

@@ -19,7 +19,9 @@ class LoadDiaryById extends DiaryEvent {
LoadDiaryById(
this.id,
);
final String? id;
@override
List<Object?> get props => [];
}
@@ -28,7 +30,9 @@ class ChangeSatiety extends DiaryEvent {
ChangeSatiety(
this.selectedElement,
);
final int selectedElement;
@override
List<Object> get props => [selectedElement];
}
@@ -37,28 +41,35 @@ class ChangeMood extends DiaryEvent {
ChangeMood(
this.selectedElement,
);
final int selectedElement;
@override
List<Object> get props => [selectedElement];
}
class ChangeMealTime extends DiaryEvent {
ChangeMealTime(this.time);
final TimeOfDay time;
@override
List<Object> get props => [time];
}
class AddComment extends DiaryEvent {
AddComment(this.diaryId, this.comment);
final String comment;
final int diaryId;
@override
List<Object> get props => [comment, diaryId];
}
class WakeupEvent extends DiaryEvent {
WakeupEvent(this.selectedTime);
final TimeOfDay selectedTime;
@override
@@ -67,6 +78,7 @@ class WakeupEvent extends DiaryEvent {
class RetireEvent extends DiaryEvent {
RetireEvent(this.selectedTime);
final TimeOfDay selectedTime;
@override
@@ -85,62 +97,78 @@ class ToggleWakeupExpandedEvent extends DiaryEvent {
class AddPortionEvent extends DiaryEvent {
AddPortionEvent();
@override
List<Object> get props => [];
}
class RemovePortionEvent extends DiaryEvent {
RemovePortionEvent(this.portionId);
final int portionId;
@override
List<Object> get props => [portionId];
}
class UploadImages extends DiaryEvent {
UploadImages(this.image);
final XFile image;
@override
List<Object> get props => [image];
}
class RemoveImageEvent extends DiaryEvent {
RemoveImageEvent(this.photoID, this.path);
final String photoID;
final String path;
@override
List<Object> get props => [photoID, path];
}
class ProductInput extends DiaryEvent {
ProductInput(this.input);
final String input;
@override
List<Object> get props => [input];
}
class ChangeMeal extends DiaryEvent {
ChangeMeal({required this.value});
SelectionPopupModel value;
@override
List<Object?> get props => [value];
}
class ClearInput extends DiaryEvent {
ClearInput({required this.value});
TextEditingController value;
@override
List<Object?> get props => [value];
}
class ChangePortion extends DiaryEvent {
ChangePortion({required this.value});
SelectionPopupModel value;
@override
List<Object?> get props => [value];
}
class FinishDay extends DiaryEvent {
FinishDay();
@override
List<Object?> get props => [];
}
@@ -160,12 +188,13 @@ class SendModeration extends DiaryEvent {
required this.fatsOn100gr,
required this.carbohydratesOn100gr,
});
String name;
String energyOn100gr;
String proteinsOn100gr;
String fatsOn100gr;
String carbohydratesOn100gr;
@override
List<Object?> get props =>
[name, energyOn100gr, proteinsOn100gr, fatsOn100gr, carbohydratesOn100gr];
List<Object?> get props => [name, energyOn100gr, proteinsOn100gr, fatsOn100gr, carbohydratesOn100gr];
}

View File

@@ -1,6 +1,7 @@
// ignore_for_file: unused_local_variable
import 'package:carousel_slider_plus/carousel_slider_plus.dart';
import 'package:eatvio_app/core/app_export.dart';
import 'package:eatvio_app/features/diary/models/diary_model.dart';
import 'package:eatvio_app/features/diary/models/meal.dart';
import 'package:eatvio_app/features/diary/models/photo.dart';
@@ -8,15 +9,13 @@ import 'package:eatvio_app/features/diary/models/portion.dart';
import 'package:eatvio_app/features/diary/models/product.dart';
import 'package:eatvio_app/features/diary/presentation/bloc/diary_bloc.dart';
import 'package:eatvio_app/features/diary/presentation/bloc/diary_state.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_edit_text_form_field.dart';
import 'package:eatvio_app/widgets/custom_outlined_button.dart';
import 'package:eatvio_app/widgets/custom_scale_element.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:image_picker/image_picker.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
@@ -176,14 +175,10 @@ class DiaryScreen extends StatelessWidget {
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
'${state.chartData![3].nutrition.toStringAsFixed(0)}%'), // Калории
Text(
'${state.chartData![2].nutrition.toStringAsFixed(0)}%'), // Белки
Text(
'${state.chartData![1].nutrition.toStringAsFixed(0)}%'), // Жиры
Text(
'${state.chartData![0].nutrition.toStringAsFixed(0)}% '), // Углеводы
Text('${state.chartData![3].nutrition.toStringAsFixed(0)}%'), // Калории
Text('${state.chartData![2].nutrition.toStringAsFixed(0)}%'), // Белки
Text('${state.chartData![1].nutrition.toStringAsFixed(0)}%'), // Жиры
Text('${state.chartData![0].nutrition.toStringAsFixed(0)}% '), // Углеводы
],
),
],
@@ -329,9 +324,7 @@ class DiaryScreen extends StatelessWidget {
borderRadius: BorderRadiusStyle.roundedBorder5,
),
child: Center(
child: CircularProgressIndicator(
color: appTheme
.blueGray300), // Замените на свой прелоадер при необходимости
child: CircularProgressIndicator(color: appTheme.blueGray300), // Замените на свой прелоадер при необходимости
),
),
],
@@ -355,8 +348,7 @@ class DiaryScreen extends StatelessWidget {
_buildMeal(BuildContext context, DiaryStateLoaded state) {
final digitsOnly = FilteringTextInputFormatter.digitsOnly;
List<String> _options =
state.autocompleteList.map((Product item) => item.name).toList();
List<String> _options = state.autocompleteList.map((Product item) => item.name).toList();
FocusNode focusNodeName = FocusNode();
return Container(
margin: EdgeInsets.symmetric(horizontal: 16.h),
@@ -400,9 +392,7 @@ class DiaryScreen extends StatelessWidget {
onTap: () => _selectMealTime(context, state),
child: AbsorbPointer(
child: CustomTextFormField(
hintText: state.mealTimeController
?.format(context)
.toString(),
hintText: state.mealTimeController?.format(context).toString(),
autofocus: false,
),
),
@@ -538,9 +528,7 @@ class DiaryScreen extends StatelessWidget {
SizedBox(height: 30.v),
_buildAddProduct(context, state),
SizedBox(height: 30.v),
...state.portions
.map((portion) => _buildProduct(context, portion))
.toList(),
...state.portions.map((portion) => _buildProduct(context, portion)).toList(),
SizedBox(height: 30.v),
_buildCarousel(context, state),
SizedBox(height: 20.v),
@@ -689,8 +677,7 @@ class DiaryScreen extends StatelessWidget {
popDialog(BuildContext dialogContext) {
return () {
Navigator.of(dialogContext)
.pop(); // Dismiss the dialog on Cancel button press
Navigator.of(dialogContext).pop(); // Dismiss the dialog on Cancel button press
};
}
@@ -700,8 +687,7 @@ class DiaryScreen extends StatelessWidget {
};
}
selectProduct(AutocompleteOnSelected<String> onSelected, String option,
DiaryStateLoaded state) {
selectProduct(AutocompleteOnSelected<String> onSelected, String option, DiaryStateLoaded state) {
state.product_nameController.text = option;
return () {
onSelected(option);
@@ -769,9 +755,7 @@ class DiaryScreen extends StatelessWidget {
top: 5.v,
),
child: Text(
portion.product_name.length > 8
? portion.product_name.substring(0, 8)
: portion.product_name,
portion.product_name.length > 8 ? portion.product_name.substring(0, 8) : portion.product_name,
style: CustomTextStyles.titleMedium16,
),
),
@@ -843,9 +827,7 @@ class DiaryScreen extends StatelessWidget {
removePhoto(BuildContext context, Photo photo) {
return () {
context
.read<DiaryBloc>()
.add(RemoveImageEvent(photo.id.toString(), photo.path));
context.read<DiaryBloc>().add(RemoveImageEvent(photo.id.toString(), photo.path));
};
}
@@ -923,9 +905,7 @@ class DiaryScreen extends StatelessWidget {
r"Подъем \ отход ко сну",
style: CustomTextStyles.bodyMediumBlack900,
),
Icon(state.wakeupExpanded
? Icons.arrow_drop_up
: Icons.arrow_drop_down),
Icon(state.wakeupExpanded ? Icons.arrow_drop_up : Icons.arrow_drop_down),
],
),
),
@@ -939,8 +919,7 @@ class DiaryScreen extends StatelessWidget {
onTap: () => _selectWakeupTime(context, state),
child: AbsorbPointer(
child: CustomTextFormField(
hintText:
state.wakeupController.format(context).toString(),
hintText: state.wakeupController.format(context).toString(),
prefix: Icon(Icons.sunny),
autofocus: false,
),
@@ -951,8 +930,7 @@ class DiaryScreen extends StatelessWidget {
onTap: () => _selectRetireTime(context, state),
child: AbsorbPointer(
child: CustomTextFormField(
hintText:
state.retireController.format(context).toString(),
hintText: state.retireController.format(context).toString(),
prefix: Icon(Icons.bed),
autofocus: false,
),
@@ -999,8 +977,7 @@ class DiaryScreen extends StatelessWidget {
};
}
Function() sendFinishDayData(
BuildContext dialogContext, BuildContext context) {
Function() sendFinishDayData(BuildContext dialogContext, BuildContext context) {
return () {
closeDialog(dialogContext);
context.read<DiaryBloc>().add(FinishDay());
@@ -1043,9 +1020,7 @@ class DiaryScreen extends StatelessWidget {
"Ваше настроение после приема пищи",
style: CustomTextStyles.bodyMediumBlack900,
),
Icon(state.moodExpanded
? Icons.arrow_drop_up
: Icons.arrow_drop_down),
Icon(state.moodExpanded ? Icons.arrow_drop_up : Icons.arrow_drop_down),
],
),
),
@@ -1105,8 +1080,7 @@ class DiaryScreen extends StatelessWidget {
};
}
Future<void> _selectWakeupTime(
BuildContext context, DiaryStateLoaded state) async {
Future<void> _selectWakeupTime(BuildContext context, DiaryStateLoaded state) async {
final TimeOfDay? pickedTime = await showTimePicker(
context: context,
initialTime: state.wakeupController,
@@ -1116,8 +1090,7 @@ class DiaryScreen extends StatelessWidget {
}
}
Future<void> _selectRetireTime(
BuildContext context, DiaryStateLoaded state) async {
Future<void> _selectRetireTime(BuildContext context, DiaryStateLoaded state) async {
final TimeOfDay? pickedTime = await showTimePicker(
context: context,
initialTime: state.retireController,
@@ -1127,8 +1100,7 @@ class DiaryScreen extends StatelessWidget {
}
}
Future<void> _selectMealTime(
BuildContext context, DiaryStateLoaded state) async {
Future<void> _selectMealTime(BuildContext context, DiaryStateLoaded state) async {
final TimeOfDay? pickedTime = await showTimePicker(
context: context,
initialTime: state.mealTimeController ?? TimeOfDay.now(),
@@ -1139,8 +1111,7 @@ class DiaryScreen extends StatelessWidget {
}
}
bool checkConsumedValues(
List<int> recommendedValues, List<int> consumedValues) {
bool checkConsumedValues(List<int> recommendedValues, List<int> consumedValues) {
for (int i = 0; i < recommendedValues.length; i++) {
if (consumedValues[i] > recommendedValues[i]) {
// Если хотя бы одно потребленное значение превышает рекомендованное