Merge pull request 'main' (#43) from main into mso7nueh-feat(chat)

Reviewed-on: maxxkim/eatvio_app#43
This commit is contained in:
2024-07-03 13:55:37 +00:00
11 changed files with 2502 additions and 553 deletions

View File

@@ -0,0 +1,116 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'diary_model.freezed.dart';
part 'diary_model.g.dart';
@freezed
class DiaryModel with _$DiaryModel {
const factory DiaryModel(
{required int id,
required DateTime date,
required DateTime wakeup,
required DateTime retire,
required int closed,
required String comment,
required List<Meals> meals}) = _DiaryModel;
factory DiaryModel.fromJson(Map<String, Object?> json) => _$DiaryModelFromJson(json);
}
class Meals {
int? id;
String? time;
int? type;
int? satiety;
int? mood;
List<Portions>? portions;
List<Photos>? photos;
Meals({this.id, this.time, this.type, this.satiety, this.mood, this.portions, this.photos});
Meals.fromJson(Map<String, dynamic> json) {
List<Portions> portions = [];
List<Photos> photos = [];
id = json['id'];
time = json['time'];
type = json['type'];
satiety = json['satiety'];
mood = json['mood'];
if (json['portions'] != null) {
json['portions'].forEach((v) {
portions.add(new Portions.fromJson(v));
});
}
if (json['photos'] != null) {
json['photos'].forEach((v) {
photos.add(new Photos.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['time'] = this.time;
data['type'] = this.type;
data['satiety'] = this.satiety;
data['mood'] = this.mood;
if (this.portions != null) {
data['portions'] = this.portions?.map((v) => v.toJson()).toList();
}
if (this.photos != null) {
data['photos'] = this.photos?.map((v) => v.toJson()).toList();
}
return data;
}
}
class Portions {
int? id;
String? productName;
int? quantity;
String? portion;
Portions({this.id, this.productName, this.quantity, this.portion});
Portions.fromJson(Map<String, dynamic> json) {
id = json['id'];
productName = json['product_name'];
quantity = json['quantity'];
portion = json['portion'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['product_name'] = this.productName;
data['quantity'] = this.quantity;
data['portion'] = this.portion;
return data;
}
}
class Photos {
int? id;
String? originalName;
String? path;
int? size;
Photos({this.id, this.originalName, this.path, this.size});
Photos.fromJson(Map<String, dynamic> json) {
id = json['id'];
originalName = json['original_name'];
path = json['path'];
size = json['size'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['original_name'] = this.originalName;
data['path'] = this.path;
data['size'] = this.size;
return data;
}
}

View File

@@ -0,0 +1,282 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'diary_model.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
DiaryModel _$DiaryModelFromJson(Map<String, dynamic> json) {
return _DiaryModel.fromJson(json);
}
/// @nodoc
mixin _$DiaryModel {
int get id => throw _privateConstructorUsedError;
DateTime get date => throw _privateConstructorUsedError;
DateTime get wakeup => throw _privateConstructorUsedError;
DateTime get retire => throw _privateConstructorUsedError;
int get closed => throw _privateConstructorUsedError;
String get comment => throw _privateConstructorUsedError;
List<Meals> get meals => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$DiaryModelCopyWith<DiaryModel> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $DiaryModelCopyWith<$Res> {
factory $DiaryModelCopyWith(
DiaryModel value, $Res Function(DiaryModel) then) =
_$DiaryModelCopyWithImpl<$Res, DiaryModel>;
@useResult
$Res call(
{int id,
DateTime date,
DateTime wakeup,
DateTime retire,
int closed,
String comment,
List<Meals> meals});
}
/// @nodoc
class _$DiaryModelCopyWithImpl<$Res, $Val extends DiaryModel>
implements $DiaryModelCopyWith<$Res> {
_$DiaryModelCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? date = null,
Object? wakeup = null,
Object? retire = null,
Object? closed = null,
Object? comment = null,
Object? meals = null,
}) {
return _then(_value.copyWith(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
date: null == date
? _value.date
: date // ignore: cast_nullable_to_non_nullable
as DateTime,
wakeup: null == wakeup
? _value.wakeup
: wakeup // ignore: cast_nullable_to_non_nullable
as DateTime,
retire: null == retire
? _value.retire
: retire // ignore: cast_nullable_to_non_nullable
as DateTime,
closed: null == closed
? _value.closed
: closed // ignore: cast_nullable_to_non_nullable
as int,
comment: null == comment
? _value.comment
: comment // ignore: cast_nullable_to_non_nullable
as String,
meals: null == meals
? _value.meals
: meals // ignore: cast_nullable_to_non_nullable
as List<Meals>,
) as $Val);
}
}
/// @nodoc
abstract class _$$DiaryModelImplCopyWith<$Res>
implements $DiaryModelCopyWith<$Res> {
factory _$$DiaryModelImplCopyWith(
_$DiaryModelImpl value, $Res Function(_$DiaryModelImpl) then) =
__$$DiaryModelImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{int id,
DateTime date,
DateTime wakeup,
DateTime retire,
int closed,
String comment,
List<Meals> meals});
}
/// @nodoc
class __$$DiaryModelImplCopyWithImpl<$Res>
extends _$DiaryModelCopyWithImpl<$Res, _$DiaryModelImpl>
implements _$$DiaryModelImplCopyWith<$Res> {
__$$DiaryModelImplCopyWithImpl(
_$DiaryModelImpl _value, $Res Function(_$DiaryModelImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? date = null,
Object? wakeup = null,
Object? retire = null,
Object? closed = null,
Object? comment = null,
Object? meals = null,
}) {
return _then(_$DiaryModelImpl(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
date: null == date
? _value.date
: date // ignore: cast_nullable_to_non_nullable
as DateTime,
wakeup: null == wakeup
? _value.wakeup
: wakeup // ignore: cast_nullable_to_non_nullable
as DateTime,
retire: null == retire
? _value.retire
: retire // ignore: cast_nullable_to_non_nullable
as DateTime,
closed: null == closed
? _value.closed
: closed // ignore: cast_nullable_to_non_nullable
as int,
comment: null == comment
? _value.comment
: comment // ignore: cast_nullable_to_non_nullable
as String,
meals: null == meals
? _value._meals
: meals // ignore: cast_nullable_to_non_nullable
as List<Meals>,
));
}
}
/// @nodoc
@JsonSerializable()
class _$DiaryModelImpl implements _DiaryModel {
const _$DiaryModelImpl(
{required this.id,
required this.date,
required this.wakeup,
required this.retire,
required this.closed,
required this.comment,
required final List<Meals> meals})
: _meals = meals;
factory _$DiaryModelImpl.fromJson(Map<String, dynamic> json) =>
_$$DiaryModelImplFromJson(json);
@override
final int id;
@override
final DateTime date;
@override
final DateTime wakeup;
@override
final DateTime retire;
@override
final int closed;
@override
final String comment;
final List<Meals> _meals;
@override
List<Meals> get meals {
if (_meals is EqualUnmodifiableListView) return _meals;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_meals);
}
@override
String toString() {
return 'DiaryModel(id: $id, date: $date, wakeup: $wakeup, retire: $retire, closed: $closed, comment: $comment, meals: $meals)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$DiaryModelImpl &&
(identical(other.id, id) || other.id == id) &&
(identical(other.date, date) || other.date == date) &&
(identical(other.wakeup, wakeup) || other.wakeup == wakeup) &&
(identical(other.retire, retire) || other.retire == retire) &&
(identical(other.closed, closed) || other.closed == closed) &&
(identical(other.comment, comment) || other.comment == comment) &&
const DeepCollectionEquality().equals(other._meals, _meals));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(runtimeType, id, date, wakeup, retire, closed,
comment, const DeepCollectionEquality().hash(_meals));
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$DiaryModelImplCopyWith<_$DiaryModelImpl> get copyWith =>
__$$DiaryModelImplCopyWithImpl<_$DiaryModelImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$DiaryModelImplToJson(
this,
);
}
}
abstract class _DiaryModel implements DiaryModel {
const factory _DiaryModel(
{required final int id,
required final DateTime date,
required final DateTime wakeup,
required final DateTime retire,
required final int closed,
required final String comment,
required final List<Meals> meals}) = _$DiaryModelImpl;
factory _DiaryModel.fromJson(Map<String, dynamic> json) =
_$DiaryModelImpl.fromJson;
@override
int get id;
@override
DateTime get date;
@override
DateTime get wakeup;
@override
DateTime get retire;
@override
int get closed;
@override
String get comment;
@override
List<Meals> get meals;
@override
@JsonKey(ignore: true)
_$$DiaryModelImplCopyWith<_$DiaryModelImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,31 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'diary_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$DiaryModelImpl _$$DiaryModelImplFromJson(Map<String, dynamic> json) =>
_$DiaryModelImpl(
id: (json['id'] as num).toInt(),
date: DateTime.parse(json['date'] as String),
wakeup: DateTime.parse(json['wakeup'] as String),
retire: DateTime.parse(json['retire'] as String),
closed: (json['closed'] as num).toInt(),
comment: json['comment'] as String,
meals: (json['meals'] as List<dynamic>)
.map((e) => Meals.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$$DiaryModelImplToJson(_$DiaryModelImpl instance) =>
<String, dynamic>{
'id': instance.id,
'date': instance.date.toIso8601String(),
'wakeup': instance.wakeup.toIso8601String(),
'retire': instance.retire.toIso8601String(),
'closed': instance.closed,
'comment': instance.comment,
'meals': instance.meals,
};

View File

@@ -0,0 +1,22 @@
/*import 'package:eatvio_app/core/app_export.dart';
import 'package:eatvio_app/features/diary/presentation/bloc/diary_state.dart';
import 'package:eatvio_app/features/diary/repositories/diary_repository.dart';
class DiaryCubit extends Cubit<DiaryState> {
final DiaryRepository blogPostRepository;
DiaryCubit({required this.blogPostRepository})
: super(const DiaryState.loading());
loadDiary(String blogPostID) async {
emit(const DiaryState.loading());
try {
final blogPost = await blogPostRepository.getDiary(blogPostID);
emit(DiaryState.loaded(blogPost: blogPost));
} catch (e) {
emit(DiaryState.error(errorMessage: e.toString()));
print(e);
}
}
}
*/

View File

@@ -0,0 +1,20 @@
/*import 'package:eatvio_app/features/diary/models/diary_model.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'diary_state.freezed.dart';
@freezed
abstract class DiaryState with _$DiaryState {
const factory DiaryState() = _DiaryState;
const factory DiaryState.loading() = DiaryStateLoading;
const factory DiaryState.loaded({
required DiaryModel blogPost,
}) = DiaryStateLoaded;
const factory DiaryState.error({
required String errorMessage,
}) = DiaryStateError;
}
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
/*import 'package:eatvio_app/features/diary/models/diary_model.dart';
import 'package:eatvio_app/features/diary/services/diary_service.dart';
class DiaryRepository {
final DiaryService blogPostService;
DiaryRepository({required this.blogPostService});
Future<DiaryModel> getDiary(String blogPostID) async {
try {
return await blogPostService.getDiary(blogPostID);
} catch (e) {
rethrow;
}
}
}
*/

View File

@@ -0,0 +1,14 @@
/*import 'package:dio/dio.dart';
import 'package:eatvio_app/features/diary/models/diary_model.dart';
import 'package:retrofit/retrofit.dart';
part 'diary_service.g.dart';
@RestApi()
abstract class DiaryService {
factory DiaryService(Dio dio, {String baseUrl}) = _DiaryService;
@GET('/feed/show/{id}')
Future<DiaryModel> getDiary(@Path() String id);
}
*/

View File

@@ -29,15 +29,18 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
on<AddPortionEvent>(_addPortion); //пользователь нажимает "Добавить продукт" on<AddPortionEvent>(_addPortion); //пользователь нажимает "Добавить продукт"
on<RemovePortionEvent>(_removePortion); on<RemovePortionEvent>(_removePortion);
on<RemoveImageEvent>( on<RemoveImageEvent>(
_removeImage,); // пользователь нажимает на крестик около продукта _removeImage,
); // пользователь нажимает на крестик около продукта
on<UploadImages>(_uploadImages); //пользователь нажимает "Добавить фото" on<UploadImages>(_uploadImages); //пользователь нажимает "Добавить фото"
on<AddComment>(_addComment); //пользователь нажимает "Добавить комментарий" on<AddComment>(_addComment); //пользователь нажимает "Добавить комментарий"
on<ProductInput>( on<ProductInput>(
_inputProduct,); //пользователь нажимает "Добавить комментарий" _inputProduct,
); //пользователь нажимает "Добавить комментарий"
on<FinishDay>(_finishDay); //пользователь нажимает "Добавить комментарий" on<FinishDay>(_finishDay); //пользователь нажимает "Добавить комментарий"
on<SendModeration>(_sendModeration); on<SendModeration>(_sendModeration);
on<RefreshEvent>( on<RefreshEvent>(
reloadScreen,); //пользователь нажимает "Добавить комментарий" reloadScreen,
); //пользователь нажимает "Добавить комментарий"
on<ClearInput>(_clearInput); on<ClearInput>(_clearInput);
} }
@@ -57,12 +60,14 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
final diary = await fetchDiaryData(token, diaryId); final diary = await fetchDiaryData(token, diaryId);
print("Screen load success"); print("Screen load success");
if (diary is Map<String, dynamic>) { if (diary is Map<String, dynamic>) {
print(diary);
final String diaryDate = diary['date'] ?? DateTime.now().toString(); final String diaryDate = diary['date'] ?? DateTime.now().toString();
final chartValues = await fetchChartValues(token, diaryId, emit); final chartValues = await fetchChartValues(token, diaryId, emit);
if (state is DiaryEditLoadedState) { if (state is DiaryEditLoadedState) {
// Если текущее состояние уже загружено, обновляем его // Если текущее состояние уже загружено, обновляем его
var currentState = state as DiaryEditLoadedState; var currentState = state as DiaryEditLoadedState;
emit((currentState).copyWith( emit(
(currentState).copyWith(
currentMeal: currentState.currentMeal, currentMeal: currentState.currentMeal,
wakeupExpanded: currentState.wakeupExpanded, wakeupExpanded: currentState.wakeupExpanded,
moodExpanded: currentState.moodExpanded, moodExpanded: currentState.moodExpanded,
@@ -84,20 +89,24 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
selectedMood: currentState.selectedMood, selectedMood: currentState.selectedMood,
diaryDate: currentState.diaryDate, diaryDate: currentState.diaryDate,
diaryId: currentState.diaryId, diaryId: currentState.diaryId,
productQuantityController: productQuantityController: currentState.productQuantityController,
currentState.productQuantityController,
recommendedChartValues: currentState.recommendedChartValues, recommendedChartValues: currentState.recommendedChartValues,
consumedChartValues: currentState.consumedChartValues, consumedChartValues: currentState.consumedChartValues,
autocompleteList: currentState.autocompleteList, autocompleteList: currentState.autocompleteList,
diaryEditModelObj: currentState.diaryEditModelObj,),); diaryEditModelObj: currentState.diaryEditModelObj,
),
);
} else { } else {
// Если текущее состояние - начальное, создаем новое загруженное состояние // Если текущее состояние - начальное, создаем новое загруженное состояние
final List<SelectionPopupModel> meals = final List<SelectionPopupModel> meals = fillMealList(diary['meals']);
fillMealList(diary['meals']); emit(
emit(DiaryEditLoadedState( DiaryEditLoadedState(
currentMeal: meals[0], currentMeal: meals[0],
portionController: SelectionPopupModel( portionController: SelectionPopupModel(
id: 0, title: "порций", isSelected: true,), id: 0,
title: "порций",
isSelected: true,
),
wakeupExpanded: true, wakeupExpanded: true,
moodExpanded: true, moodExpanded: true,
moderationExpanded: false, moderationExpanded: false,
@@ -109,12 +118,10 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
photos: diary['meals'][0]['photos'], photos: diary['meals'][0]['photos'],
wakeupController: toTime(diary['wakeup'] ?? "09:00"), wakeupController: toTime(diary['wakeup'] ?? "09:00"),
retireController: toTime(diary['retire'] ?? "23:00"), retireController: toTime(diary['retire'] ?? "23:00"),
mealTimeController: mealTimeController: toTime(diary['meals'][0]['time'] ?? "10:00"),
toTime(diary['meals'][0]['time'] ?? "10:00"),
selectedSatiety: diary['meals'][0]['satiety'], selectedSatiety: diary['meals'][0]['satiety'],
selectedMood: diary['meals'][0]['mood'], selectedMood: diary['meals'][0]['mood'],
commentController: commentController: TextEditingController(text: diary['comment']),
TextEditingController(text: diary['comment']),
productNameController: TextEditingController(), productNameController: TextEditingController(),
productQuantityController: TextEditingController(), productQuantityController: TextEditingController(),
caloriesController: TextEditingController(), caloriesController: TextEditingController(),
@@ -124,8 +131,9 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
diaryId: diaryId, diaryId: diaryId,
diaryDate: diaryDate, diaryDate: diaryDate,
autocompleteList: [], autocompleteList: [],
diaryEditModelObj: state.diaryEditModelObj diaryEditModelObj: state.diaryEditModelObj?.copyWith(mealList: meals, portionList: fillPortions()),
?.copyWith(mealList: meals, portionList: fillPortions()),),); ),
);
} }
} }
} catch (e) { } catch (e) {
@@ -177,31 +185,33 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
} }
fetchChartValues( fetchChartValues(
String token, int diaryID, Emitter<DiaryEditState> emit,) async { String token,
int diaryID,
Emitter<DiaryEditState> emit,
) async {
final responseChart = await http.get( final responseChart = await http.get(
Uri.parse( Uri.parse(
dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/dailyNutritionData/',), dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/dailyNutritionData/',
),
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Authorization': 'Bearer $token', 'Authorization': 'Bearer $token',
}, },
); );
if (responseChart.statusCode == 200) { if (responseChart.statusCode == 200) {
final recommendedChartValues = final responseBody = jsonDecode(responseChart.body);
jsonDecode(responseChart.body)['dailyNutritionRecommendation']
.values final recommendedChartValues = responseBody['dailyNutritionRecommendation'].values.map<int>((value) => convertToInt(value)).toList();
.map<double>((value) => value as double)
.toList(); final consumedChartValues = responseBody['dailyNutritionIntake'].values.map<int>((value) => convertToInt(value)).toList();
final consumedChartValues =
jsonDecode(responseChart.body)['dailyNutritionIntake'] print([recommendedChartValues, consumedChartValues]);
.values
.map<double>((value) => value as double)
.toList();
return [recommendedChartValues, consumedChartValues]; return [recommendedChartValues, consumedChartValues];
} else { } else {
emit(DiaryEditErrorState('Ошибка при декодировании данных КБЖУ')); emit(DiaryEditErrorState('Ошибка при декодировании данных КБЖУ'));
print('fail'); print('fail');
return -1; return [[], []]; // Return empty lists instead of -1
} }
} }
@@ -249,8 +259,9 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
if (diary is Map<String, dynamic>) { if (diary is Map<String, dynamic>) {
final String diaryDate = diary['date'] ?? DateTime.now().toString(); final String diaryDate = diary['date'] ?? DateTime.now().toString();
final responseChart = await http.get( final responseChart = await http.get(
Uri.parse(dotenv.env['SERVER_ROOT']! + Uri.parse(
'/diary/$diaryId/dailyNutritionData/',), dotenv.env['SERVER_ROOT']! + '/diary/$diaryId/dailyNutritionData/',
),
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Authorization': 'Bearer $token', 'Authorization': 'Bearer $token',
@@ -258,39 +269,38 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
); );
if (responseChart.statusCode == 200) { if (responseChart.statusCode == 200) {
final recommendedChartValues = jsonDecode( final recommendedChartValues = jsonDecode(
responseChart.body,)['dailyNutritionRecommendation']; responseChart.body,
final consumedChartValues = )['dailyNutritionRecommendation'];
jsonDecode(responseChart.body)['dailyNutritionIntake']; final consumedChartValues = jsonDecode(responseChart.body)['dailyNutritionIntake'];
final List<SelectionPopupModel> meals = final List<SelectionPopupModel> meals = fillMealList(diary['meals']);
fillMealList(diary['meals']);
try { try {
await Future(() => emit(DiaryEditLoadedState( await Future(
() => emit(
DiaryEditLoadedState(
diaryEditModelObj: state.diaryEditModelObj?.copyWith( diaryEditModelObj: state.diaryEditModelObj?.copyWith(
mealList: meals, portionList: fillPortions(),), mealList: meals,
portionList: fillPortions(),
),
currentMeal: meals[0], currentMeal: meals[0],
portionController: SelectionPopupModel( portionController: SelectionPopupModel(
id: 0, title: "порций", isSelected: true,), id: 0,
title: "порций",
isSelected: true,
),
wakeupExpanded: true, wakeupExpanded: true,
moodExpanded: true, moodExpanded: true,
moderationExpanded: false, moderationExpanded: false,
token: token, token: token,
recommendedChartValues: recommendedChartValues.values recommendedChartValues: recommendedChartValues.values.map<int>((value) => convertToInt(value)).toList(),
.map<double>((value) => value as double) consumedChartValues: consumedChartValues.values.map<int>((value) => convertToInt(value)).toList(),
.toList(),
consumedChartValues: consumedChartValues.values
.map<double>((value) => value as double)
.toList(),
meals: diary['meals'],
portions: diary['meals'][0]['portions'], portions: diary['meals'][0]['portions'],
photos: diary['meals'][0]['photos'], photos: diary['meals'][0]['photos'],
wakeupController: toTime(diary['wakeup'] ?? "09:00"), wakeupController: toTime(diary['wakeup'] ?? "09:00"),
retireController: toTime(diary['retire'] ?? "23:00"), retireController: toTime(diary['retire'] ?? "23:00"),
mealTimeController: mealTimeController: toTime(diary['meals'][0]['time'] ?? "10:00"),
toTime(diary['meals'][0]['time'] ?? "10:00"),
selectedSatiety: diary['meals'][0]['satiety'], selectedSatiety: diary['meals'][0]['satiety'],
selectedMood: diary['meals'][0]['mood'], selectedMood: diary['meals'][0]['mood'],
commentController: commentController: TextEditingController(text: diary['comment']),
TextEditingController(text: diary['comment']),
productNameController: TextEditingController(), productNameController: TextEditingController(),
productQuantityController: TextEditingController(), productQuantityController: TextEditingController(),
caloriesController: TextEditingController(), caloriesController: TextEditingController(),
@@ -301,7 +311,9 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
diaryDate: diaryDate, diaryDate: diaryDate,
isLoading: false, isLoading: false,
autocompleteList: [], autocompleteList: [],
),),); ),
),
);
print("Updated"); print("Updated");
} catch (e) { } catch (e) {
@@ -311,12 +323,16 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
emit(DiaryEditErrorState('Ошибка при декодировании данных КБЖУ')); emit(DiaryEditErrorState('Ошибка при декодировании данных КБЖУ'));
} }
} else { } else {
emit(DiaryEditErrorState( emit(
'Ошибка при декодировании данных дневника',),); DiaryEditErrorState(
'Ошибка при декодировании данных дневника',
),
);
} }
} else { } else {
emit( emit(
DiaryEditErrorState('Некоторые необходимые данные отсутствуют.'),); DiaryEditErrorState('Некоторые необходимые данные отсутствуют.'),
);
} }
} else { } else {
emit(DiaryEditErrorState('Ошибка сервера: ${response.statusCode}')); emit(DiaryEditErrorState('Ошибка сервера: ${response.statusCode}'));
@@ -327,18 +343,20 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
} }
Future<void> _changeSatiety( Future<void> _changeSatiety(
ChangeSatiety event, Emitter<DiaryEditState> emit,) async { ChangeSatiety event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) { if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState; var currentState = state as DiaryEditLoadedState;
var updatedState = var updatedState = currentState.copyWith(selectedSatiety: event.selectedElement);
currentState.copyWith(selectedSatiety: event.selectedElement);
// Отправляем данные по HTTP маршруту и ждем ответ // Отправляем данные по HTTP маршруту и ждем ответ
var response = await sendSatietyData( var response = await sendSatietyData(
currentState.token, currentState.token,
event.selectedElement, event.selectedElement,
currentState.currentMeal?.id, currentState.currentMeal?.id,
currentState.diaryId,); currentState.diaryId,
);
if (response.statusCode == 200) { if (response.statusCode == 200) {
updatedState.selectedSatiety = event.selectedElement; updatedState.selectedSatiety = event.selectedElement;
@@ -353,38 +371,42 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
int? mealID, int? mealID,
int diaryID, int diaryID,
) async { ) async {
String url = dotenv.env['SERVER_ROOT']! + String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/meal/$mealID/satiety/fill';
'/diary/$diaryID/meal/$mealID/satiety/fill';
final Map<String, dynamic> credentials = { final Map<String, dynamic> credentials = {
'satiety': selectedSatiety, 'satiety': selectedSatiety,
}; };
var response = await http.post(Uri.parse(url), var response = await http.post(
headers: { Uri.parse(url),
'Content-Type': 'application/json', headers: {
'Authorization': 'Bearer $token', 'Content-Type': 'application/json',
}, 'Authorization': 'Bearer $token',
body: json.encode(credentials), },
encoding: utf8,); body: json.encode(credentials),
encoding: utf8,
);
return response; return response;
} }
Future<void> _changeMood( Future<void> _changeMood(
ChangeMood event, Emitter<DiaryEditState> emit,) async { ChangeMood event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) { if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState; var currentState = state as DiaryEditLoadedState;
var updatedState = var updatedState = currentState.copyWith(selectedMood: event.selectedElement);
currentState.copyWith(selectedMood: event.selectedElement);
// Отправляем данные по HTTP маршруту и ждем ответ // Отправляем данные по HTTP маршруту и ждем ответ
var response = await sendMoodData( var response = await sendMoodData(
currentState.token, currentState.token,
event.selectedElement, event.selectedElement,
currentState.currentMeal?.id, currentState.currentMeal?.id,
currentState.diaryId,); currentState.diaryId,
);
if (response.statusCode == 200) { if (response.statusCode == 200) {
print( print(
'Mood change success! meal_id: ${currentState.currentMeal?.id}, mood: ${event.selectedElement}',); 'Mood change success! meal_id: ${currentState.currentMeal?.id}, mood: ${event.selectedElement}',
);
updatedState.selectedMood = event.selectedElement; updatedState.selectedMood = event.selectedElement;
emit(updatedState); // Передаем обновленное состояние в emit emit(updatedState); // Передаем обновленное состояние в emit
} }
@@ -397,33 +419,38 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
int? mealID, int? mealID,
int diaryID, int diaryID,
) async { ) async {
String url = String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/meal/$mealID/mood/fill';
dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/meal/$mealID/mood/fill';
final Map<String, dynamic> credentials = { final Map<String, dynamic> credentials = {
'mood': selectedMood, 'mood': selectedMood,
}; };
var response = await http.post(Uri.parse(url), var response = await http.post(
headers: { Uri.parse(url),
'Content-Type': 'application/json', headers: {
'Authorization': 'Bearer $token', 'Content-Type': 'application/json',
}, 'Authorization': 'Bearer $token',
body: json.encode(credentials), },
encoding: utf8,); body: json.encode(credentials),
encoding: utf8,
);
return response; return response;
} }
FutureOr<void> _changeWakeup( FutureOr<void> _changeWakeup(
WakeupEvent event, Emitter<DiaryEditState> emit,) async { WakeupEvent event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) { if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState; var currentState = state as DiaryEditLoadedState;
var response = await sendWakeupData( var response = await sendWakeupData(
currentState.token, event.selectedTime, currentState.diaryId,); currentState.token,
event.selectedTime,
currentState.diaryId,
);
if (response.statusCode == 200) { if (response.statusCode == 200) {
await reloadScreen(event, emit); await reloadScreen(event, emit);
var updatedState = var updatedState = currentState.copyWith(wakeupController: event.selectedTime);
currentState.copyWith(wakeupController: event.selectedTime);
print("Wakeup time changed to ${event.selectedTime}"); print("Wakeup time changed to ${event.selectedTime}");
emit(updatedState); // Передаем обновленное состояние в emit emit(updatedState); // Передаем обновленное состояние в emit
} else } else
@@ -432,15 +459,19 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
} }
FutureOr<void> _changeRetire( FutureOr<void> _changeRetire(
RetireEvent event, Emitter<DiaryEditState> emit,) async { RetireEvent event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) { if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState; var currentState = state as DiaryEditLoadedState;
var response = await sendRetireData( var response = await sendRetireData(
currentState.token, event.selectedTime, currentState.diaryId,); currentState.token,
event.selectedTime,
currentState.diaryId,
);
if (response.statusCode == 200) { if (response.statusCode == 200) {
await reloadScreen(event, emit); await reloadScreen(event, emit);
var updatedState = var updatedState = currentState.copyWith(retireController: event.selectedTime);
currentState.copyWith(retireController: event.selectedTime);
print("Retire time changed to ${event.selectedTime}"); print("Retire time changed to ${event.selectedTime}");
emit(updatedState); // Передаем обновленное состояние в emit emit(updatedState); // Передаем обновленное состояние в emit
} else } else
@@ -455,46 +486,53 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
) async { ) async {
String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/wakeUp/fill'; String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/wakeUp/fill';
final formatter = DateFormat('HH:mm'); final formatter = DateFormat('HH:mm');
final wakeupString = final wakeupString = formatter.format(DateTime(2022, 1, 1, wakeup.hour, wakeup.minute));
formatter.format(DateTime(2022, 1, 1, wakeup.hour, wakeup.minute));
final Map<String, dynamic> credentials = { final Map<String, dynamic> credentials = {
'wakeUp': wakeupString, 'wakeUp': wakeupString,
}; };
var response = await http.post(Uri.parse(url), var response = await http.post(
headers: { Uri.parse(url),
'Content-Type': 'application/json', headers: {
'Authorization': 'Bearer $token', 'Content-Type': 'application/json',
}, 'Authorization': 'Bearer $token',
body: json.encode(credentials), },
encoding: utf8,); body: json.encode(credentials),
encoding: utf8,
);
return response; return response;
} }
Future<http.Response> sendRetireData( Future<http.Response> sendRetireData(
String? token, TimeOfDay retire, int diaryID,) async { String? token,
TimeOfDay retire,
int diaryID,
) async {
String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/retire/fill'; String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/retire/fill';
final formatter = DateFormat('HH:mm'); final formatter = DateFormat('HH:mm');
final retireString = final retireString = formatter.format(DateTime(2022, 1, 1, retire.hour, retire.minute));
formatter.format(DateTime(2022, 1, 1, retire.hour, retire.minute));
final Map<String, dynamic> credentials = { final Map<String, dynamic> credentials = {
'retire': retireString, 'retire': retireString,
}; };
var response = await http.post(Uri.parse(url), var response = await http.post(
headers: { Uri.parse(url),
'Content-Type': 'application/json', headers: {
'Authorization': 'Bearer $token', 'Content-Type': 'application/json',
}, 'Authorization': 'Bearer $token',
body: json.encode(credentials), },
encoding: utf8,); body: json.encode(credentials),
encoding: utf8,
);
return response; return response;
} }
FutureOr<void> _changeMealTime( FutureOr<void> _changeMealTime(
ChangeMealTime event, Emitter<DiaryEditState> emit,) async { ChangeMealTime event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) { if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState; var currentState = state as DiaryEditLoadedState;
var updatedState = currentState.copyWith(mealTimeController: event.time); var updatedState = currentState.copyWith(mealTimeController: event.time);
@@ -516,51 +554,58 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
'diary_id': diaryID, 'diary_id': diaryID,
}; };
var response = await http.post(Uri.parse(url), var response = await http.post(
headers: { Uri.parse(url),
'Content-Type': 'application/json', headers: {
'Authorization': 'Bearer $token', 'Content-Type': 'application/json',
}, 'Authorization': 'Bearer $token',
body: json.encode(credentials), },
encoding: utf8,); body: json.encode(credentials),
encoding: utf8,
);
return response; return response;
} }
FutureOr<void> _changeMeal( FutureOr<void> _changeMeal(
ChangeMeal event, Emitter<DiaryEditState> emit,) async { ChangeMeal event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) { if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState; var currentState = state as DiaryEditLoadedState;
final meal = currentState.meals?.firstWhere( final meal = currentState.meals?.firstWhere(
(meal) => meal['id'] == event.value.id, (meal) => meal['id'] == event.value.id,
orElse: () => null,); orElse: () => null,
);
int? id = event.value.id; int? id = event.value.id;
print(meal['photos']);
DiaryEditLoadedState updatedState = currentState.copyWith( DiaryEditLoadedState updatedState = currentState.copyWith(
currentMeal: event.value, currentMeal: event.value,
portions: meal['portions'], portions: meal['portions'],
photos: meal['photos'], photos: meal['photos'],
mealTimeController: toTime(meal['time'] ?? "1$id:00"), mealTimeController: toTime(meal['time'] ?? "1$id:00"),
selectedMood: meal['mood'], selectedMood: meal['mood'],
selectedSatiety: meal['satiety'],); selectedSatiety: meal['satiety'],
);
print(updatedState.photos); print(updatedState.photos);
emit(updatedState); emit(updatedState);
} }
} }
FutureOr<void> _clearInput( FutureOr<void> _clearInput(
ClearInput event, Emitter<DiaryEditState> emit,) { ClearInput event,
Emitter<DiaryEditState> emit,
) {
if (state is DiaryEditLoadedState) { if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState; var currentState = state as DiaryEditLoadedState;
DiaryEditLoadedState updatedState = currentState.copyWith( DiaryEditLoadedState updatedState = currentState.copyWith();
);
emit(updatedState); emit(updatedState);
} }
} }
FutureOr<void> _changePortion( FutureOr<void> _changePortion(
ChangePortion event, Emitter<DiaryEditState> emit,) { ChangePortion event,
Emitter<DiaryEditState> emit,
) {
if (state is DiaryEditLoadedState) { if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState; var currentState = state as DiaryEditLoadedState;
DiaryEditLoadedState updatedState = currentState.copyWith( DiaryEditLoadedState updatedState = currentState.copyWith(
@@ -571,7 +616,9 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
} }
FutureOr<void> _toggleMood( FutureOr<void> _toggleMood(
ToggleMoodExpandedEvent event, Emitter<DiaryEditState> emit,) { ToggleMoodExpandedEvent event,
Emitter<DiaryEditState> emit,
) {
if (state is DiaryEditLoadedState) { if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState; var currentState = state as DiaryEditLoadedState;
@@ -581,7 +628,9 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
} }
FutureOr<void> _toggleWakeup( FutureOr<void> _toggleWakeup(
ToggleWakeupExpandedEvent event, Emitter<DiaryEditState> emit,) { ToggleWakeupExpandedEvent event,
Emitter<DiaryEditState> emit,
) {
if (state is DiaryEditLoadedState) { if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState; var currentState = state as DiaryEditLoadedState;
@@ -591,7 +640,9 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
} }
FutureOr<void> _addPortion( FutureOr<void> _addPortion(
AddPortionEvent event, Emitter<DiaryEditState> emit,) async { AddPortionEvent event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) { if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState; var currentState = state as DiaryEditLoadedState;
@@ -609,15 +660,21 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
await reloadScreen(event, emit); await reloadScreen(event, emit);
} else { } else {
print( print(
'Failed to add portion. Status Code: ${response.statusCode} ${response.body}',); 'Failed to add portion. Status Code: ${response.statusCode} ${response.body}',
);
} }
} }
} }
FutureOr<http.Response> sendPortionData(String? token, String? name, FutureOr<http.Response> sendPortionData(
String portion, int? quantity, int? mealID, int diaryID,) async { String? token,
String url = String? name,
'${dotenv.env['SERVER_ROOT']!}/diary/$diaryID/meal/$mealID/portions/create'; String portion,
int? quantity,
int? mealID,
int diaryID,
) async {
String url = '${dotenv.env['SERVER_ROOT']!}/diary/$diaryID/meal/$mealID/portions/create';
final Map<String, dynamic> credentials = { final Map<String, dynamic> credentials = {
'product_name': name, 'product_name': name,
@@ -639,14 +696,17 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
} }
Future<void> _inputProduct( Future<void> _inputProduct(
ProductInput event, Emitter<DiaryEditState> emit,) async { ProductInput event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) { if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState; var currentState = state as DiaryEditLoadedState;
String? token = currentState.token; String? token = currentState.token;
final Map<String, dynamic> credentials = {'name': event.input}; final Map<String, dynamic> credentials = {'name': event.input};
final uri = Uri.parse( final uri = Uri.parse(
'${dotenv.env['SERVER_ROOT']!}/diary/product_nutritional_values/filter?${Uri(queryParameters: credentials).query}',); '${dotenv.env['SERVER_ROOT']!}/diary/product_nutritional_values/filter?${Uri(queryParameters: credentials).query}',
);
final response = await http.get( final response = await http.get(
uri, uri,
@@ -656,16 +716,13 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
}, },
); );
final productNutritionalValues = final productNutritionalValues = jsonDecode(response.body)['product_nutritional_value'];
jsonDecode(response.body)['product_nutritional_value'];
if (productNutritionalValues is List<dynamic>) { if (productNutritionalValues is List<dynamic>) {
// Create a new controller with the input text and update the autocomplete list // Create a new controller with the input text and update the autocomplete list
var updatedState = currentState.copyWith( var updatedState = currentState.copyWith(
productNameController: TextEditingController(text: event.input), productNameController: TextEditingController(text: event.input),
autocompleteList: productNutritionalValues autocompleteList: productNutritionalValues.map((product) => product['name']).toList(),
.map((product) => product['name'])
.toList(),
); );
if (event.input.length > 3) { if (event.input.length > 3) {
updatedState = updatedState.copyWith(moderationExpanded: true); updatedState = updatedState.copyWith(moderationExpanded: true);
@@ -679,12 +736,13 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
} }
Future<void> _removePortion( Future<void> _removePortion(
RemovePortionEvent event, Emitter<DiaryEditState> emit,) async { RemovePortionEvent event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) { if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState; var currentState = state as DiaryEditLoadedState;
int? mealId = int? mealId = currentState.currentMeal?.id; // Rename id to mealId for clarity
currentState.currentMeal?.id; // Rename id to mealId for clarity
var response = await sendRemovePortion( var response = await sendRemovePortion(
currentState.token, currentState.token,
@@ -697,15 +755,19 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
await reloadScreen(event, emit); await reloadScreen(event, emit);
} else { } else {
print( print(
'Failed to add portion. Status Code: ${response.statusCode} ${response.body}',); 'Failed to add portion. Status Code: ${response.statusCode} ${response.body}',
);
} }
} }
} }
Future<http.Response> sendRemovePortion( Future<http.Response> sendRemovePortion(
String? token, int? portionID, int? mealID, int diaryID,) async { String? token,
String url = int? portionID,
'${dotenv.env['SERVER_ROOT']!}/diary/$diaryID/meal/$mealID/portions/$portionID/delete'; int? mealID,
int diaryID,
) async {
String url = '${dotenv.env['SERVER_ROOT']!}/diary/$diaryID/meal/$mealID/portions/$portionID/delete';
var response = await http.delete( var response = await http.delete(
Uri.parse(url), Uri.parse(url),
@@ -720,7 +782,9 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
} }
FutureOr<void> _removeImage( FutureOr<void> _removeImage(
RemoveImageEvent event, Emitter<DiaryEditState> emit,) async { RemoveImageEvent event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) { if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState; var currentState = state as DiaryEditLoadedState;
@@ -736,15 +800,20 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
await reloadScreen(event, emit); await reloadScreen(event, emit);
} else { } else {
print( print(
'Failed to remove photo. Status Code: ${response.statusCode} ${response.body}',); 'Failed to remove photo. Status Code: ${response.statusCode} ${response.body}',
);
} }
} }
} }
Future<http.Response> sendRemovePhoto(String? token, String? path, Future<http.Response> sendRemovePhoto(
String? photoID, int? mealID, int diaryID,) async { String? token,
String url = String? path,
'${dotenv.env['SERVER_ROOT']!}/diary/$diaryID/meal/$mealID/photo/delete'; String? photoID,
int? mealID,
int diaryID,
) async {
String url = '${dotenv.env['SERVER_ROOT']!}/diary/$diaryID/meal/$mealID/photo/delete';
final Map<String, dynamic> credentials = { final Map<String, dynamic> credentials = {
'id': photoID, 'id': photoID,
'path': path, 'path': path,
@@ -780,13 +849,16 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
} }
} }
Future<http.Response> sendFinishDay(String? token, int diaryID, Future<http.Response> sendFinishDay(
TimeOfDay? wakeup, TimeOfDay? retire, String? comment,) async { String? token,
int diaryID,
TimeOfDay? wakeup,
TimeOfDay? retire,
String? comment,
) async {
final formatter = DateFormat('HH:mm'); final formatter = DateFormat('HH:mm');
final wakeupString = final wakeupString = formatter.format(DateTime(2022, 1, 1, wakeup!.hour, wakeup.minute));
formatter.format(DateTime(2022, 1, 1, wakeup!.hour, wakeup.minute)); final retireString = formatter.format(DateTime(2022, 1, 1, retire!.hour, retire.minute));
final retireString =
formatter.format(DateTime(2022, 1, 1, retire!.hour, retire.minute));
final Map<String, dynamic> credentials = { final Map<String, dynamic> credentials = {
'wakeup': wakeupString, 'wakeup': wakeupString,
@@ -810,21 +882,30 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
} }
Future<void> _uploadImages( Future<void> _uploadImages(
UploadImages event, Emitter<DiaryEditState> emit,) async { UploadImages event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) { if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState; var currentState = state as DiaryEditLoadedState;
emit(currentState.copyWith(isLoading: true)); emit(currentState.copyWith(isLoading: true));
await uploadImageToServer(event.image.path, currentState.diaryId, await uploadImageToServer(
currentState.currentMeal!.id!, currentState.token,); event.image.path,
currentState.diaryId,
currentState.currentMeal!.id!,
currentState.token,
);
await reloadScreen(event, emit); await reloadScreen(event, emit);
} }
} }
Future<String> uploadImageToServer( Future<String> uploadImageToServer(
String imagePath, int diaryID, int mealId, String? token,) async { String imagePath,
String url = int diaryID,
'${dotenv.env['SERVER_ROOT']!}/diary/$diaryID/meal/$mealId/photo/upload'; int mealId,
String? token,
) async {
String url = '${dotenv.env['SERVER_ROOT']!}/diary/$diaryID/meal/$mealId/photo/upload';
var request = http.MultipartRequest('POST', Uri.parse(url)); var request = http.MultipartRequest('POST', Uri.parse(url));
request.headers['Authorization'] = 'Bearer $token'; request.headers['Authorization'] = 'Bearer $token';
@@ -841,12 +922,15 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
return imageUrl; return imageUrl;
} else { } else {
throw Exception( throw Exception(
'Failed to upload image. Status code: ${streamedResponse.statusCode}}',); 'Failed to upload image. Status code: ${streamedResponse.statusCode}}',
);
} }
} }
FutureOr<void> _sendModeration( FutureOr<void> _sendModeration(
SendModeration event, Emitter<DiaryEditState> emit,) async { SendModeration event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) { if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState; var currentState = state as DiaryEditLoadedState;
final response = await _sendModerationData( final response = await _sendModerationData(
@@ -866,14 +950,16 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
} }
Future<http.Response> _sendModerationData( Future<http.Response> _sendModerationData(
String name, String name,
String energy_on_100gr, String energy_on_100gr,
String proteins_on_100gr, String proteins_on_100gr,
String fats_on_100gr, String fats_on_100gr,
String carbohydrates_on_100gr, String carbohydrates_on_100gr,
String? token,) async { String? token,
) async {
final Uri url = Uri.parse( final Uri url = Uri.parse(
'${dotenv.env['SERVER_ROOT']!}/diary/product_nutritional_values/sendToModeration',); '${dotenv.env['SERVER_ROOT']!}/diary/product_nutritional_values/sendToModeration',
);
final Uri serverURL = Uri.parse('${dotenv.env['SERVER_ROOT']!}'); final Uri serverURL = Uri.parse('${dotenv.env['SERVER_ROOT']!}');
String host = serverURL.host; String host = serverURL.host;
final Map<String, String> credentials = { final Map<String, String> credentials = {
@@ -901,12 +987,15 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
return response; return response;
} else { } else {
throw Exception( throw Exception(
'Failed to send a product for moderation ${response.statusCode}',); 'Failed to send a product for moderation ${response.statusCode}',
);
} }
} }
FutureOr<void> _addComment( FutureOr<void> _addComment(
AddComment event, Emitter<DiaryEditState> emit,) async { AddComment event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) { if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState; var currentState = state as DiaryEditLoadedState;
var updatedState = currentState.copyWith( var updatedState = currentState.copyWith(
@@ -915,7 +1004,10 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
// Отправляем данные по HTTP маршруту и ждем ответ // Отправляем данные по HTTP маршруту и ждем ответ
var response = await sendCommentData( var response = await sendCommentData(
currentState.token, event.comment, currentState.diaryId,); currentState.token,
event.comment,
currentState.diaryId,
);
if (response.statusCode == 200) { if (response.statusCode == 200) {
emit(updatedState); // Передаем обновленное состояние в emit emit(updatedState); // Передаем обновленное состояние в emit
@@ -924,19 +1016,24 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
} }
Future<http.Response> sendCommentData( Future<http.Response> sendCommentData(
String? token, String comment, int diaryID,) async { String? token,
String comment,
int diaryID,
) async {
String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/retire/fill'; String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/retire/fill';
final Map<String, dynamic> credentials = { final Map<String, dynamic> credentials = {
'comment': comment, 'comment': comment,
}; };
var response = await http.post(Uri.parse(url), var response = await http.post(
headers: { Uri.parse(url),
'Content-Type': 'application/json', headers: {
'Authorization': 'Bearer $token', 'Content-Type': 'application/json',
}, 'Authorization': 'Bearer $token',
body: json.encode(credentials), },
encoding: utf8,); body: json.encode(credentials),
encoding: utf8,
);
return response; return response;
} }
@@ -969,3 +1066,13 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
]; ];
} }
} }
int convertToInt(dynamic value) {
if (value is int) {
return value;
} else if (value is double) {
return value.toInt();
} else {
throw FormatException('Unexpected value type: ${value.runtimeType}');
}
}

View File

@@ -12,43 +12,42 @@ class DiaryEditState extends Equatable {
} }
class DiaryEditInitialState extends DiaryEditState { class DiaryEditInitialState extends DiaryEditState {
DiaryEditInitialState({required DiaryEditModel diaryEditModelObj}) DiaryEditInitialState({required DiaryEditModel diaryEditModelObj}) : super(diaryEditModelObj: diaryEditModelObj);
: super(diaryEditModelObj: diaryEditModelObj);
} }
/// Represents the state of DiaryEdit in the application. /// Represents the state of DiaryEdit in the application.
class DiaryEditLoadedState extends DiaryEditState { class DiaryEditLoadedState extends DiaryEditState {
DiaryEditLoadedState( DiaryEditLoadedState({
{this.diaryEditModelObj, this.diaryEditModelObj,
this.diaryDate, this.diaryDate,
this.token, this.token,
this.meals, this.meals,
this.portions, this.portions,
this.photos, this.photos,
this.autocompleteList, this.autocompleteList,
this.wakeupController, this.wakeupController,
this.retireController, this.retireController,
this.commentController, this.commentController,
this.mealTimeController, this.mealTimeController,
this.portionController, this.portionController,
this.productNameController, this.productNameController,
this.productQuantityController, this.productQuantityController,
this.selectedMood, this.selectedMood,
this.currentMeal, this.currentMeal,
this.caloriesController, this.caloriesController,
this.fatsController, this.fatsController,
this.proteinsController, this.proteinsController,
this.carbsController, this.carbsController,
this.isLoading = false, this.isLoading = false,
this.isAdded = false, this.isAdded = false,
required this.recommendedChartValues, required this.recommendedChartValues,
required this.consumedChartValues, required this.consumedChartValues,
required this.diaryId, required this.diaryId,
required this.selectedSatiety, required this.selectedSatiety,
required this.moderationExpanded, required this.moderationExpanded,
required this.wakeupExpanded, required this.wakeupExpanded,
required this.moodExpanded,}) required this.moodExpanded,
: super(diaryEditModelObj: null); }) : super(diaryEditModelObj: null);
DiaryEditModel? diaryEditModelObj; DiaryEditModel? diaryEditModelObj;
String? diaryDate; String? diaryDate;
@@ -57,8 +56,8 @@ class DiaryEditLoadedState extends DiaryEditState {
List<dynamic>? portions; List<dynamic>? portions;
List<dynamic>? photos; List<dynamic>? photos;
List<dynamic>? autocompleteList; List<dynamic>? autocompleteList;
List<double> recommendedChartValues; List<int> recommendedChartValues;
List<double> consumedChartValues; List<int> consumedChartValues;
SelectionPopupModel? currentMeal; SelectionPopupModel? currentMeal;
SelectionPopupModel? portionController; SelectionPopupModel? portionController;
TimeOfDay? wakeupController; TimeOfDay? wakeupController;
@@ -117,8 +116,8 @@ class DiaryEditLoadedState extends DiaryEditState {
SelectionPopupModel? portionController, SelectionPopupModel? portionController,
String? diaryDate, String? diaryDate,
String? token, String? token,
List<double>? recommendedChartValues, List<int>? recommendedChartValues,
List<double>? consumedChartValues, List<int>? consumedChartValues,
List<dynamic>? meals, List<dynamic>? meals,
List<dynamic>? portions, List<dynamic>? portions,
List<dynamic>? photos, List<dynamic>? photos,
@@ -143,38 +142,36 @@ class DiaryEditLoadedState extends DiaryEditState {
bool? isAdded, bool? isAdded,
}) { }) {
return DiaryEditLoadedState( return DiaryEditLoadedState(
diaryEditModelObj: diaryEditModelObj ?? this.diaryEditModelObj, diaryEditModelObj: diaryEditModelObj ?? this.diaryEditModelObj,
diaryDate: diaryDate ?? this.diaryDate, diaryDate: diaryDate ?? this.diaryDate,
token: token ?? this.token, token: token ?? this.token,
meals: meals ?? this.meals, meals: meals ?? this.meals,
photos: photos ?? this.photos, photos: photos ?? this.photos,
autocompleteList: autocompleteList ?? this.autocompleteList, autocompleteList: autocompleteList ?? this.autocompleteList,
portions: portions ?? this.portions, portions: portions ?? this.portions,
recommendedChartValues: recommendedChartValues: recommendedChartValues ?? this.recommendedChartValues,
recommendedChartValues ?? this.recommendedChartValues, consumedChartValues: consumedChartValues ?? this.consumedChartValues,
consumedChartValues: consumedChartValues ?? this.consumedChartValues, wakeupController: wakeupController ?? this.wakeupController,
wakeupController: wakeupController ?? this.wakeupController, retireController: retireController ?? this.retireController,
retireController: retireController ?? this.retireController, mealTimeController: mealTimeController ?? this.mealTimeController,
mealTimeController: mealTimeController ?? this.mealTimeController, commentController: commentController ?? this.commentController,
commentController: commentController ?? this.commentController, portionController: portionController ?? this.portionController,
portionController: portionController ?? this.portionController, productNameController: productNameController ?? this.productNameController,
productNameController: productQuantityController: productQuantityController ?? this.productQuantityController,
productNameController ?? this.productNameController, selectedMood: selectedMood ?? this.selectedMood,
productQuantityController: selectedSatiety: selectedSatiety ?? this.selectedSatiety,
productQuantityController ?? this.productQuantityController, diaryId: diaryId ?? this.diaryId,
selectedMood: selectedMood ?? this.selectedMood, currentMeal: currentMeal ?? this.currentMeal,
selectedSatiety: selectedSatiety ?? this.selectedSatiety, caloriesController: caloriesController ?? this.caloriesController,
diaryId: diaryId ?? this.diaryId, fatsController: fatsController ?? this.fatsController,
currentMeal: currentMeal ?? this.currentMeal, proteinsController: proteinsController ?? this.proteinsController,
caloriesController: caloriesController ?? this.caloriesController, carbsController: carbsController ?? this.carbsController,
fatsController: fatsController ?? this.fatsController, wakeupExpanded: wakeupExpanded ?? this.wakeupExpanded,
proteinsController: proteinsController ?? this.proteinsController, moderationExpanded: moderationExpanded ?? this.moderationExpanded,
carbsController: carbsController ?? this.carbsController, moodExpanded: moodExpanded ?? this.moodExpanded,
wakeupExpanded: wakeupExpanded ?? this.wakeupExpanded, isAdded: isAdded ?? this.isAdded,
moderationExpanded: moderationExpanded ?? this.moderationExpanded, isLoading: isLoading ?? this.isLoading,
moodExpanded: moodExpanded ?? this.moodExpanded, );
isAdded: isAdded ?? this.isAdded,
isLoading: isLoading ?? this.isLoading,);
} }
} }

View File

@@ -21,7 +21,9 @@ class DiaryEditScreen extends StatelessWidget {
static Widget builder(BuildContext context) { static Widget builder(BuildContext context) {
return BlocProvider<DiaryEditBloc>( return BlocProvider<DiaryEditBloc>(
create: (context) => DiaryEditBloc(DiaryEditState(diaryEditModelObj: DiaryEditModel()))..add(DiaryEditInitialEvent()), child: DiaryEditScreen(),); create: (context) => DiaryEditBloc(DiaryEditState(diaryEditModelObj: DiaryEditModel()))..add(DiaryEditInitialEvent()),
child: DiaryEditScreen(),
);
} }
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -264,237 +266,241 @@ class DiaryEditScreen extends StatelessWidget {
//print(_options); //print(_options);
FocusNode focusNodeName = FocusNode(); FocusNode focusNodeName = FocusNode();
return Container( return Container(
margin: EdgeInsets.symmetric(horizontal: 16.h), margin: EdgeInsets.symmetric(horizontal: 16.h),
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: 24.h, horizontal: 24.h,
vertical: 12.v, vertical: 12.v,
), ),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: const BorderRadius.all(Radius.circular(12)), borderRadius: const BorderRadius.all(Radius.circular(12)),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.grey.withOpacity(0.5), color: Colors.grey.withOpacity(0.5),
spreadRadius: 2, spreadRadius: 2,
blurRadius: 5, blurRadius: 5,
offset: Offset(0, 3), offset: Offset(0, 3),
), ),
], ],
), ),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Padding( Padding(
padding: EdgeInsets.symmetric(horizontal: 10.h), padding: EdgeInsets.symmetric(horizontal: 10.h),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text(
"Время приема пищи", "Время приема пищи",
style: CustomTextStyles.bodyMediumBlack900, style: CustomTextStyles.bodyMediumBlack900,
), ),
Expanded( Expanded(
// Adding Expanded widget // Adding Expanded widget
child: Padding( child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10.h), padding: EdgeInsets.symmetric(horizontal: 10.h),
child: ConstrainedBox( child: ConstrainedBox(
constraints: BoxConstraints( constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width - 260, maxWidth: MediaQuery.of(context).size.width - 260,
), ),
child: GestureDetector( child: GestureDetector(
onTap: () => _selectMealTime(context, state), onTap: () => _selectMealTime(context, state),
child: AbsorbPointer( child: AbsorbPointer(
child: CustomTextFormField( child: CustomTextFormField(
hintText: state.mealTimeController?.format(context).toString(), hintText: state.mealTimeController?.format(context).toString(),
autofocus: false, 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: 20.v), ),
Padding( SizedBox(height: 30.v),
padding: EdgeInsets.symmetric(horizontal: 10.h), _buildAddProduct(context, state),
child: BlocSelector<DiaryEditBloc, DiaryEditState, DiaryEditModel?>( SizedBox(height: 30.v),
selector: (state) => state.diaryEditModelObj, ...state.portions!.map((portion) => _buildProduct(context, portion)).toList(),
builder: (context, diaryEditModelObj) { SizedBox(height: 30.v),
return CustomDropDown( /*...state.photos != null
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 ? state.photos!.isEmpty
? [Text('Фото пока нет')] ? [Text('Фото пока нет')]
: state.photos! : state.photos!
.map((photo) => _buildPhoto(context, photo)) .map((photo) => _buildPhoto(context, photo))
.toList() .toList()
: [Text('Фото нет')],*/ : [Text('Фото нет')],*/
_buildCarousel(context, state), _buildCarousel(context, state),
SizedBox(height: 20.v), SizedBox(height: 20.v),
_buildAddPhoto(context, state), _buildAddPhoto(context, state),
SizedBox(height: 30.v), SizedBox(height: 30.v),
Text( Text(
"Ваша сытость после приёма пищи", "Ваша сытость после приёма пищи",
style: CustomTextStyles.bodyMediumBlack900, style: CustomTextStyles.bodyMediumBlack900,
), ),
SizedBox(height: 15.v), SizedBox(height: 15.v),
BlocBuilder<DiaryEditBloc, DiaryEditState>( BlocBuilder<DiaryEditBloc, DiaryEditState>(
builder: (context, state) { builder: (context, state) {
if (state is DiaryEditLoadedState) { if (state is DiaryEditLoadedState) {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text("😭"), Text("😭"),
ScaleElement( ScaleElement(
color: Colors.red, color: Colors.red,
isSelected: state.selectedSatiety == 0, isSelected: state.selectedSatiety == 0,
onTap: changeSatiety(context, 0), onTap: changeSatiety(context, 0),
), ),
ScaleElement( ScaleElement(
color: Colors.orange, color: Colors.orange,
isSelected: state.selectedSatiety == 1, isSelected: state.selectedSatiety == 1,
onTap: changeSatiety(context, 1), onTap: changeSatiety(context, 1),
), ),
ScaleElement( ScaleElement(
color: Colors.yellow, color: Colors.yellow,
isSelected: state.selectedSatiety == 2, isSelected: state.selectedSatiety == 2,
onTap: changeSatiety(context, 2), onTap: changeSatiety(context, 2),
), ),
ScaleElement( ScaleElement(
color: Colors.lime, color: Colors.lime,
isSelected: state.selectedSatiety == 3, isSelected: state.selectedSatiety == 3,
onTap: changeSatiety(context, 3), onTap: changeSatiety(context, 3),
), ),
ScaleElement( ScaleElement(
color: Colors.lightGreen, color: Colors.lightGreen,
isSelected: state.selectedSatiety == 4, isSelected: state.selectedSatiety == 4,
onTap: changeSatiety(context, 4), onTap: changeSatiety(context, 4),
), ),
ScaleElement( ScaleElement(
color: Colors.green, color: Colors.green,
isSelected: state.selectedSatiety == 5, isSelected: state.selectedSatiety == 5,
onTap: changeSatiety(context, 5), onTap: changeSatiety(context, 5),
), ),
Text("😊"), Text("😊"),
// Остальные элементы шкалы // Остальные элементы шкалы
], ],
); );
} else { } else {
return Container(); // Возвращаем пустой контейнер, если состояние не является DiaryEditLoadedState return Container(); // Возвращаем пустой контейнер, если состояние не является DiaryEditLoadedState
} }
}, },
), ),
], ],
),); ),
);
} }
openCaloriesDialog(BuildContext context, DiaryEditLoadedState state) { openCaloriesDialog(BuildContext context, DiaryEditLoadedState state) {
@@ -542,8 +548,15 @@ class DiaryEditScreen extends StatelessWidget {
child: Text('Отмена'), child: Text('Отмена'),
), ),
TextButton( TextButton(
onPressed: triggerModeration(context, state.productNameController!.text, state.caloriesController!.text, state.proteinsController!.text, onPressed: triggerModeration(
state.fatsController!.text, state.carbsController!.text, dialogContext,), context,
state.productNameController!.text,
state.caloriesController!.text,
state.proteinsController!.text,
state.fatsController!.text,
state.carbsController!.text,
dialogContext,
),
child: Text('Отправить'), child: Text('Отправить'),
), ),
], ],
@@ -552,12 +565,26 @@ class DiaryEditScreen extends StatelessWidget {
); );
} }
triggerModeration(BuildContext context, String name, String energyOn100gr, String proteinsOn100gr, String fatsOn100gr, String carbohydratesOn100gr, triggerModeration(
BuildContext dialogContext,) { BuildContext context,
String name,
String energyOn100gr,
String proteinsOn100gr,
String fatsOn100gr,
String carbohydratesOn100gr,
BuildContext dialogContext,
) {
return () { return () {
// Call function to send moderation with the entered values // Call function to send moderation with the entered values
context.read<DiaryEditBloc>().add(SendModeration( context.read<DiaryEditBloc>().add(
name: name, energyOn100gr: energyOn100gr, proteinsOn100gr: proteinsOn100gr, fatsOn100gr: fatsOn100gr, carbohydratesOn100gr: carbohydratesOn100gr,),); SendModeration(
name: name,
energyOn100gr: energyOn100gr,
proteinsOn100gr: proteinsOn100gr,
fatsOn100gr: fatsOn100gr,
carbohydratesOn100gr: carbohydratesOn100gr,
),
);
Navigator.of(dialogContext).pop(); // Dismiss the dialog Navigator.of(dialogContext).pop(); // Dismiss the dialog
}; };
} }
@@ -640,14 +667,15 @@ class DiaryEditScreen extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Padding( Padding(
padding: EdgeInsets.only( padding: EdgeInsets.only(
left: 7.h, left: 7.h,
top: 5.v, top: 5.v,
), ),
child: Text( 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, style: CustomTextStyles.titleMedium16,
),), ),
),
Padding( Padding(
padding: EdgeInsets.only( padding: EdgeInsets.only(
left: 20.h, left: 20.h,
@@ -660,14 +688,15 @@ class DiaryEditScreen extends StatelessWidget {
), ),
Spacer(), Spacer(),
GestureDetector( GestureDetector(
onTap: removePortion(context, portion), onTap: removePortion(context, portion),
child: Padding( child: Padding(
padding: const EdgeInsets.only(right: 10), padding: const EdgeInsets.only(right: 10),
child: Icon( child: Icon(
Icons.close, Icons.close,
color: appTheme.blueGray300, color: appTheme.blueGray300,
), ),
),), ),
),
], ],
), ),
); );
@@ -720,8 +749,8 @@ class DiaryEditScreen extends StatelessWidget {
} }
_buildNutritionChart(BuildContext context, DiaryEditLoadedState state) { _buildNutritionChart(BuildContext context, DiaryEditLoadedState state) {
final List<double> recommendedValues = state.recommendedChartValues; // Рекомендуемые значения: калории, жиры, белки, углеводы final List<int> recommendedValues = state.recommendedChartValues; // Рекомендуемые значения: калории, жиры, белки, углеводы
final List<double> consumedValues = state.consumedChartValues; // final List<int> consumedValues = state.consumedChartValues; //
return Container( return Container(
margin: EdgeInsets.symmetric(horizontal: 16.h), margin: EdgeInsets.symmetric(horizontal: 16.h),
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
@@ -779,30 +808,42 @@ class DiaryEditScreen extends StatelessWidget {
), ),
borderData: FlBorderData(show: false), borderData: FlBorderData(show: false),
barGroups: [ barGroups: [
BarChartGroupData(x: 0, barRods: [ BarChartGroupData(
BarChartRodData( x: 0,
toY: consumedValues[0] / recommendedValues[0] * 100, barRods: [
color: checkConsumedValues([recommendedValues[0]], [consumedValues[1]]) ? Colors.red : Colors.blue, 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: 1,
],), barRods: [
BarChartGroupData(x: 2, barRods: [ BarChartRodData(
BarChartRodData( toY: consumedValues[1] / recommendedValues[1] * 100,
toY: consumedValues[2] / recommendedValues[2] * 100, color: checkConsumedValues([recommendedValues[1]], [consumedValues[1]]) ? Colors.red : Colors.blue,
color: checkConsumedValues([recommendedValues[2]], [consumedValues[2]]) ? Colors.red : Colors.blue, ),
), ],
],), ),
BarChartGroupData(x: 3, barRods: [ BarChartGroupData(
BarChartRodData( x: 2,
toY: consumedValues[3] / recommendedValues[3] * 100, barRods: [
color: checkConsumedValues([recommendedValues[3]], [consumedValues[3]]) ? Colors.red : Colors.blue, 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,
),
],
),
], ],
), ),
), ),
@@ -1077,24 +1118,25 @@ class DiaryEditScreen extends StatelessWidget {
_buildMood(BuildContext context, DiaryEditLoadedState state) { _buildMood(BuildContext context, DiaryEditLoadedState state) {
return Container( return Container(
margin: EdgeInsets.symmetric(horizontal: 16.h), margin: EdgeInsets.symmetric(horizontal: 16.h),
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: 24.h, horizontal: 24.h,
vertical: 12.v, vertical: 12.v,
), ),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: const BorderRadius.all(Radius.circular(12)), borderRadius: const BorderRadius.all(Radius.circular(12)),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.grey.withOpacity(0.5), color: Colors.grey.withOpacity(0.5),
spreadRadius: 2, spreadRadius: 2,
blurRadius: 5, blurRadius: 5,
offset: Offset(0, 3), offset: Offset(0, 3),
), ),
], ],
), ),
child: Column(children: [ child: Column(
children: [
GestureDetector( GestureDetector(
onTap: toggleMood(context), onTap: toggleMood(context),
child: Row( child: Row(
@@ -1147,7 +1189,9 @@ class DiaryEditScreen extends StatelessWidget {
// Остальные элементы шкалы // Остальные элементы шкалы
], ],
), ),
],),); ],
),
);
} }
changeMood(BuildContext context, int satiety) { changeMood(BuildContext context, int satiety) {
@@ -1196,7 +1240,7 @@ class DiaryEditScreen extends StatelessWidget {
} }
} }
bool checkConsumedValues(List<double> recommendedValues, List<double> consumedValues) { bool checkConsumedValues(List<int> recommendedValues, List<int> consumedValues) {
for (int i = 0; i < recommendedValues.length; i++) { for (int i = 0; i < recommendedValues.length; i++) {
if (consumedValues[i] > recommendedValues[i]) { if (consumedValues[i] > recommendedValues[i]) {
// Если хотя бы одно потребленное значение превышает рекомендованное // Если хотя бы одно потребленное значение превышает рекомендованное