Merge pull request 'diary_refactor' (#38) from diary_refactor into main

Reviewed-on: maxxkim/eatvio_app#38
This commit is contained in:
2024-07-03 10:37:58 +00:00
10 changed files with 2085 additions and 552 deletions

3
.gitignore vendored
View File

@@ -6,4 +6,5 @@
/.flutter-plugins
/.flutter-plugins-dependencies
/.packages
/.env
/.env
/node_modules

View File

@@ -0,0 +1,24 @@
/*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 String state,
String? image,
required String description,
String? author_name,
String? author_avatar_path,
@JsonKey(name: "youtube_url") required String youtubeUrl,
@JsonKey(name: "created_at") required DateTime createdAt,
@JsonKey(name: "updated_at") required DateTime updatedAt,
required String title,
}) = _DiaryModel;
factory DiaryModel.fromJson(Map<String, Object?> json) =>
_$DiaryModelFromJson(json);
}
*/

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<RemovePortionEvent>(_removePortion);
on<RemoveImageEvent>(
_removeImage,); // пользователь нажимает на крестик около продукта
_removeImage,
); // пользователь нажимает на крестик около продукта
on<UploadImages>(_uploadImages); //пользователь нажимает "Добавить фото"
on<AddComment>(_addComment); //пользователь нажимает "Добавить комментарий"
on<ProductInput>(
_inputProduct,); //пользователь нажимает "Добавить комментарий"
_inputProduct,
); //пользователь нажимает "Добавить комментарий"
on<FinishDay>(_finishDay); //пользователь нажимает "Добавить комментарий"
on<SendModeration>(_sendModeration);
on<RefreshEvent>(
reloadScreen,); //пользователь нажимает "Добавить комментарий"
reloadScreen,
); //пользователь нажимает "Добавить комментарий"
on<ClearInput>(_clearInput);
}
@@ -62,7 +65,8 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
if (state is DiaryEditLoadedState) {
// Если текущее состояние уже загружено, обновляем его
var currentState = state as DiaryEditLoadedState;
emit((currentState).copyWith(
emit(
(currentState).copyWith(
currentMeal: currentState.currentMeal,
wakeupExpanded: currentState.wakeupExpanded,
moodExpanded: currentState.moodExpanded,
@@ -84,20 +88,24 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
selectedMood: currentState.selectedMood,
diaryDate: currentState.diaryDate,
diaryId: currentState.diaryId,
productQuantityController:
currentState.productQuantityController,
productQuantityController: currentState.productQuantityController,
recommendedChartValues: currentState.recommendedChartValues,
consumedChartValues: currentState.consumedChartValues,
autocompleteList: currentState.autocompleteList,
diaryEditModelObj: currentState.diaryEditModelObj,),);
diaryEditModelObj: currentState.diaryEditModelObj,
),
);
} else {
// Если текущее состояние - начальное, создаем новое загруженное состояние
final List<SelectionPopupModel> meals =
fillMealList(diary['meals']);
emit(DiaryEditLoadedState(
final List<SelectionPopupModel> meals = fillMealList(diary['meals']);
emit(
DiaryEditLoadedState(
currentMeal: meals[0],
portionController: SelectionPopupModel(
id: 0, title: "порций", isSelected: true,),
id: 0,
title: "порций",
isSelected: true,
),
wakeupExpanded: true,
moodExpanded: true,
moderationExpanded: false,
@@ -109,12 +117,10 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
photos: diary['meals'][0]['photos'],
wakeupController: toTime(diary['wakeup'] ?? "09:00"),
retireController: toTime(diary['retire'] ?? "23:00"),
mealTimeController:
toTime(diary['meals'][0]['time'] ?? "10:00"),
mealTimeController: toTime(diary['meals'][0]['time'] ?? "10:00"),
selectedSatiety: diary['meals'][0]['satiety'],
selectedMood: diary['meals'][0]['mood'],
commentController:
TextEditingController(text: diary['comment']),
commentController: TextEditingController(text: diary['comment']),
productNameController: TextEditingController(),
productQuantityController: TextEditingController(),
caloriesController: TextEditingController(),
@@ -124,8 +130,9 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
diaryId: diaryId,
diaryDate: diaryDate,
autocompleteList: [],
diaryEditModelObj: state.diaryEditModelObj
?.copyWith(mealList: meals, portionList: fillPortions()),),);
diaryEditModelObj: state.diaryEditModelObj?.copyWith(mealList: meals, portionList: fillPortions()),
),
);
}
}
} catch (e) {
@@ -177,31 +184,28 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
}
fetchChartValues(
String token, int diaryID, Emitter<DiaryEditState> emit,) async {
String token,
int diaryID,
Emitter<DiaryEditState> emit,
) async {
final responseChart = await http.get(
Uri.parse(
dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/dailyNutritionData/',),
dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/dailyNutritionData/',
),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
},
);
if (responseChart.statusCode == 200) {
final recommendedChartValues =
jsonDecode(responseChart.body)['dailyNutritionRecommendation']
.values
.map<double>((value) => value as double)
.toList();
final consumedChartValues =
jsonDecode(responseChart.body)['dailyNutritionIntake']
.values
.map<double>((value) => value as double)
.toList();
final recommendedChartValues = jsonDecode(responseChart.body)['dailyNutritionRecommendation'].values.map<int>((value) => value as int).toList();
final consumedChartValues = jsonDecode(responseChart.body)['dailyNutritionIntake'].values.map<int>((value) => value as int).toList();
print([recommendedChartValues, consumedChartValues]);
return [recommendedChartValues, consumedChartValues];
} else {
emit(DiaryEditErrorState('Ошибка при декодировании данных КБЖУ'));
print('fail');
return -1;
return [[], []]; // Возвращаем пустые списки вместо -1
}
}
@@ -249,8 +253,9 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
if (diary is Map<String, dynamic>) {
final String diaryDate = diary['date'] ?? DateTime.now().toString();
final responseChart = await http.get(
Uri.parse(dotenv.env['SERVER_ROOT']! +
'/diary/$diaryId/dailyNutritionData/',),
Uri.parse(
dotenv.env['SERVER_ROOT']! + '/diary/$diaryId/dailyNutritionData/',
),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
@@ -258,39 +263,41 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
);
if (responseChart.statusCode == 200) {
final recommendedChartValues = jsonDecode(
responseChart.body,)['dailyNutritionRecommendation'];
final consumedChartValues =
jsonDecode(responseChart.body)['dailyNutritionIntake'];
final List<SelectionPopupModel> meals =
fillMealList(diary['meals']);
responseChart.body,
)['dailyNutritionRecommendation'];
final consumedChartValues = jsonDecode(responseChart.body)['dailyNutritionIntake'];
final List<SelectionPopupModel> meals = fillMealList(diary['meals']);
print(recommendedChartValues);
print(consumedChartValues);
try {
await Future(() => emit(DiaryEditLoadedState(
await Future(
() => emit(
DiaryEditLoadedState(
diaryEditModelObj: state.diaryEditModelObj?.copyWith(
mealList: meals, portionList: fillPortions(),),
mealList: meals,
portionList: fillPortions(),
),
currentMeal: meals[0],
portionController: SelectionPopupModel(
id: 0, title: "порций", isSelected: true,),
id: 0,
title: "порций",
isSelected: true,
),
wakeupExpanded: true,
moodExpanded: true,
moderationExpanded: false,
token: token,
recommendedChartValues: recommendedChartValues.values
.map<double>((value) => value as double)
.toList(),
consumedChartValues: consumedChartValues.values
.map<double>((value) => value as double)
.toList(),
recommendedChartValues: recommendedChartValues.values.map<double>((value) => value as double).toList(),
consumedChartValues: consumedChartValues.values.map<double>((value) => value as double).toList(),
meals: diary['meals'],
portions: diary['meals'][0]['portions'],
photos: diary['meals'][0]['photos'],
wakeupController: toTime(diary['wakeup'] ?? "09:00"),
retireController: toTime(diary['retire'] ?? "23:00"),
mealTimeController:
toTime(diary['meals'][0]['time'] ?? "10:00"),
mealTimeController: toTime(diary['meals'][0]['time'] ?? "10:00"),
selectedSatiety: diary['meals'][0]['satiety'],
selectedMood: diary['meals'][0]['mood'],
commentController:
TextEditingController(text: diary['comment']),
commentController: TextEditingController(text: diary['comment']),
productNameController: TextEditingController(),
productQuantityController: TextEditingController(),
caloriesController: TextEditingController(),
@@ -301,7 +308,9 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
diaryDate: diaryDate,
isLoading: false,
autocompleteList: [],
),),);
),
),
);
print("Updated");
} catch (e) {
@@ -311,12 +320,16 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
emit(DiaryEditErrorState('Ошибка при декодировании данных КБЖУ'));
}
} else {
emit(DiaryEditErrorState(
'Ошибка при декодировании данных дневника',),);
emit(
DiaryEditErrorState(
'Ошибка при декодировании данных дневника',
),
);
}
} else {
emit(
DiaryEditErrorState('Некоторые необходимые данные отсутствуют.'),);
DiaryEditErrorState('Некоторые необходимые данные отсутствуют.'),
);
}
} else {
emit(DiaryEditErrorState('Ошибка сервера: ${response.statusCode}'));
@@ -327,18 +340,20 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
}
Future<void> _changeSatiety(
ChangeSatiety event, Emitter<DiaryEditState> emit,) async {
ChangeSatiety event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState;
var updatedState =
currentState.copyWith(selectedSatiety: event.selectedElement);
var updatedState = currentState.copyWith(selectedSatiety: event.selectedElement);
// Отправляем данные по HTTP маршруту и ждем ответ
var response = await sendSatietyData(
currentState.token,
event.selectedElement,
currentState.currentMeal?.id,
currentState.diaryId,);
currentState.token,
event.selectedElement,
currentState.currentMeal?.id,
currentState.diaryId,
);
if (response.statusCode == 200) {
updatedState.selectedSatiety = event.selectedElement;
@@ -353,38 +368,42 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
int? mealID,
int diaryID,
) async {
String url = dotenv.env['SERVER_ROOT']! +
'/diary/$diaryID/meal/$mealID/satiety/fill';
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',
'Authorization': 'Bearer $token',
},
body: json.encode(credentials),
encoding: utf8,);
var response = await http.post(
Uri.parse(url),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
},
body: json.encode(credentials),
encoding: utf8,
);
return response;
}
Future<void> _changeMood(
ChangeMood event, Emitter<DiaryEditState> emit,) async {
ChangeMood event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState;
var updatedState =
currentState.copyWith(selectedMood: event.selectedElement);
var updatedState = currentState.copyWith(selectedMood: event.selectedElement);
// Отправляем данные по HTTP маршруту и ждем ответ
var response = await sendMoodData(
currentState.token,
event.selectedElement,
currentState.currentMeal?.id,
currentState.diaryId,);
currentState.token,
event.selectedElement,
currentState.currentMeal?.id,
currentState.diaryId,
);
if (response.statusCode == 200) {
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;
emit(updatedState); // Передаем обновленное состояние в emit
}
@@ -397,33 +416,38 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
int? mealID,
int diaryID,
) async {
String url =
dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/meal/$mealID/mood/fill';
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',
'Authorization': 'Bearer $token',
},
body: json.encode(credentials),
encoding: utf8,);
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> _changeWakeup(
WakeupEvent event, Emitter<DiaryEditState> emit,) async {
WakeupEvent event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState;
var response = await sendWakeupData(
currentState.token, event.selectedTime, currentState.diaryId,);
currentState.token,
event.selectedTime,
currentState.diaryId,
);
if (response.statusCode == 200) {
await reloadScreen(event, emit);
var updatedState =
currentState.copyWith(wakeupController: event.selectedTime);
var updatedState = currentState.copyWith(wakeupController: event.selectedTime);
print("Wakeup time changed to ${event.selectedTime}");
emit(updatedState); // Передаем обновленное состояние в emit
} else
@@ -432,15 +456,19 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
}
FutureOr<void> _changeRetire(
RetireEvent event, Emitter<DiaryEditState> emit,) async {
RetireEvent event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState;
var response = await sendRetireData(
currentState.token, event.selectedTime, currentState.diaryId,);
currentState.token,
event.selectedTime,
currentState.diaryId,
);
if (response.statusCode == 200) {
await reloadScreen(event, emit);
var updatedState =
currentState.copyWith(retireController: event.selectedTime);
var updatedState = currentState.copyWith(retireController: event.selectedTime);
print("Retire time changed to ${event.selectedTime}");
emit(updatedState); // Передаем обновленное состояние в emit
} else
@@ -455,46 +483,53 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
) 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 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',
'Authorization': 'Bearer $token',
},
body: json.encode(credentials),
encoding: utf8,);
var response = await http.post(
Uri.parse(url),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
},
body: json.encode(credentials),
encoding: utf8,
);
return response;
}
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';
final formatter = DateFormat('HH:mm');
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 = {
'retire': retireString,
};
var response = await http.post(Uri.parse(url),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
},
body: json.encode(credentials),
encoding: utf8,);
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> _changeMealTime(
ChangeMealTime event, Emitter<DiaryEditState> emit,) async {
ChangeMealTime event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState;
var updatedState = currentState.copyWith(mealTimeController: event.time);
@@ -516,51 +551,59 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
'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,);
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<DiaryEditState> emit,) async {
ChangeMeal event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState;
final meal = currentState.meals?.firstWhere(
(meal) => meal['id'] == event.value.id,
orElse: () => null,);
(meal) => meal['id'] == event.value.id,
orElse: () => null,
);
int? id = event.value.id;
print(meal['photos']);
DiaryEditLoadedState updatedState = currentState.copyWith(
currentMeal: event.value,
portions: meal['portions'],
photos: meal['photos'],
mealTimeController: toTime(meal['time'] ?? "1$id:00"),
selectedMood: meal['mood'],
selectedSatiety: meal['satiety'],);
currentMeal: event.value,
portions: meal['portions'],
photos: meal['photos'],
mealTimeController: toTime(meal['time'] ?? "1$id:00"),
selectedMood: meal['mood'],
selectedSatiety: meal['satiety'],
);
print(updatedState.photos);
emit(updatedState);
}
}
FutureOr<void> _clearInput(
ClearInput event, Emitter<DiaryEditState> emit,) {
ClearInput event,
Emitter<DiaryEditState> emit,
) {
if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState;
DiaryEditLoadedState updatedState = currentState.copyWith(
);
DiaryEditLoadedState updatedState = currentState.copyWith();
emit(updatedState);
}
}
FutureOr<void> _changePortion(
ChangePortion event, Emitter<DiaryEditState> emit,) {
ChangePortion event,
Emitter<DiaryEditState> emit,
) {
if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState;
DiaryEditLoadedState updatedState = currentState.copyWith(
@@ -571,7 +614,9 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
}
FutureOr<void> _toggleMood(
ToggleMoodExpandedEvent event, Emitter<DiaryEditState> emit,) {
ToggleMoodExpandedEvent event,
Emitter<DiaryEditState> emit,
) {
if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState;
@@ -581,7 +626,9 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
}
FutureOr<void> _toggleWakeup(
ToggleWakeupExpandedEvent event, Emitter<DiaryEditState> emit,) {
ToggleWakeupExpandedEvent event,
Emitter<DiaryEditState> emit,
) {
if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState;
@@ -591,7 +638,9 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
}
FutureOr<void> _addPortion(
AddPortionEvent event, Emitter<DiaryEditState> emit,) async {
AddPortionEvent event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState;
@@ -609,15 +658,21 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
await reloadScreen(event, emit);
} else {
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,
String portion, int? quantity, int? mealID, int diaryID,) async {
String url =
'${dotenv.env['SERVER_ROOT']!}/diary/$diaryID/meal/$mealID/portions/create';
FutureOr<http.Response> sendPortionData(
String? token,
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,
@@ -639,14 +694,17 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
}
Future<void> _inputProduct(
ProductInput event, Emitter<DiaryEditState> emit,) async {
ProductInput event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState;
String? token = currentState.token;
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}',);
'${dotenv.env['SERVER_ROOT']!}/diary/product_nutritional_values/filter?${Uri(queryParameters: credentials).query}',
);
final response = await http.get(
uri,
@@ -656,16 +714,13 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
},
);
final productNutritionalValues =
jsonDecode(response.body)['product_nutritional_value'];
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(),
autocompleteList: productNutritionalValues.map((product) => product['name']).toList(),
);
if (event.input.length > 3) {
updatedState = updatedState.copyWith(moderationExpanded: true);
@@ -679,12 +734,13 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
}
Future<void> _removePortion(
RemovePortionEvent event, Emitter<DiaryEditState> emit,) async {
RemovePortionEvent event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState;
int? mealId =
currentState.currentMeal?.id; // Rename id to mealId for clarity
int? mealId = currentState.currentMeal?.id; // Rename id to mealId for clarity
var response = await sendRemovePortion(
currentState.token,
@@ -697,15 +753,19 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
await reloadScreen(event, emit);
} else {
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(
String? token, int? portionID, int? mealID, int diaryID,) async {
String url =
'${dotenv.env['SERVER_ROOT']!}/diary/$diaryID/meal/$mealID/portions/$portionID/delete';
String? token,
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),
@@ -720,7 +780,9 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
}
FutureOr<void> _removeImage(
RemoveImageEvent event, Emitter<DiaryEditState> emit,) async {
RemoveImageEvent event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState;
@@ -736,15 +798,20 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
await reloadScreen(event, emit);
} else {
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,
String? photoID, int? mealID, int diaryID,) async {
String url =
'${dotenv.env['SERVER_ROOT']!}/diary/$diaryID/meal/$mealID/photo/delete';
Future<http.Response> sendRemovePhoto(
String? token,
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,
@@ -780,13 +847,16 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
}
}
Future<http.Response> sendFinishDay(String? token, int diaryID,
TimeOfDay? wakeup, TimeOfDay? retire, String? comment,) async {
Future<http.Response> sendFinishDay(
String? token,
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 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,
@@ -810,21 +880,30 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
}
Future<void> _uploadImages(
UploadImages event, Emitter<DiaryEditState> emit,) async {
UploadImages event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState;
emit(currentState.copyWith(isLoading: true));
await uploadImageToServer(event.image.path, currentState.diaryId,
currentState.currentMeal!.id!, currentState.token,);
await uploadImageToServer(
event.image.path,
currentState.diaryId,
currentState.currentMeal!.id!,
currentState.token,
);
await reloadScreen(event, emit);
}
}
Future<String> uploadImageToServer(
String imagePath, int diaryID, int mealId, String? token,) async {
String url =
'${dotenv.env['SERVER_ROOT']!}/diary/$diaryID/meal/$mealId/photo/upload';
String imagePath,
int diaryID,
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));
request.headers['Authorization'] = 'Bearer $token';
@@ -841,12 +920,15 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
return imageUrl;
} else {
throw Exception(
'Failed to upload image. Status code: ${streamedResponse.statusCode}}',);
'Failed to upload image. Status code: ${streamedResponse.statusCode}}',
);
}
}
FutureOr<void> _sendModeration(
SendModeration event, Emitter<DiaryEditState> emit,) async {
SendModeration event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState;
final response = await _sendModerationData(
@@ -866,14 +948,16 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
}
Future<http.Response> _sendModerationData(
String name,
String energy_on_100gr,
String proteins_on_100gr,
String fats_on_100gr,
String carbohydrates_on_100gr,
String? token,) async {
String name,
String energy_on_100gr,
String proteins_on_100gr,
String fats_on_100gr,
String carbohydrates_on_100gr,
String? token,
) async {
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']!}');
String host = serverURL.host;
final Map<String, String> credentials = {
@@ -901,12 +985,15 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
return response;
} else {
throw Exception(
'Failed to send a product for moderation ${response.statusCode}',);
'Failed to send a product for moderation ${response.statusCode}',
);
}
}
FutureOr<void> _addComment(
AddComment event, Emitter<DiaryEditState> emit,) async {
AddComment event,
Emitter<DiaryEditState> emit,
) async {
if (state is DiaryEditLoadedState) {
var currentState = state as DiaryEditLoadedState;
var updatedState = currentState.copyWith(
@@ -915,7 +1002,10 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
// Отправляем данные по HTTP маршруту и ждем ответ
var response = await sendCommentData(
currentState.token, event.comment, currentState.diaryId,);
currentState.token,
event.comment,
currentState.diaryId,
);
if (response.statusCode == 200) {
emit(updatedState); // Передаем обновленное состояние в emit
@@ -924,19 +1014,24 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
}
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';
final Map<String, dynamic> credentials = {
'comment': comment,
};
var response = await http.post(Uri.parse(url),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
},
body: json.encode(credentials),
encoding: utf8,);
var response = await http.post(
Uri.parse(url),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
},
body: json.encode(credentials),
encoding: utf8,
);
return response;
}

View File

@@ -12,43 +12,42 @@ class DiaryEditState extends Equatable {
}
class DiaryEditInitialState extends DiaryEditState {
DiaryEditInitialState({required DiaryEditModel diaryEditModelObj})
: super(diaryEditModelObj: diaryEditModelObj);
DiaryEditInitialState({required DiaryEditModel diaryEditModelObj}) : super(diaryEditModelObj: diaryEditModelObj);
}
/// Represents the state of DiaryEdit in the application.
class DiaryEditLoadedState extends DiaryEditState {
DiaryEditLoadedState(
{this.diaryEditModelObj,
this.diaryDate,
this.token,
this.meals,
this.portions,
this.photos,
this.autocompleteList,
this.wakeupController,
this.retireController,
this.commentController,
this.mealTimeController,
this.portionController,
this.productNameController,
this.productQuantityController,
this.selectedMood,
this.currentMeal,
this.caloriesController,
this.fatsController,
this.proteinsController,
this.carbsController,
this.isLoading = false,
this.isAdded = false,
required this.recommendedChartValues,
required this.consumedChartValues,
required this.diaryId,
required this.selectedSatiety,
required this.moderationExpanded,
required this.wakeupExpanded,
required this.moodExpanded,})
: super(diaryEditModelObj: null);
DiaryEditLoadedState({
this.diaryEditModelObj,
this.diaryDate,
this.token,
this.meals,
this.portions,
this.photos,
this.autocompleteList,
this.wakeupController,
this.retireController,
this.commentController,
this.mealTimeController,
this.portionController,
this.productNameController,
this.productQuantityController,
this.selectedMood,
this.currentMeal,
this.caloriesController,
this.fatsController,
this.proteinsController,
this.carbsController,
this.isLoading = false,
this.isAdded = false,
required this.recommendedChartValues,
required this.consumedChartValues,
required this.diaryId,
required this.selectedSatiety,
required this.moderationExpanded,
required this.wakeupExpanded,
required this.moodExpanded,
}) : super(diaryEditModelObj: null);
DiaryEditModel? diaryEditModelObj;
String? diaryDate;
@@ -57,8 +56,8 @@ class DiaryEditLoadedState extends DiaryEditState {
List<dynamic>? portions;
List<dynamic>? photos;
List<dynamic>? autocompleteList;
List<double> recommendedChartValues;
List<double> consumedChartValues;
List<int> recommendedChartValues;
List<int> consumedChartValues;
SelectionPopupModel? currentMeal;
SelectionPopupModel? portionController;
TimeOfDay? wakeupController;
@@ -117,8 +116,8 @@ class DiaryEditLoadedState extends DiaryEditState {
SelectionPopupModel? portionController,
String? diaryDate,
String? token,
List<double>? recommendedChartValues,
List<double>? consumedChartValues,
List<int>? recommendedChartValues,
List<int>? consumedChartValues,
List<dynamic>? meals,
List<dynamic>? portions,
List<dynamic>? photos,
@@ -143,38 +142,36 @@ class DiaryEditLoadedState extends DiaryEditState {
bool? isAdded,
}) {
return DiaryEditLoadedState(
diaryEditModelObj: diaryEditModelObj ?? this.diaryEditModelObj,
diaryDate: diaryDate ?? this.diaryDate,
token: token ?? this.token,
meals: meals ?? this.meals,
photos: photos ?? this.photos,
autocompleteList: autocompleteList ?? this.autocompleteList,
portions: portions ?? this.portions,
recommendedChartValues:
recommendedChartValues ?? this.recommendedChartValues,
consumedChartValues: consumedChartValues ?? this.consumedChartValues,
wakeupController: wakeupController ?? this.wakeupController,
retireController: retireController ?? this.retireController,
mealTimeController: mealTimeController ?? this.mealTimeController,
commentController: commentController ?? this.commentController,
portionController: portionController ?? this.portionController,
productNameController:
productNameController ?? this.productNameController,
productQuantityController:
productQuantityController ?? this.productQuantityController,
selectedMood: selectedMood ?? this.selectedMood,
selectedSatiety: selectedSatiety ?? this.selectedSatiety,
diaryId: diaryId ?? this.diaryId,
currentMeal: currentMeal ?? this.currentMeal,
caloriesController: caloriesController ?? this.caloriesController,
fatsController: fatsController ?? this.fatsController,
proteinsController: proteinsController ?? this.proteinsController,
carbsController: carbsController ?? this.carbsController,
wakeupExpanded: wakeupExpanded ?? this.wakeupExpanded,
moderationExpanded: moderationExpanded ?? this.moderationExpanded,
moodExpanded: moodExpanded ?? this.moodExpanded,
isAdded: isAdded ?? this.isAdded,
isLoading: isLoading ?? this.isLoading,);
diaryEditModelObj: diaryEditModelObj ?? this.diaryEditModelObj,
diaryDate: diaryDate ?? this.diaryDate,
token: token ?? this.token,
meals: meals ?? this.meals,
photos: photos ?? this.photos,
autocompleteList: autocompleteList ?? this.autocompleteList,
portions: portions ?? this.portions,
recommendedChartValues: recommendedChartValues ?? this.recommendedChartValues,
consumedChartValues: consumedChartValues ?? this.consumedChartValues,
wakeupController: wakeupController ?? this.wakeupController,
retireController: retireController ?? this.retireController,
mealTimeController: mealTimeController ?? this.mealTimeController,
commentController: commentController ?? this.commentController,
portionController: portionController ?? this.portionController,
productNameController: productNameController ?? this.productNameController,
productQuantityController: productQuantityController ?? this.productQuantityController,
selectedMood: selectedMood ?? this.selectedMood,
selectedSatiety: selectedSatiety ?? this.selectedSatiety,
diaryId: diaryId ?? this.diaryId,
currentMeal: currentMeal ?? this.currentMeal,
caloriesController: caloriesController ?? this.caloriesController,
fatsController: fatsController ?? this.fatsController,
proteinsController: proteinsController ?? this.proteinsController,
carbsController: carbsController ?? this.carbsController,
wakeupExpanded: wakeupExpanded ?? this.wakeupExpanded,
moderationExpanded: moderationExpanded ?? this.moderationExpanded,
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) {
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) {
@@ -264,237 +266,241 @@ class DiaryEditScreen extends StatelessWidget {
//print(_options);
FocusNode focusNodeName = FocusNode();
return Container(
margin: EdgeInsets.symmetric(horizontal: 16.h),
padding: EdgeInsets.symmetric(
horizontal: 24.h,
vertical: 12.v,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(Radius.circular(12)),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 2,
blurRadius: 5,
offset: Offset(0, 3),
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 10.h),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Время приема пищи",
style: CustomTextStyles.bodyMediumBlack900,
),
Expanded(
// Adding Expanded widget
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10.h),
child: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width - 260,
),
child: GestureDetector(
onTap: () => _selectMealTime(context, state),
child: AbsorbPointer(
child: CustomTextFormField(
hintText: state.mealTimeController?.format(context).toString(),
autofocus: false,
),
margin: EdgeInsets.symmetric(horizontal: 16.h),
padding: EdgeInsets.symmetric(
horizontal: 24.h,
vertical: 12.v,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(Radius.circular(12)),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 2,
blurRadius: 5,
offset: Offset(0, 3),
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 10.h),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Время приема пищи",
style: CustomTextStyles.bodyMediumBlack900,
),
Expanded(
// Adding Expanded widget
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10.h),
child: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width - 260,
),
child: GestureDetector(
onTap: () => _selectMealTime(context, state),
child: AbsorbPointer(
child: CustomTextFormField(
hintText: state.mealTimeController?.format(context).toString(),
autofocus: false,
),
),
),
),
),
),
],
),
),
SizedBox(height: 20.v),
Padding(
padding: EdgeInsets.symmetric(horizontal: 10.h),
child: BlocSelector<DiaryEditBloc, DiaryEditState, DiaryEditModel?>(
selector: (state) => state.diaryEditModelObj,
builder: (context, diaryEditModelObj) {
return CustomDropDown(
hintText: "Прием пищи",
items: diaryEditModelObj?.mealList,
contentPadding: EdgeInsets.symmetric(
horizontal: 10.h,
vertical: 9.v,
),
defaultValue: diaryEditModelObj?.mealList[0],
onChanged: changeMeal(context, state),
);
},
),
),
SizedBox(height: 20.v),
Padding(
padding: EdgeInsets.symmetric(horizontal: 10.h),
child: RawAutocomplete<String>(
optionsBuilder: buildOptions(_options),
fieldViewBuilder: (
BuildContext context,
TextEditingController productEditingController,
FocusNode focusNodeName,
VoidCallback onFieldSubmitted,
) {
if (state.isAdded) {
print("Clear");
}
return CustomTextFormField(
hintText: "Введите название продукта",
controller: productEditingController,
focusNode: focusNodeName,
onChanged: getAutocomplete(context, focusNodeName),
);
},
optionsViewBuilder: (
BuildContext context,
AutocompleteOnSelected<String> onSelected,
Iterable<String> options,
) {
return Align(
alignment: Alignment.topLeft,
child: Material(
elevation: 4.0,
child: SizedBox(
height: 200.0,
child: ListView.builder(
padding: const EdgeInsets.all(8.0),
itemCount: options.length,
itemBuilder: (BuildContext context, int index) {
final String option = options.elementAt(index);
return GestureDetector(
onTap: selectProduct(onSelected, option, state),
child: ListTile(
title: Text(option),
),
);
},
),
),
),
);
},
),
),
SizedBox(height: 20.v),
if (state.moderationExpanded)
Padding(
padding: EdgeInsets.symmetric(horizontal: 10.h),
child: GestureDetector(
onTap: () => openCaloriesDialog(context, state),
child: Text("Отправить на модерацию"),
),
),
SizedBox(height: 20.v),
Padding(
padding: EdgeInsets.symmetric(horizontal: 10.h),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CustomTextFormField(
width: 150.h,
hintText: "Кол-во",
textInputAction: TextInputAction.done,
// focusNode: focusNodeQuantity,
controller: state.productQuantityController,
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[digitsOnly],
),
Padding(
padding: EdgeInsets.only(left: 30.h),
child: BlocSelector<DiaryEditBloc, DiaryEditState, DiaryEditModel?>(
selector: (state) => state.diaryEditModelObj,
builder: (context, diaryEditModelObj) {
return CustomDropDown(
items: diaryEditModelObj?.portionList,
defaultValue: diaryEditModelObj?.portionList?[0],
onChanged: changePortion(context, state),
);
},
),
),
],
),
),
SizedBox(height: 20.v),
Padding(
padding: EdgeInsets.symmetric(horizontal: 10.h),
child: BlocSelector<DiaryEditBloc, DiaryEditState, DiaryEditModel?>(
selector: (state) => state.diaryEditModelObj,
builder: (context, diaryEditModelObj) {
return CustomDropDown(
hintText: "Прием пищи",
items: diaryEditModelObj?.mealList,
contentPadding: EdgeInsets.symmetric(
horizontal: 10.h,
vertical: 9.v,
),
defaultValue: diaryEditModelObj?.mealList[0],
onChanged: changeMeal(context, state),
);
},),),
SizedBox(height: 20.v),
Padding(
padding: EdgeInsets.symmetric(horizontal: 10.h),
child: RawAutocomplete<String>(
optionsBuilder: buildOptions(_options),
fieldViewBuilder: (
BuildContext context,
TextEditingController productEditingController,
FocusNode focusNodeName,
VoidCallback onFieldSubmitted,
) {
if (state.isAdded) {
print("Clear");
}
return CustomTextFormField(
hintText: "Введите название продукта",
controller: productEditingController,
focusNode: focusNodeName,
onChanged: getAutocomplete(context, focusNodeName),
);
},
optionsViewBuilder: (
BuildContext context,
AutocompleteOnSelected<String> onSelected,
Iterable<String> options,
) {
return Align(
alignment: Alignment.topLeft,
child: Material(
elevation: 4.0,
child: SizedBox(
height: 200.0,
child: ListView.builder(
padding: const EdgeInsets.all(8.0),
itemCount: options.length,
itemBuilder: (BuildContext context, int index) {
final String option = options.elementAt(index);
return GestureDetector(
onTap: selectProduct(onSelected, option, state),
child: ListTile(
title: Text(option),
),
);
},
),
),
),
);
},),
),
SizedBox(height: 20.v),
if (state.moderationExpanded)
Padding(
padding: EdgeInsets.symmetric(horizontal: 10.h),
child: GestureDetector(
onTap: () => openCaloriesDialog(context, state),
child: Text("Отправить на модерацию"),
),
),
SizedBox(height: 20.v),
Padding(
padding: EdgeInsets.symmetric(horizontal: 10.h),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CustomTextFormField(
width: 150.h,
hintText: "Кол-во",
textInputAction: TextInputAction.done,
// focusNode: focusNodeQuantity,
controller: state.productQuantityController,
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[digitsOnly],
),
Padding(
padding: EdgeInsets.only(left: 30.h),
child: BlocSelector<DiaryEditBloc, DiaryEditState, DiaryEditModel?>(
selector: (state) => state.diaryEditModelObj,
builder: (context, diaryEditModelObj) {
return CustomDropDown(
items: diaryEditModelObj?.portionList,
defaultValue: diaryEditModelObj?.portionList?[0],
onChanged: changePortion(context, state),
);
},
),
),
],
),
),
),
SizedBox(height: 30.v),
_buildAddProduct(context, state),
SizedBox(height: 30.v),
...state.portions!.map((portion) => _buildProduct(context, portion)).toList(),
SizedBox(height: 30.v),
/*...state.photos != null
),
SizedBox(height: 30.v),
_buildAddProduct(context, state),
SizedBox(height: 30.v),
...state.portions!.map((portion) => _buildProduct(context, portion)).toList(),
SizedBox(height: 30.v),
/*...state.photos != null
? state.photos!.isEmpty
? [Text('Фото пока нет')]
: state.photos!
.map((photo) => _buildPhoto(context, photo))
.toList()
: [Text('Фото нет')],*/
_buildCarousel(context, state),
SizedBox(height: 20.v),
_buildAddPhoto(context, state),
SizedBox(height: 30.v),
Text(
"Ваша сытость после приёма пищи",
style: CustomTextStyles.bodyMediumBlack900,
),
SizedBox(height: 15.v),
BlocBuilder<DiaryEditBloc, DiaryEditState>(
builder: (context, state) {
if (state is DiaryEditLoadedState) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("😭"),
ScaleElement(
color: Colors.red,
isSelected: state.selectedSatiety == 0,
onTap: changeSatiety(context, 0),
),
ScaleElement(
color: Colors.orange,
isSelected: state.selectedSatiety == 1,
onTap: changeSatiety(context, 1),
),
ScaleElement(
color: Colors.yellow,
isSelected: state.selectedSatiety == 2,
onTap: changeSatiety(context, 2),
),
ScaleElement(
color: Colors.lime,
isSelected: state.selectedSatiety == 3,
onTap: changeSatiety(context, 3),
),
ScaleElement(
color: Colors.lightGreen,
isSelected: state.selectedSatiety == 4,
onTap: changeSatiety(context, 4),
),
ScaleElement(
color: Colors.green,
isSelected: state.selectedSatiety == 5,
onTap: changeSatiety(context, 5),
),
Text("😊"),
// Остальные элементы шкалы
],
);
} else {
return Container(); // Возвращаем пустой контейнер, если состояние не является DiaryEditLoadedState
}
},
),
],
),);
_buildCarousel(context, state),
SizedBox(height: 20.v),
_buildAddPhoto(context, state),
SizedBox(height: 30.v),
Text(
"Ваша сытость после приёма пищи",
style: CustomTextStyles.bodyMediumBlack900,
),
SizedBox(height: 15.v),
BlocBuilder<DiaryEditBloc, DiaryEditState>(
builder: (context, state) {
if (state is DiaryEditLoadedState) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("😭"),
ScaleElement(
color: Colors.red,
isSelected: state.selectedSatiety == 0,
onTap: changeSatiety(context, 0),
),
ScaleElement(
color: Colors.orange,
isSelected: state.selectedSatiety == 1,
onTap: changeSatiety(context, 1),
),
ScaleElement(
color: Colors.yellow,
isSelected: state.selectedSatiety == 2,
onTap: changeSatiety(context, 2),
),
ScaleElement(
color: Colors.lime,
isSelected: state.selectedSatiety == 3,
onTap: changeSatiety(context, 3),
),
ScaleElement(
color: Colors.lightGreen,
isSelected: state.selectedSatiety == 4,
onTap: changeSatiety(context, 4),
),
ScaleElement(
color: Colors.green,
isSelected: state.selectedSatiety == 5,
onTap: changeSatiety(context, 5),
),
Text("😊"),
// Остальные элементы шкалы
],
);
} else {
return Container(); // Возвращаем пустой контейнер, если состояние не является DiaryEditLoadedState
}
},
),
],
),
);
}
openCaloriesDialog(BuildContext context, DiaryEditLoadedState state) {
@@ -542,8 +548,15 @@ class DiaryEditScreen extends StatelessWidget {
child: Text('Отмена'),
),
TextButton(
onPressed: triggerModeration(context, state.productNameController!.text, state.caloriesController!.text, state.proteinsController!.text,
state.fatsController!.text, state.carbsController!.text, dialogContext,),
onPressed: triggerModeration(
context,
state.productNameController!.text,
state.caloriesController!.text,
state.proteinsController!.text,
state.fatsController!.text,
state.carbsController!.text,
dialogContext,
),
child: Text('Отправить'),
),
],
@@ -552,12 +565,26 @@ class DiaryEditScreen extends StatelessWidget {
);
}
triggerModeration(BuildContext context, String name, String energyOn100gr, String proteinsOn100gr, String fatsOn100gr, String carbohydratesOn100gr,
BuildContext dialogContext,) {
triggerModeration(
BuildContext context,
String name,
String energyOn100gr,
String proteinsOn100gr,
String fatsOn100gr,
String carbohydratesOn100gr,
BuildContext dialogContext,
) {
return () {
// Call function to send moderation with the entered values
context.read<DiaryEditBloc>().add(SendModeration(
name: name, energyOn100gr: energyOn100gr, proteinsOn100gr: proteinsOn100gr, fatsOn100gr: fatsOn100gr, carbohydratesOn100gr: carbohydratesOn100gr,),);
context.read<DiaryEditBloc>().add(
SendModeration(
name: name,
energyOn100gr: energyOn100gr,
proteinsOn100gr: proteinsOn100gr,
fatsOn100gr: fatsOn100gr,
carbohydratesOn100gr: carbohydratesOn100gr,
),
);
Navigator.of(dialogContext).pop(); // Dismiss the dialog
};
}
@@ -640,14 +667,15 @@ class DiaryEditScreen extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: EdgeInsets.only(
left: 7.h,
top: 5.v,
),
child: Text(
portion['product_name'].length > 8 ? portion['product_name'].substring(0, 8) : portion['product_name'],
style: CustomTextStyles.titleMedium16,
),),
padding: EdgeInsets.only(
left: 7.h,
top: 5.v,
),
child: Text(
portion['product_name'].length > 8 ? portion['product_name'].substring(0, 8) : portion['product_name'],
style: CustomTextStyles.titleMedium16,
),
),
Padding(
padding: EdgeInsets.only(
left: 20.h,
@@ -660,14 +688,15 @@ class DiaryEditScreen extends StatelessWidget {
),
Spacer(),
GestureDetector(
onTap: removePortion(context, portion),
child: Padding(
padding: const EdgeInsets.only(right: 10),
child: Icon(
Icons.close,
color: appTheme.blueGray300,
),
),),
onTap: removePortion(context, portion),
child: Padding(
padding: const EdgeInsets.only(right: 10),
child: Icon(
Icons.close,
color: appTheme.blueGray300,
),
),
),
],
),
);
@@ -720,8 +749,8 @@ class DiaryEditScreen extends StatelessWidget {
}
_buildNutritionChart(BuildContext context, DiaryEditLoadedState state) {
final List<double> recommendedValues = state.recommendedChartValues; // Рекомендуемые значения: калории, жиры, белки, углеводы
final List<double> consumedValues = state.consumedChartValues; //
final List<int> recommendedValues = state.recommendedChartValues; // Рекомендуемые значения: калории, жиры, белки, углеводы
final List<int> consumedValues = state.consumedChartValues; //
return Container(
margin: EdgeInsets.symmetric(horizontal: 16.h),
padding: EdgeInsets.symmetric(
@@ -779,30 +808,42 @@ class DiaryEditScreen extends StatelessWidget {
),
borderData: FlBorderData(show: false),
barGroups: [
BarChartGroupData(x: 0, barRods: [
BarChartRodData(
toY: consumedValues[0] / recommendedValues[0] * 100,
color: checkConsumedValues([recommendedValues[0]], [consumedValues[1]]) ? Colors.red : Colors.blue,
),
],),
BarChartGroupData(x: 1, barRods: [
BarChartRodData(
toY: consumedValues[1] / recommendedValues[1] * 100,
color: checkConsumedValues([recommendedValues[1]], [consumedValues[1]]) ? Colors.red : Colors.blue,
),
],),
BarChartGroupData(x: 2, barRods: [
BarChartRodData(
toY: consumedValues[2] / recommendedValues[2] * 100,
color: checkConsumedValues([recommendedValues[2]], [consumedValues[2]]) ? Colors.red : Colors.blue,
),
],),
BarChartGroupData(x: 3, barRods: [
BarChartRodData(
toY: consumedValues[3] / recommendedValues[3] * 100,
color: checkConsumedValues([recommendedValues[3]], [consumedValues[3]]) ? Colors.red : Colors.blue,
),
],),
BarChartGroupData(
x: 0,
barRods: [
BarChartRodData(
toY: consumedValues[0] / recommendedValues[0] * 100,
color: checkConsumedValues([recommendedValues[0]], [consumedValues[1]]) ? Colors.red : Colors.blue,
),
],
),
BarChartGroupData(
x: 1,
barRods: [
BarChartRodData(
toY: consumedValues[1] / recommendedValues[1] * 100,
color: checkConsumedValues([recommendedValues[1]], [consumedValues[1]]) ? Colors.red : Colors.blue,
),
],
),
BarChartGroupData(
x: 2,
barRods: [
BarChartRodData(
toY: consumedValues[2] / recommendedValues[2] * 100,
color: checkConsumedValues([recommendedValues[2]], [consumedValues[2]]) ? Colors.red : Colors.blue,
),
],
),
BarChartGroupData(
x: 3,
barRods: [
BarChartRodData(
toY: consumedValues[3] / recommendedValues[3] * 100,
color: checkConsumedValues([recommendedValues[3]], [consumedValues[3]]) ? Colors.red : Colors.blue,
),
],
),
],
),
),
@@ -1077,24 +1118,25 @@ class DiaryEditScreen extends StatelessWidget {
_buildMood(BuildContext context, DiaryEditLoadedState state) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 16.h),
padding: EdgeInsets.symmetric(
horizontal: 24.h,
vertical: 12.v,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(Radius.circular(12)),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 2,
blurRadius: 5,
offset: Offset(0, 3),
),
],
),
child: Column(children: [
margin: EdgeInsets.symmetric(horizontal: 16.h),
padding: EdgeInsets.symmetric(
horizontal: 24.h,
vertical: 12.v,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(Radius.circular(12)),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 2,
blurRadius: 5,
offset: Offset(0, 3),
),
],
),
child: Column(
children: [
GestureDetector(
onTap: toggleMood(context),
child: Row(
@@ -1147,7 +1189,9 @@ class DiaryEditScreen extends StatelessWidget {
// Остальные элементы шкалы
],
),
],),);
],
),
);
}
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++) {
if (consumedValues[i] > recommendedValues[i]) {
// Если хотя бы одно потребленное значение превышает рекомендованное