forked from eatvio/eatvio_app
refatcor(diary): Refactored (doesn't work yet though)
This commit is contained in:
845
lib/features/diary/presentation/bloc/diary_bloc.dart
Normal file
845
lib/features/diary/presentation/bloc/diary_bloc.dart
Normal file
@@ -0,0 +1,845 @@
|
||||
import 'dart:async';
|
||||
import 'package:eatvio_app/features/diary/models/diary_model.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:http/http.dart' as http;
|
||||
import 'dart:convert';
|
||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||
|
||||
part 'diary_event.dart';
|
||||
|
||||
/// A bloc that manages the state of a Diary according to the event that is dispatched to it.
|
||||
class DiaryBloc extends Bloc<DiaryEvent, DiaryState> {
|
||||
final DiaryRepository diaryRepository;
|
||||
|
||||
DiaryBloc({required this.diaryRepository})
|
||||
: super(const DiaryState.loading()) {
|
||||
on<LoadDiary>(loadDiary);
|
||||
on<ChangeSatiety>(_changeSatiety); // пользователь нажимает на шкалу сытости
|
||||
on<ChangeMood>(_changeMood); // пользователь нажимает на шкалу настроения
|
||||
on<ChangeMealTime>(_changeMealTime); // пользовательяет времяа пиши
|
||||
on<ChangeMeal>(_changeMeal);
|
||||
on<ChangePortion>(_changePortion);
|
||||
on<WakeupEvent>(_changeWakeup); // пользователь выбирает время пробуждения
|
||||
on<RetireEvent>(_changeRetire); // пользователь выбирает время отхода ко сну
|
||||
on<ToggleMoodExpandedEvent>(_toggleMood);
|
||||
on<ToggleWakeupExpandedEvent>(_toggleWakeup);
|
||||
on<AddPortionEvent>(_addPortion); //пользователь нажимает "Добавить продукт"
|
||||
on<RemovePortionEvent>(_removePortion);
|
||||
on<RemoveImageEvent>(
|
||||
_removeImage,
|
||||
); // пользователь нажимает на крестик около продукта
|
||||
on<UploadImages>(_uploadImages); //пользователь нажимает "Добавить фото"
|
||||
on<AddComment>(_addComment); //пользователь нажимает "Добавить комментарий"
|
||||
on<ProductInput>(
|
||||
_inputProduct,
|
||||
);
|
||||
on<FinishDay>(_finishDay);
|
||||
on<SendModeration>(_sendModeration);
|
||||
on<RefreshEvent>(
|
||||
reloadScreen,
|
||||
);
|
||||
on<ClearInput>(_clearInput);
|
||||
}
|
||||
|
||||
loadDiary(
|
||||
LoadDiary event,
|
||||
Emitter<DiaryState> emit,
|
||||
) async {
|
||||
emit(const DiaryState.loading());
|
||||
try {
|
||||
final diary =
|
||||
await diaryRepository.getDiary(await diaryRepository.getDiaryID());
|
||||
emit(DiaryState.loaded(
|
||||
diary: diary,
|
||||
commentController: TextEditingController(),
|
||||
productNameController: TextEditingController(),
|
||||
productQuantityController: TextEditingController(),
|
||||
caloriesController: TextEditingController(),
|
||||
fatsController: TextEditingController(),
|
||||
proteinsController: TextEditingController(),
|
||||
carbsController: TextEditingController(),
|
||||
wakeupExpanded: false,
|
||||
moderationExpanded: false,
|
||||
moodExpanded: false,
|
||||
isLoading: false,
|
||||
isAdded: false,
|
||||
recommendedChartValues: [0, 0, 0, 0],
|
||||
consumedChartValues: [0, 0, 0, 0]));
|
||||
} catch (e) {
|
||||
emit(DiaryState.error(errorMessage: e.toString()));
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
fetchChartValues(
|
||||
String token,
|
||||
int diaryID,
|
||||
Emitter<DiaryState> emit,
|
||||
) async {
|
||||
final responseChart = await http.get(
|
||||
Uri.parse(
|
||||
dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/dailyNutritionData/',
|
||||
),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer $token',
|
||||
},
|
||||
);
|
||||
|
||||
if (responseChart.statusCode == 200) {
|
||||
final responseBody = jsonDecode(responseChart.body);
|
||||
|
||||
final recommendedChartValues =
|
||||
responseBody['dailyNutritionRecommendation']
|
||||
.values
|
||||
.map<int>((value) => convertToInt(value))
|
||||
.toList();
|
||||
|
||||
final consumedChartValues = responseBody['dailyNutritionIntake']
|
||||
.values
|
||||
.map<int>((value) => convertToInt(value))
|
||||
.toList();
|
||||
|
||||
print([recommendedChartValues, consumedChartValues]);
|
||||
return [recommendedChartValues, consumedChartValues];
|
||||
} else {
|
||||
emit(DiaryStateError(
|
||||
errorMessage: 'Ошибка при декодировании данных КБЖУ'));
|
||||
print('fail');
|
||||
return [[], []]; // Return empty lists instead of -1
|
||||
}
|
||||
}
|
||||
|
||||
refreshScreen(
|
||||
int mealID,
|
||||
DiaryEvent event,
|
||||
Emitter<DiaryState> emit,
|
||||
) async {
|
||||
await reloadScreen(event, emit);
|
||||
}
|
||||
|
||||
reloadScreen(
|
||||
DiaryEvent event,
|
||||
Emitter<DiaryState> emit,
|
||||
) async {
|
||||
print("Reloading...");
|
||||
}
|
||||
|
||||
Future<void> _changeSatiety(
|
||||
ChangeSatiety event,
|
||||
Emitter<DiaryState> emit,
|
||||
) async {
|
||||
if (state is DiaryStateLoaded) {
|
||||
var currentState = state as DiaryStateLoaded;
|
||||
var updatedState =
|
||||
currentState.copyWith(selectedMood: event.selectedElement);
|
||||
|
||||
// Отправляем данные по HTTP маршруту и ждем ответ
|
||||
var response = await sendSatietyData(
|
||||
event.selectedElement,
|
||||
currentState.currentMeal?.id,
|
||||
currentState.diary.id,
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
print(
|
||||
'Satiety change success! meal_id: ${currentState.currentMeal?.id}, mood: ${event.selectedElement}',
|
||||
);
|
||||
emit(updatedState); // Передаем обновленное состояние в emit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<http.Response> sendSatietyData(
|
||||
int selectedSatiety,
|
||||
int? mealID,
|
||||
int diaryID,
|
||||
) async {
|
||||
String url = dotenv.env['SERVER_ROOT']! +
|
||||
'/diary/$diaryID/meal/$mealID/satiety/fill';
|
||||
final Map<String, dynamic> credentials = {
|
||||
'satiety': selectedSatiety,
|
||||
};
|
||||
var response = await http.post(
|
||||
Uri.parse(url),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: json.encode(credentials),
|
||||
encoding: utf8,
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
Future<void> _changeMood(
|
||||
ChangeMood event,
|
||||
Emitter<DiaryState> emit,
|
||||
) async {
|
||||
if (state is DiaryStateLoaded) {
|
||||
var currentState = state as DiaryStateLoaded;
|
||||
var updatedState =
|
||||
currentState.copyWith(selectedMood: event.selectedElement);
|
||||
|
||||
// Отправляем данные по HTTP маршруту и ждем ответ
|
||||
var response = await sendMoodData(
|
||||
event.selectedElement,
|
||||
currentState.currentMeal?.id,
|
||||
currentState.diary.id,
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
print(
|
||||
'Mood change success! meal_id: ${currentState.currentMeal?.id}, mood: ${event.selectedElement}',
|
||||
);
|
||||
emit(updatedState); // Передаем обновленное состояние в emit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<http.Response> sendMoodData(
|
||||
int selectedMood,
|
||||
int? mealID,
|
||||
int diaryID,
|
||||
) async {
|
||||
String url =
|
||||
dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/meal/$mealID/mood/fill';
|
||||
final Map<String, dynamic> credentials = {
|
||||
'mood': selectedMood,
|
||||
};
|
||||
|
||||
var response = await http.post(
|
||||
Uri.parse(url),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: json.encode(credentials),
|
||||
encoding: utf8,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
FutureOr<void> _changeWakeup(
|
||||
WakeupEvent event,
|
||||
Emitter<DiaryState> emit,
|
||||
) async {
|
||||
if (state is DiaryStateLoaded) {
|
||||
var currentState = state as DiaryStateLoaded;
|
||||
var response = await sendWakeupData(
|
||||
event.selectedTime,
|
||||
currentState.diary.id,
|
||||
);
|
||||
if (response.statusCode == 200) {
|
||||
await reloadScreen(event, emit);
|
||||
var updatedState =
|
||||
currentState.copyWith(wakeupController: event.selectedTime);
|
||||
print("Wakeup time changed to ${event.selectedTime}");
|
||||
emit(updatedState); // Передаем обновленное состояние в emit
|
||||
} else
|
||||
print("Wakeup time change error");
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _changeRetire(
|
||||
RetireEvent event,
|
||||
Emitter<DiaryState> emit,
|
||||
) async {
|
||||
if (state is DiaryStateLoaded) {
|
||||
var currentState = state as DiaryStateLoaded;
|
||||
var response = await sendRetireData(
|
||||
event.selectedTime,
|
||||
currentState.diary.id,
|
||||
);
|
||||
if (response.statusCode == 200) {
|
||||
await reloadScreen(event, emit);
|
||||
var updatedState =
|
||||
currentState.copyWith(retireController: event.selectedTime);
|
||||
print("Retire time changed to ${event.selectedTime}");
|
||||
emit(updatedState); // Передаем обновленное состояние в emit
|
||||
} else
|
||||
print("Retire time change error");
|
||||
}
|
||||
}
|
||||
|
||||
Future<http.Response> sendWakeupData(
|
||||
TimeOfDay wakeup,
|
||||
int diaryID,
|
||||
) async {
|
||||
String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/wakeUp/fill';
|
||||
final formatter = DateFormat('HH:mm');
|
||||
final wakeupString =
|
||||
formatter.format(DateTime(2022, 1, 1, wakeup.hour, wakeup.minute));
|
||||
final Map<String, dynamic> credentials = {
|
||||
'wakeUp': wakeupString,
|
||||
};
|
||||
|
||||
var response = await http.post(
|
||||
Uri.parse(url),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: json.encode(credentials),
|
||||
encoding: utf8,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
Future<http.Response> sendRetireData(
|
||||
TimeOfDay retire,
|
||||
int diaryID,
|
||||
) async {
|
||||
String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/retire/fill';
|
||||
final formatter = DateFormat('HH:mm');
|
||||
final retireString =
|
||||
formatter.format(DateTime(2022, 1, 1, retire.hour, retire.minute));
|
||||
final Map<String, dynamic> credentials = {
|
||||
'retire': retireString,
|
||||
};
|
||||
|
||||
var response = await http.post(
|
||||
Uri.parse(url),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: json.encode(credentials),
|
||||
encoding: utf8,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
FutureOr<void> _changeMealTime(
|
||||
ChangeMealTime event,
|
||||
Emitter<DiaryState> emit,
|
||||
) async {
|
||||
if (state is DiaryStateLoaded) {
|
||||
var currentState = state as DiaryStateLoaded;
|
||||
var updatedState = currentState.copyWith(mealTimeController: event.time);
|
||||
|
||||
emit(updatedState);
|
||||
}
|
||||
}
|
||||
|
||||
Future<http.Response> sendMealTimeData(
|
||||
String? token,
|
||||
TimeOfDay mealTime,
|
||||
int? mealID,
|
||||
int diaryID,
|
||||
) async {
|
||||
String url = dotenv.env['SERVER_ROOT']! + '/diary/???';
|
||||
final Map<String, dynamic> credentials = {
|
||||
'time': mealTime,
|
||||
'meal_id': mealID,
|
||||
'diary_id': diaryID,
|
||||
};
|
||||
|
||||
var response = await http.post(
|
||||
Uri.parse(url),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer $token',
|
||||
},
|
||||
body: json.encode(credentials),
|
||||
encoding: utf8,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
FutureOr<void> _changeMeal(
|
||||
ChangeMeal event,
|
||||
Emitter<DiaryState> emit,
|
||||
) async {
|
||||
if (state is DiaryStateLoaded) {
|
||||
var currentState = state as DiaryStateLoaded;
|
||||
Meal? meal =
|
||||
currentState.diary.meals.firstWhere((meal) => meal.id == event.value);
|
||||
|
||||
DiaryStateLoaded updatedState = currentState.copyWith(
|
||||
currentMeal: event.value,
|
||||
portions: meal.portions,
|
||||
photos: meal.photos,
|
||||
mealTimeController: toTime(meal.time),
|
||||
selectedMood: meal.mood,
|
||||
selectedSatiety: meal.satiety,
|
||||
);
|
||||
emit(updatedState);
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _clearInput(
|
||||
ClearInput event,
|
||||
Emitter<DiaryState> emit,
|
||||
) {
|
||||
if (state is DiaryStateLoaded) {
|
||||
var currentState = state as DiaryStateLoaded;
|
||||
DiaryStateLoaded updatedState = currentState.copyWith();
|
||||
emit(updatedState);
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _changePortion(
|
||||
ChangePortion event,
|
||||
Emitter<DiaryState> emit,
|
||||
) {
|
||||
if (state is DiaryStateLoaded) {
|
||||
var currentState = state as DiaryStateLoaded;
|
||||
DiaryStateLoaded updatedState = currentState.copyWith(
|
||||
portionController: event.value,
|
||||
);
|
||||
emit(updatedState);
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _toggleMood(
|
||||
ToggleMoodExpandedEvent event,
|
||||
Emitter<DiaryState> emit,
|
||||
) {
|
||||
if (state is DiaryStateLoaded) {
|
||||
var currentState = state as DiaryStateLoaded;
|
||||
|
||||
emit(currentState.copyWith(moodExpanded: !currentState.moodExpanded));
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _toggleWakeup(
|
||||
ToggleWakeupExpandedEvent event,
|
||||
Emitter<DiaryState> emit,
|
||||
) {
|
||||
if (state is DiaryStateLoaded) {
|
||||
var currentState = state as DiaryStateLoaded;
|
||||
|
||||
emit(currentState.copyWith(wakeupExpanded: !currentState.wakeupExpanded));
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _addPortion(
|
||||
AddPortionEvent event,
|
||||
Emitter<DiaryState> emit,
|
||||
) async {
|
||||
if (state is DiaryStateLoaded) {
|
||||
var currentState = state as DiaryStateLoaded;
|
||||
|
||||
var response = await sendPortionData(
|
||||
currentState.productNameController?.text,
|
||||
currentState.portionController?.id == 0 ? 'pcs' : 'gr',
|
||||
int.parse(currentState.productQuantityController!.text),
|
||||
currentState.currentMeal!.id,
|
||||
currentState.diary.id,
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
emit(currentState.copyWith(isAdded: true));
|
||||
await reloadScreen(event, emit);
|
||||
} else {
|
||||
print(
|
||||
'Failed to add portion. Status Code: ${response.statusCode} ${response.body}',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<http.Response> sendPortionData(
|
||||
String? name,
|
||||
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 = {
|
||||
'product_name': name,
|
||||
'portion': portion,
|
||||
'quantity': quantity,
|
||||
};
|
||||
|
||||
var response = await http.post(
|
||||
Uri.parse(url),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: json.encode(credentials),
|
||||
encoding: utf8,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
Future<void> _inputProduct(
|
||||
ProductInput event,
|
||||
Emitter<DiaryState> emit,
|
||||
) async {
|
||||
if (state is DiaryStateLoaded) {
|
||||
var currentState = state as DiaryStateLoaded;
|
||||
|
||||
final Map<String, dynamic> credentials = {'name': event.input};
|
||||
final uri = Uri.parse(
|
||||
'${dotenv.env['SERVER_ROOT']!}/diary/product_nutritional_values/filter?${Uri(queryParameters: credentials).query}',
|
||||
);
|
||||
|
||||
final response = await http.get(
|
||||
uri,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
);
|
||||
|
||||
final productNutritionalValues =
|
||||
jsonDecode(response.body)['product_nutritional_value'];
|
||||
|
||||
if (productNutritionalValues is List<dynamic>) {
|
||||
// Create a new controller with the input text and update the autocomplete list
|
||||
var updatedState = currentState.copyWith(
|
||||
productNameController: TextEditingController(text: event.input),
|
||||
autocompleteList: productNutritionalValues
|
||||
.map((product) => product['name'])
|
||||
.toList(),
|
||||
);
|
||||
if (event.input.length > 3) {
|
||||
updatedState = updatedState.copyWith(moderationExpanded: true);
|
||||
} else {
|
||||
updatedState = updatedState.copyWith(moderationExpanded: false);
|
||||
}
|
||||
|
||||
emit(updatedState); // Emit the updated state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _removePortion(
|
||||
RemovePortionEvent event,
|
||||
Emitter<DiaryState> emit,
|
||||
) async {
|
||||
if (state is DiaryStateLoaded) {
|
||||
var currentState = state as DiaryStateLoaded;
|
||||
|
||||
int? mealId =
|
||||
currentState.currentMeal?.id; // Rename id to mealId for clarity
|
||||
|
||||
var response = await sendRemovePortion(
|
||||
event.portionId,
|
||||
mealId,
|
||||
currentState.diary.id,
|
||||
);
|
||||
|
||||
if (response.statusCode == 204) {
|
||||
await reloadScreen(event, emit);
|
||||
} else {
|
||||
print(
|
||||
'Failed to add portion. Status Code: ${response.statusCode} ${response.body}',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<http.Response> sendRemovePortion(
|
||||
int? portionID,
|
||||
int? mealID,
|
||||
int diaryID,
|
||||
) async {
|
||||
String url =
|
||||
'${dotenv.env['SERVER_ROOT']!}/diary/$diaryID/meal/$mealID/portions/$portionID/delete';
|
||||
|
||||
var response = await http.delete(
|
||||
Uri.parse(url),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
encoding: utf8,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
FutureOr<void> _removeImage(
|
||||
RemoveImageEvent event,
|
||||
Emitter<DiaryState> emit,
|
||||
) async {
|
||||
if (state is DiaryStateLoaded) {
|
||||
var currentState = state as DiaryStateLoaded;
|
||||
|
||||
var response = await sendRemovePhoto(
|
||||
event.path,
|
||||
event.photoID,
|
||||
currentState.currentMeal?.id,
|
||||
currentState.diary.id,
|
||||
);
|
||||
print(response.statusCode);
|
||||
if (response.statusCode == 204) {
|
||||
await reloadScreen(event, emit);
|
||||
} else {
|
||||
print(
|
||||
'Failed to remove photo. Status Code: ${response.statusCode} ${response.body}',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<http.Response> sendRemovePhoto(
|
||||
String? path,
|
||||
String? photoID,
|
||||
int? mealID,
|
||||
int diaryID,
|
||||
) async {
|
||||
String url =
|
||||
'${dotenv.env['SERVER_ROOT']!}/diary/$diaryID/meal/$mealID/photo/delete';
|
||||
final Map<String, dynamic> credentials = {
|
||||
'id': photoID,
|
||||
'path': path,
|
||||
};
|
||||
var response = await http.delete(
|
||||
Uri.parse(url),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: json.encode(credentials),
|
||||
encoding: utf8,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
Future<void> _finishDay(FinishDay event, Emitter<DiaryState> emit) async {
|
||||
if (state is DiaryStateLoaded) {
|
||||
var currentState = state as DiaryStateLoaded;
|
||||
|
||||
var response = await sendFinishDay(
|
||||
currentState.diary.id,
|
||||
currentState.wakeupController,
|
||||
currentState.retireController,
|
||||
currentState.commentController?.text,
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
await reloadScreen(event, emit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<http.Response> sendFinishDay(
|
||||
int diaryID,
|
||||
TimeOfDay? wakeup,
|
||||
TimeOfDay? retire,
|
||||
String? comment,
|
||||
) async {
|
||||
final formatter = DateFormat('HH:mm');
|
||||
final wakeupString =
|
||||
formatter.format(DateTime(2022, 1, 1, wakeup!.hour, wakeup.minute));
|
||||
final retireString =
|
||||
formatter.format(DateTime(2022, 1, 1, retire!.hour, retire.minute));
|
||||
|
||||
final Map<String, dynamic> credentials = {
|
||||
'wakeup': wakeupString,
|
||||
'retire': retireString,
|
||||
'comment': comment ?? " ",
|
||||
};
|
||||
|
||||
String url = '${dotenv.env['SERVER_ROOT']!}/diary/$diaryID/finishDay';
|
||||
|
||||
var response = await http.post(
|
||||
Uri.parse(url),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: json.encode(credentials),
|
||||
encoding: utf8,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
Future<void> _uploadImages(
|
||||
UploadImages event,
|
||||
Emitter<DiaryState> emit,
|
||||
) async {
|
||||
if (state is DiaryStateLoaded) {
|
||||
var currentState = state as DiaryStateLoaded;
|
||||
|
||||
emit(currentState.copyWith(isLoading: true));
|
||||
await uploadImageToServer(
|
||||
event.image.path,
|
||||
currentState.diary.id,
|
||||
currentState.currentMeal!.id,
|
||||
);
|
||||
await reloadScreen(event, emit);
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> uploadImageToServer(
|
||||
String imagePath,
|
||||
int diaryID,
|
||||
int mealId,
|
||||
) async {
|
||||
String url =
|
||||
'${dotenv.env['SERVER_ROOT']!}/diary/$diaryID/meal/$mealId/photo/upload';
|
||||
|
||||
var request = http.MultipartRequest('POST', Uri.parse(url));
|
||||
|
||||
request.files.add(await http.MultipartFile.fromPath('photo', imagePath));
|
||||
|
||||
var client = http.Client();
|
||||
var streamedResponse = await client.send(request);
|
||||
|
||||
if (streamedResponse.statusCode == 200) {
|
||||
var response = await http.Response.fromStream(streamedResponse);
|
||||
var imageUrl = response.body;
|
||||
print('Image successfully uploaded');
|
||||
return imageUrl;
|
||||
} else {
|
||||
throw Exception(
|
||||
'Failed to upload image. Status code: ${streamedResponse.statusCode}}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _sendModeration(
|
||||
SendModeration event,
|
||||
Emitter<DiaryState> emit,
|
||||
) async {
|
||||
if (state is DiaryStateLoaded) {
|
||||
final response = await _sendModerationData(
|
||||
event.name,
|
||||
event.energyOn100gr,
|
||||
event.proteinsOn100gr,
|
||||
event.fatsOn100gr,
|
||||
event.carbohydratesOn100gr,
|
||||
);
|
||||
|
||||
if (response.statusCode == 200)
|
||||
print("Moderation success");
|
||||
else
|
||||
print("Moderation error");
|
||||
}
|
||||
}
|
||||
|
||||
Future<http.Response> _sendModerationData(
|
||||
String name,
|
||||
String energy_on_100gr,
|
||||
String proteins_on_100gr,
|
||||
String fats_on_100gr,
|
||||
String carbohydrates_on_100gr,
|
||||
) async {
|
||||
final Uri url = Uri.parse(
|
||||
'${dotenv.env['SERVER_ROOT']!}/diary/product_nutritional_values/sendToModeration',
|
||||
);
|
||||
final Uri serverURL = Uri.parse('${dotenv.env['SERVER_ROOT']!}');
|
||||
String host = serverURL.host;
|
||||
final Map<String, String> credentials = {
|
||||
'name': name,
|
||||
'energy_on_100gr': energy_on_100gr,
|
||||
'proteins_on_100gr': proteins_on_100gr,
|
||||
'fats_on_100gr': fats_on_100gr,
|
||||
'carbohydrates_on_100gr': carbohydrates_on_100gr,
|
||||
};
|
||||
|
||||
var headers = {
|
||||
//'Content-Length': bodyBytes,
|
||||
'Host': host,
|
||||
};
|
||||
|
||||
var response = await http.post(
|
||||
url,
|
||||
headers: headers,
|
||||
body: credentials,
|
||||
encoding: utf8,
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return response;
|
||||
} else {
|
||||
throw Exception(
|
||||
'Failed to send a product for moderation ${response.statusCode}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _addComment(
|
||||
AddComment event,
|
||||
Emitter<DiaryState> emit,
|
||||
) async {
|
||||
if (state is DiaryStateLoaded) {
|
||||
var currentState = state as DiaryStateLoaded;
|
||||
var updatedState = currentState.copyWith(
|
||||
commentController: TextEditingController(text: event.comment),
|
||||
);
|
||||
|
||||
// Отправляем данные по HTTP маршруту и ждем ответ
|
||||
var response = await sendCommentData(
|
||||
event.comment,
|
||||
currentState.diary.id,
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
emit(updatedState); // Передаем обновленное состояние в emit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<http.Response> sendCommentData(
|
||||
String comment,
|
||||
int diaryID,
|
||||
) async {
|
||||
String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/retire/fill';
|
||||
final Map<String, dynamic> credentials = {
|
||||
'comment': comment,
|
||||
};
|
||||
|
||||
var response = await http.post(
|
||||
Uri.parse(url),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: json.encode(credentials),
|
||||
encoding: utf8,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
TimeOfDay toTime(String timeStr) {
|
||||
List<String> timeParts = timeStr.split(":");
|
||||
int hour = int.parse(timeParts[0]);
|
||||
int minute = int.parse(timeParts[1]);
|
||||
|
||||
TimeOfDay timeOfDay = TimeOfDay(hour: hour, minute: minute);
|
||||
return timeOfDay;
|
||||
}
|
||||
|
||||
List<SelectionPopupModel> fillMealList(List<dynamic> meals) {
|
||||
meals.sort(compareTypes);
|
||||
return meals.map((meal) {
|
||||
String title = "Прием пищи ${meal['type']}";
|
||||
return SelectionPopupModel(id: meal['id'], title: title);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
int compareTypes(a, b) {
|
||||
return a['type'].compareTo(b['type']);
|
||||
}
|
||||
|
||||
List<SelectionPopupModel> fillPortion() {
|
||||
return [
|
||||
SelectionPopupModel(id: 0, title: "порций", isSelected: true),
|
||||
SelectionPopupModel(id: 1, title: "грамм"),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
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}');
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
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 diaryRepository;
|
||||
|
||||
DiaryCubit({required this.diaryRepository}) : super(const DiaryState.loading());
|
||||
|
||||
loadDiary(String diaryID) async {
|
||||
emit(const DiaryState.loading());
|
||||
try {
|
||||
final diary = await diaryRepository.getDiary(await diaryRepository.getDiaryID().toString());
|
||||
emit(DiaryState.loaded(diary: diary));
|
||||
} catch (e) {
|
||||
emit(DiaryState.error(errorMessage: e.toString()));
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
171
lib/features/diary/presentation/bloc/diary_event.dart
Normal file
171
lib/features/diary/presentation/bloc/diary_event.dart
Normal file
@@ -0,0 +1,171 @@
|
||||
// ignore_for_file: must_be_immutable
|
||||
|
||||
part of 'diary_bloc.dart';
|
||||
|
||||
/// Abstract class for all events that can be dispatched from the
|
||||
///Diary widget.
|
||||
///
|
||||
/// Events must be immutable and implement the [Equatable] interface.
|
||||
@immutable
|
||||
abstract class DiaryEvent extends Equatable {}
|
||||
|
||||
/// Event that is dispatched when the Diary widget is first created.
|
||||
class LoadDiary extends DiaryEvent {
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
class ChangeSatiety extends DiaryEvent {
|
||||
ChangeSatiety(
|
||||
this.selectedElement,
|
||||
);
|
||||
final int selectedElement;
|
||||
|
||||
@override
|
||||
List<Object> get props => [selectedElement];
|
||||
}
|
||||
|
||||
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
|
||||
List<Object> get props => [selectedTime];
|
||||
}
|
||||
|
||||
class RetireEvent extends DiaryEvent {
|
||||
RetireEvent(this.selectedTime);
|
||||
final TimeOfDay selectedTime;
|
||||
|
||||
@override
|
||||
List<Object> get props => [selectedTime];
|
||||
}
|
||||
|
||||
class ToggleMoodExpandedEvent extends DiaryEvent {
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
class ToggleWakeupExpandedEvent extends DiaryEvent {
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
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, required this.meals});
|
||||
|
||||
Meal value;
|
||||
List<Meal>? meals;
|
||||
@override
|
||||
List<Object?> get props => [value, meals];
|
||||
}
|
||||
|
||||
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 => [];
|
||||
}
|
||||
|
||||
class RefreshEvent extends DiaryEvent {
|
||||
RefreshEvent();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
class SendModeration extends DiaryEvent {
|
||||
SendModeration({
|
||||
required this.name,
|
||||
required this.energyOn100gr,
|
||||
required this.proteinsOn100gr,
|
||||
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];
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
import 'package:eatvio_app/features/diary/models/diary_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
import '../../../../data/models/selectionPopupModel/selection_popup_model.dart';
|
||||
|
||||
part 'diary_state.freezed.dart';
|
||||
|
||||
@freezed
|
||||
@@ -11,6 +14,31 @@ abstract class DiaryState with _$DiaryState {
|
||||
|
||||
const factory DiaryState.loaded({
|
||||
required DiaryModel diary,
|
||||
String? diaryDate,
|
||||
List<dynamic>? autocompleteList,
|
||||
required List<int> recommendedChartValues,
|
||||
required List<int> consumedChartValues,
|
||||
List<Portion>? portions,
|
||||
List<Photo>? photos,
|
||||
Meal? currentMeal,
|
||||
SelectionPopupModel? portionController,
|
||||
TimeOfDay? wakeupController,
|
||||
TimeOfDay? retireController,
|
||||
TimeOfDay? mealTimeController,
|
||||
required TextEditingController? commentController,
|
||||
required TextEditingController? productNameController,
|
||||
required TextEditingController? productQuantityController,
|
||||
required TextEditingController? caloriesController,
|
||||
required TextEditingController? fatsController,
|
||||
required TextEditingController? proteinsController,
|
||||
required TextEditingController? carbsController,
|
||||
int? selectedMood,
|
||||
int? selectedSatiety,
|
||||
required bool wakeupExpanded,
|
||||
required bool moderationExpanded,
|
||||
required bool moodExpanded,
|
||||
required bool isLoading,
|
||||
required bool isAdded,
|
||||
}) = DiaryStateLoaded;
|
||||
|
||||
const factory DiaryState.error({
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,11 @@
|
||||
// ignore_for_file: unused_local_variable
|
||||
|
||||
/*import 'bloc/diary_edit_bloc.dart';
|
||||
import 'models/diary_edit_model.dart';
|
||||
import 'package:eatvio_app/features/diary/models/diary_model.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/locator_service.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
@@ -16,42 +20,45 @@ import 'package:eatvio_app/widgets/custom_scale_element.dart';
|
||||
import 'package:carousel_slider/carousel_slider.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class DiaryEditScreen extends StatelessWidget {
|
||||
DiaryEditScreen({Key? key}) : super(key: key);
|
||||
|
||||
static Widget builder(BuildContext context) {
|
||||
return BlocProvider<DiaryEditBloc>(
|
||||
create: (context) =>
|
||||
DiaryEditBloc(DiaryEditState(diaryEditModelObj: DiaryEditModel()))
|
||||
..add(DiaryEditInitialEvent()),
|
||||
child: DiaryEditScreen(),
|
||||
);
|
||||
}
|
||||
|
||||
class DiaryScreen extends StatelessWidget {
|
||||
DiaryScreen({Key? key}) : super(key: key);
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<DiaryEditBloc, DiaryEditState>(
|
||||
builder: (context, state) {
|
||||
if (state is DiaryEditInitialState) {
|
||||
// Это начальное состояние, данные ещё не загружены.
|
||||
return Container(
|
||||
color: Colors.white,
|
||||
);
|
||||
} else if (state is DiaryEditLoadedState) {
|
||||
// Данные загружены, можно строить экран.
|
||||
return _buildDiaryEditScreen(context, state);
|
||||
} else if (state is DiaryEditErrorState) {
|
||||
// Произошла ошибка при загрузке данных.
|
||||
return Center(child: Text(state.errorMessage));
|
||||
} else {
|
||||
// Другие состояния, если они есть.
|
||||
return Container(); // Пустой контейнер для необработанных состояний.
|
||||
}
|
||||
},
|
||||
return BlocProvider<DiaryBloc>(
|
||||
create: (context) => sl<DiaryBloc>()..add(LoadDiary()),
|
||||
child: BlocBuilder<DiaryBloc, DiaryState>(
|
||||
builder: (context, state) {
|
||||
if (state is DiaryStateLoaded) {
|
||||
return _buildDiary(context, state);
|
||||
} else if (state is DiaryStateLoading) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: CupertinoActivityIndicator(),
|
||||
),
|
||||
);
|
||||
} else if (state is DiaryStateError) {
|
||||
return Scaffold(
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Center(
|
||||
child: Text(state.errorMessage),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else
|
||||
return Scaffold(
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Center(
|
||||
child: Text("Неопределенная ошибка"),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDiaryEditScreen(
|
||||
BuildContext context, DiaryEditLoadedState state) {
|
||||
Widget _buildDiary(BuildContext context, DiaryStateLoaded state) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: refreshPage(context),
|
||||
child: Stack(
|
||||
@@ -121,13 +128,13 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
|
||||
refreshPage(BuildContext context) {
|
||||
return () async {
|
||||
context.read<DiaryEditBloc>().add(RefreshEvent());
|
||||
context.read<DiaryBloc>().add(RefreshEvent());
|
||||
};
|
||||
}
|
||||
|
||||
/// Section Widget
|
||||
_buildHeaderRow(BuildContext context, DiaryEditLoadedState state) {
|
||||
final day = state.diaryId;
|
||||
_buildHeaderRow(BuildContext context, DiaryStateLoaded state) {
|
||||
final day = state.diary.id;
|
||||
return Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: 16.h, vertical: 16.h),
|
||||
padding: EdgeInsets.symmetric(
|
||||
@@ -162,7 +169,7 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
),
|
||||
SizedBox(height: 2.v),
|
||||
Text(
|
||||
state.diaryDate.toString(),
|
||||
state.diary.date.toString(),
|
||||
style: CustomTextStyles.bodyMediumBluegray800,
|
||||
),
|
||||
],
|
||||
@@ -174,7 +181,7 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
}
|
||||
|
||||
/// Section Widget
|
||||
_buildAddProduct(BuildContext context, DiaryEditLoadedState state) {
|
||||
_buildAddProduct(BuildContext context, DiaryState state) {
|
||||
return CustomOutlinedButton(
|
||||
text: "Добавить продукт",
|
||||
margin: EdgeInsets.symmetric(horizontal: 10.h),
|
||||
@@ -185,12 +192,12 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
|
||||
addProduct(BuildContext context) {
|
||||
return () {
|
||||
context.read<DiaryEditBloc>().add(AddPortionEvent());
|
||||
context.read<DiaryBloc>().add(AddPortionEvent());
|
||||
};
|
||||
}
|
||||
|
||||
/// Section Widget
|
||||
_buildAddPhoto(BuildContext context, DiaryEditLoadedState state) {
|
||||
_buildAddPhoto(BuildContext context, DiaryStateLoaded state) {
|
||||
bool isLoading = state.isLoading;
|
||||
return GestureDetector(
|
||||
onTap: addImage(context, isLoading),
|
||||
@@ -258,14 +265,14 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
List<XFile>? images = await picker.pickMultiImage();
|
||||
if (images.isNotEmpty) {
|
||||
for (var image in images) {
|
||||
context.read<DiaryEditBloc>().add(UploadImages(image));
|
||||
context.read<DiaryBloc>().add(UploadImages(image));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
_buildMeal(BuildContext context, DiaryEditLoadedState state) {
|
||||
_buildMeal(BuildContext context, DiaryStateLoaded state) {
|
||||
final digitsOnly = FilteringTextInputFormatter.digitsOnly;
|
||||
List<String> _options =
|
||||
state.autocompleteList!.map((dynamic item) => item as String).toList();
|
||||
@@ -329,17 +336,22 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
SizedBox(height: 20.v),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10.h),
|
||||
child: BlocSelector<DiaryEditBloc, DiaryEditState, DiaryEditModel?>(
|
||||
selector: (state) => state.diaryEditModelObj,
|
||||
builder: (context, diaryEditModelObj) {
|
||||
child: BlocSelector<DiaryBloc, DiaryState, DiaryModel?>(
|
||||
selector: (state) {
|
||||
if (state is DiaryStateLoaded)
|
||||
return state.diary;
|
||||
else
|
||||
return null;
|
||||
},
|
||||
builder: (context, diary) {
|
||||
return CustomDropDown(
|
||||
hintText: "Прием пищи",
|
||||
items: diaryEditModelObj?.mealList,
|
||||
items: mealsToDropdown(diary!.meals),
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
horizontal: 10.h,
|
||||
vertical: 9.v,
|
||||
),
|
||||
defaultValue: diaryEditModelObj?.mealList[0],
|
||||
defaultValue: mealsToDropdown(diary.meals)[0],
|
||||
onChanged: changeMeal(context, state),
|
||||
);
|
||||
},
|
||||
@@ -424,13 +436,20 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 30.h),
|
||||
child: BlocSelector<DiaryEditBloc, DiaryEditState,
|
||||
DiaryEditModel?>(
|
||||
selector: (state) => state.diaryEditModelObj,
|
||||
builder: (context, diaryEditModelObj) {
|
||||
child: BlocSelector<DiaryBloc, DiaryState, DiaryModel?>(
|
||||
selector: (state) {
|
||||
if (state is DiaryStateLoaded) {
|
||||
return state.diary;
|
||||
} else
|
||||
return null;
|
||||
},
|
||||
builder: (context, diary) {
|
||||
return CustomDropDown(
|
||||
items: diaryEditModelObj?.portionList,
|
||||
defaultValue: diaryEditModelObj?.portionList?[0],
|
||||
items: [
|
||||
SelectionPopupModel(title: "gr"),
|
||||
SelectionPopupModel(title: "pcs")
|
||||
],
|
||||
defaultValue: SelectionPopupModel(title: "gr"),
|
||||
onChanged: changePortion(context, state),
|
||||
);
|
||||
},
|
||||
@@ -463,9 +482,9 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
style: CustomTextStyles.bodyMediumBlack900,
|
||||
),
|
||||
SizedBox(height: 15.v),
|
||||
BlocBuilder<DiaryEditBloc, DiaryEditState>(
|
||||
BlocBuilder<DiaryBloc, DiaryState>(
|
||||
builder: (context, state) {
|
||||
if (state is DiaryEditLoadedState) {
|
||||
if (state is DiaryStateLoaded) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
@@ -505,7 +524,7 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return Container(); // Возвращаем пустой контейнер, если состояние не является DiaryEditLoadedState
|
||||
return Container(); // Возвращаем пустой контейнер, если состояние не является DiaryState
|
||||
}
|
||||
},
|
||||
),
|
||||
@@ -514,7 +533,7 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
openCaloriesDialog(BuildContext context, DiaryEditLoadedState state) {
|
||||
openCaloriesDialog(BuildContext context, DiaryStateLoaded state) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext dialogContext) {
|
||||
@@ -587,7 +606,7 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
) {
|
||||
return () {
|
||||
// Call function to send moderation with the entered values
|
||||
context.read<DiaryEditBloc>().add(
|
||||
context.read<DiaryBloc>().add(
|
||||
SendModeration(
|
||||
name: name,
|
||||
energyOn100gr: energyOn100gr,
|
||||
@@ -609,12 +628,12 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
|
||||
changeSatiety(BuildContext context, int satiety) {
|
||||
return () {
|
||||
context.read<DiaryEditBloc>().add(ChangeSatiety(satiety));
|
||||
context.read<DiaryBloc>().add(ChangeSatiety(satiety));
|
||||
};
|
||||
}
|
||||
|
||||
selectProduct(AutocompleteOnSelected<String> onSelected, String option,
|
||||
DiaryEditLoadedState state) {
|
||||
DiaryStateLoaded state) {
|
||||
state.productNameController?.text = option;
|
||||
return () {
|
||||
onSelected(option);
|
||||
@@ -627,7 +646,7 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
?.map((dynamic item) => item as String)
|
||||
.toList());*/
|
||||
if (value.length > 2) {
|
||||
context.read<DiaryEditBloc>().add(ProductInput(value));
|
||||
context.read<DiaryBloc>().add(ProductInput(value));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -640,27 +659,27 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
};
|
||||
}
|
||||
|
||||
changeMeal(BuildContext context, DiaryEditLoadedState state) {
|
||||
changeMeal(BuildContext context, DiaryStateLoaded state) {
|
||||
return (value) {
|
||||
context
|
||||
.read<DiaryEditBloc>()
|
||||
.add(ChangeMeal(meals: state.meals, value: value));
|
||||
.read<DiaryBloc>()
|
||||
.add(ChangeMeal(meals: state.diary.meals, value: value));
|
||||
};
|
||||
}
|
||||
|
||||
changePortion(BuildContext context, DiaryEditLoadedState state) {
|
||||
changePortion(BuildContext context, DiaryState state) {
|
||||
return (value) {
|
||||
context.read<DiaryEditBloc>().add(ChangePortion(value: value));
|
||||
context.read<DiaryBloc>().add(ChangePortion(value: value));
|
||||
};
|
||||
}
|
||||
|
||||
_buildCarousel(BuildContext context, DiaryEditLoadedState state) {
|
||||
if (state.photos!.isEmpty) {
|
||||
_buildCarousel(BuildContext context, DiaryStateLoaded state) {
|
||||
if (state.currentMeal!.photos!.isEmpty) {
|
||||
return Text("Фото нет");
|
||||
} else {
|
||||
return CarouselSlider(
|
||||
options: CarouselOptions(height: 340.0),
|
||||
items: state.photos!.map<Widget>((photo) {
|
||||
items: state.currentMeal!.photos!.map<Widget>((photo) {
|
||||
return _buildPhoto(
|
||||
context, photo); // Assuming photos are stored as strings
|
||||
}).toList(),
|
||||
@@ -668,7 +687,7 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
_buildProduct(BuildContext context, Map<String, dynamic> portion) {
|
||||
_buildProduct(BuildContext context, Portion portion) {
|
||||
return Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: 10.h),
|
||||
padding: EdgeInsets.symmetric(
|
||||
@@ -688,9 +707,9 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
top: 5.v,
|
||||
),
|
||||
child: Text(
|
||||
portion['product_name'].length > 8
|
||||
? portion['product_name'].substring(0, 8)
|
||||
: portion['product_name'],
|
||||
portion.productName.length > 8
|
||||
? portion.productName.substring(0, 8)
|
||||
: portion.productName,
|
||||
style: CustomTextStyles.titleMedium16,
|
||||
),
|
||||
),
|
||||
@@ -701,9 +720,7 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
bottom: 3.v,
|
||||
),
|
||||
child: Text(
|
||||
portion['quantity'].toString() +
|
||||
' ' +
|
||||
portion['portion'].toString().tr,
|
||||
portion.quantity.toString() + ' ' + portion.portion.toString().tr,
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
@@ -722,7 +739,7 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
_buildPhoto(BuildContext context, Map<String, dynamic> photo) {
|
||||
_buildPhoto(BuildContext context, Photo photo) {
|
||||
return Stack(
|
||||
children: [
|
||||
Container(
|
||||
@@ -731,7 +748,7 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
borderRadius: BorderRadiusStyle.roundedBorder5,
|
||||
),
|
||||
child: Image.network(
|
||||
dotenv.env['STORAGE_URL']! + photo['path'],
|
||||
dotenv.env['STORAGE_URL']! + photo.path,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
@@ -756,21 +773,21 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
removePortion(BuildContext context, Map<String, dynamic> portion) {
|
||||
removePortion(BuildContext context, Portion portion) {
|
||||
return () {
|
||||
context.read<DiaryEditBloc>().add(RemovePortionEvent(portion['id']));
|
||||
context.read<DiaryBloc>().add(RemovePortionEvent(portion.id));
|
||||
};
|
||||
}
|
||||
|
||||
removePhoto(BuildContext context, Map<String, dynamic> photo) {
|
||||
removePhoto(BuildContext context, Photo photo) {
|
||||
return () {
|
||||
context
|
||||
.read<DiaryEditBloc>()
|
||||
.add(RemoveImageEvent(photo['id'].toString(), photo['path']));
|
||||
.read<DiaryBloc>()
|
||||
.add(RemoveImageEvent(photo.id.toString(), photo.path));
|
||||
};
|
||||
}
|
||||
|
||||
_buildNutritionChart(BuildContext context, DiaryEditLoadedState state) {
|
||||
_buildNutritionChart(BuildContext context, DiaryStateLoaded state) {
|
||||
final List<int> recommendedValues = state
|
||||
.recommendedChartValues; // Рекомендуемые значения: калории, жиры, белки, углеводы
|
||||
final List<int> consumedValues = state.consumedChartValues; //
|
||||
@@ -992,7 +1009,7 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
}
|
||||
|
||||
/// Section Widget
|
||||
_buildComment(BuildContext context, DiaryEditLoadedState state) {
|
||||
_buildComment(BuildContext context, DiaryStateLoaded state) {
|
||||
return Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: 16.h),
|
||||
padding: EdgeInsets.symmetric(
|
||||
@@ -1036,7 +1053,7 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
_buildWakupRetire(BuildContext context, DiaryEditLoadedState state) {
|
||||
_buildWakupRetire(BuildContext context, DiaryStateLoaded state) {
|
||||
return Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: 16.h),
|
||||
padding: EdgeInsets.symmetric(
|
||||
@@ -1112,7 +1129,7 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
|
||||
toggleWakeup(BuildContext context) {
|
||||
return () {
|
||||
BlocProvider.of<DiaryEditBloc>(context).add(ToggleWakeupExpandedEvent());
|
||||
BlocProvider.of<DiaryBloc>(context).add(ToggleWakeupExpandedEvent());
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1146,7 +1163,7 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
BuildContext dialogContext, BuildContext context) {
|
||||
return () {
|
||||
closeDialog(dialogContext);
|
||||
context.read<DiaryEditBloc>().add(FinishDay());
|
||||
context.read<DiaryBloc>().add(FinishDay());
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1156,7 +1173,7 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
};
|
||||
}
|
||||
|
||||
_buildMood(BuildContext context, DiaryEditLoadedState state) {
|
||||
_buildMood(BuildContext context, DiaryStateLoaded state) {
|
||||
return Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: 16.h),
|
||||
padding: EdgeInsets.symmetric(
|
||||
@@ -1238,49 +1255,46 @@ class DiaryEditScreen extends StatelessWidget {
|
||||
|
||||
changeMood(BuildContext context, int satiety) {
|
||||
return () {
|
||||
context.read<DiaryEditBloc>().add(ChangeMood(satiety));
|
||||
context.read<DiaryBloc>().add(ChangeMood(satiety));
|
||||
};
|
||||
}
|
||||
|
||||
toggleMood(BuildContext context) {
|
||||
return () {
|
||||
BlocProvider.of<DiaryEditBloc>(context).add(ToggleMoodExpandedEvent());
|
||||
BlocProvider.of<DiaryBloc>(context).add(ToggleMoodExpandedEvent());
|
||||
};
|
||||
}
|
||||
|
||||
Future<void> _selectWakeupTime(
|
||||
BuildContext context, DiaryEditLoadedState state) async {
|
||||
BuildContext context, DiaryStateLoaded state) async {
|
||||
final TimeOfDay? pickedTime = await showTimePicker(
|
||||
context: context,
|
||||
initialTime: state.wakeupController ?? TimeOfDay.now(),
|
||||
);
|
||||
if (pickedTime != null && pickedTime != state.wakeupController) {
|
||||
state.wakeupController = pickedTime;
|
||||
context.read<DiaryEditBloc>().add(WakeupEvent(pickedTime));
|
||||
context.read<DiaryBloc>().add(WakeupEvent(pickedTime));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _selectRetireTime(
|
||||
BuildContext context, DiaryEditLoadedState state) async {
|
||||
BuildContext context, DiaryStateLoaded state) async {
|
||||
final TimeOfDay? pickedTime = await showTimePicker(
|
||||
context: context,
|
||||
initialTime: state.retireController ?? TimeOfDay.now(),
|
||||
);
|
||||
if (pickedTime != null && pickedTime != state.retireController) {
|
||||
state.retireController = pickedTime;
|
||||
context.read<DiaryEditBloc>().add(RetireEvent(pickedTime));
|
||||
context.read<DiaryBloc>().add(RetireEvent(pickedTime));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _selectMealTime(
|
||||
BuildContext context, DiaryEditLoadedState state) async {
|
||||
BuildContext context, DiaryStateLoaded state) async {
|
||||
final TimeOfDay? pickedTime = await showTimePicker(
|
||||
context: context,
|
||||
initialTime: state.mealTimeController ?? TimeOfDay.now(),
|
||||
);
|
||||
if (pickedTime != null && pickedTime != state.mealTimeController) {
|
||||
state.mealTimeController = pickedTime;
|
||||
context.read<DiaryEditBloc>().add(ChangeMealTime(pickedTime));
|
||||
context.read<DiaryBloc>().add(ChangeMealTime(pickedTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1296,4 +1310,13 @@ bool checkConsumedValues(
|
||||
// Если ни одно потребленное значение не превышает рекомендованное с соответствующим индексом
|
||||
return false; // Возвращаем true
|
||||
}
|
||||
*/
|
||||
|
||||
List<SelectionPopupModel> mealsToDropdown(List<Meal> meals) {
|
||||
return meals
|
||||
.map((meal) => SelectionPopupModel(
|
||||
id: meal.id,
|
||||
title: "Прием пищи ${meal.id}",
|
||||
isSelected: false,
|
||||
))
|
||||
.toList();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user