diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart index 9cfda07f..1796418f 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart @@ -30,6 +30,8 @@ class DiaryEditBloc extends Bloc { _removePortion); // пользователь нажимает на крестик около продукта on(_uploadImages); //пользователь нажимает "Добавить фото" on(_addComment); //пользователь нажимает "Добавить комментарий" + on( + _inputProduct); //пользователь нажимает "Добавить комментарий" } Future _onInitialize( @@ -83,6 +85,7 @@ class DiaryEditBloc extends Bloc { diaryId: currentState.diaryId, productQuantityController: currentState.productQuantityController, + autocompleteList: currentState.autocompleteList, diaryEditModelObj: currentState.diaryEditModelObj)); } else { // Если текущее состояние - начальное, создаем новое загруженное состояние @@ -106,6 +109,7 @@ class DiaryEditBloc extends Bloc { productQuantityController: TextEditingController(), diaryId: diaryId, diaryDate: diaryDate, + autocompleteList: [], diaryEditModelObj: state.diaryEditModelObj ?.copyWith(mealList: fillMealList()))); } @@ -284,7 +288,7 @@ class DiaryEditBloc extends Bloc { } Future sendRetireData( - String? token, TimeOfDay retire, int diaryID, int? mealID) async { + String? token, TimeOfDay retire, int diaryID) async { String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/retire/fill'; final credentials = { 'retire': retire, @@ -433,51 +437,82 @@ class DiaryEditBloc extends Bloc { return response; } -} -FutureOr _removePortion( - RemovePortionEvent event, Emitter emit) {} + FutureOr _inputProduct( + ProductInput event, Emitter emit) async { + if (state is DiaryEditLoadedState) { + var currentState = state as DiaryEditLoadedState; + String? token = currentState.token; + final 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: { + 'Authorization': 'Bearer $token', + }, + ); + final productNutritionalValues = + jsonDecode(response.body)['productNutritionalValue']; + if (productNutritionalValues is Map) { + var updatedState = currentState.copyWith( + autocompleteList: productNutritionalValues.values + .map((value) => value['name']) + .toList()); -Future> _uploadImages( - UploadImages event, Emitter emit) async { - String imageUrl = await uploadImageToServer(event.image.path); - print(imageUrl); -} + emit(updatedState); + } + } + } -FutureOr _addComment(AddComment event, Emitter emit) {} -Future uploadImageToServer(String imagePath) async { - var request = http.MultipartRequest( - 'POST', - Uri.parse('http://your-api-url.com/upload'), // Замените на ваш маршрут API - ); + FutureOr _removePortion( + RemovePortionEvent event, Emitter emit) {} - request.files.add(await http.MultipartFile.fromPath('image', imagePath)); + Future> _uploadImages( + UploadImages event, Emitter emit) async { + String imageUrl = await uploadImageToServer(event.image.path); + print(imageUrl); + } - var response = await request.send(); - if (response.statusCode == 200) { - var responseData = await response.stream.bytesToString(); - return responseData; - } else { - throw Exception('Ошибка при загрузке изображения'); + FutureOr _addComment(AddComment event, Emitter emit) {} + Future uploadImageToServer(String imagePath) async { + var request = http.MultipartRequest( + 'POST', + Uri.parse( + 'http://your-api-url.com/upload'), // Замените на ваш маршрут API + ); + + request.files.add(await http.MultipartFile.fromPath('image', imagePath)); + + var response = await request.send(); + if (response.statusCode == 200) { + var responseData = await response.stream.bytesToString(); + return responseData; + } else { + throw Exception('Ошибка при загрузке изображения'); + } + } + + TimeOfDay toTime(String timeStr) { + List 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 fillMealList() { + return [ + SelectionPopupModel(id: 0, title: "Прием пищи 1", isSelected: true), + SelectionPopupModel(id: 1, title: "Прием пищи 2"), + SelectionPopupModel(id: 2, title: "Прием пищи 3"), + SelectionPopupModel(id: 3, title: "Прием пищи 4"), + SelectionPopupModel(id: 4, title: "Прием пищи 5"), + SelectionPopupModel(id: 5, title: "Прием пищи 6"), + ]; } } - -TimeOfDay toTime(String timeStr) { - List 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 fillMealList() { - return [ - SelectionPopupModel(id: 0, title: "Прием пищи 1", isSelected: true), - SelectionPopupModel(id: 1, title: "Прием пищи 2"), - SelectionPopupModel(id: 2, title: "Прием пищи 3"), - SelectionPopupModel(id: 3, title: "Прием пищи 4"), - SelectionPopupModel(id: 4, title: "Прием пищи 5"), - SelectionPopupModel(id: 5, title: "Прием пищи 6"), - ]; -} diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_event.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_event.dart index 236ecbcd..206e5957 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_event.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_event.dart @@ -101,6 +101,13 @@ class UploadImages extends DiaryEditEvent { List get props => [image]; } +class ProductInput extends DiaryEditEvent { + ProductInput(this.input); + final String input; + @override + List get props => [input]; +} + class ChangeMeal extends DiaryEditEvent { ChangeMeal({required this.value, required this.meals}); diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_state.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_state.dart index 4ba46d61..c518e9af 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_state.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_state.dart @@ -24,6 +24,7 @@ class DiaryEditLoadedState extends DiaryEditState { this.token, this.meals, this.portions, + this.autocompleteList, this.wakeupController, this.retireController, this.commentController, @@ -43,6 +44,7 @@ class DiaryEditLoadedState extends DiaryEditState { String? token; List? meals; List? portions; + List? autocompleteList; SelectionPopupModel? currentMeal; TimeOfDay? wakeupController; TimeOfDay? retireController; @@ -61,6 +63,7 @@ class DiaryEditLoadedState extends DiaryEditState { diaryDate, token, meals, + autocompleteList, wakeupController, retireController, mealTimeController, @@ -81,6 +84,7 @@ class DiaryEditLoadedState extends DiaryEditState { String? token, List? meals, List? portions, + List? autocompleteList, TimeOfDay? wakeupController, TimeOfDay? retireController, TimeOfDay? mealTimeController, @@ -98,6 +102,7 @@ class DiaryEditLoadedState extends DiaryEditState { diaryDate: diaryDate ?? this.diaryDate, token: token ?? this.token, meals: meals ?? this.meals, + autocompleteList: autocompleteList ?? this.autocompleteList, portions: portions ?? this.portions, wakeupController: wakeupController ?? this.wakeupController, retireController: retireController ?? this.retireController, diff --git a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart index 04206dd4..2bc07d97 100644 --- a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart +++ b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart @@ -70,7 +70,6 @@ class DiaryEditScreen extends StatelessWidget { SizedBox(height: 30.v), _buildWakupRetire(context, state), SizedBox(height: 30.v), - //_buildImageStack(context), _buildMeal(context, state), SizedBox(height: 20.v), _buildMood(context, state), @@ -281,6 +280,11 @@ class DiaryEditScreen extends StatelessWidget { child: CustomTextFormField( hintText: "Введите названия продукта", controller: state.productNameController, + onChanged: (value) { + if (value.length > 3) { + context.read().add(ProductInput(value)); + } + }, ), ), SizedBox(height: 20.v), diff --git a/lib/widgets/custom_edit_text_form_field.dart b/lib/widgets/custom_edit_text_form_field.dart index 5a5687fb..5b27a43f 100644 --- a/lib/widgets/custom_edit_text_form_field.dart +++ b/lib/widgets/custom_edit_text_form_field.dart @@ -29,6 +29,7 @@ class CustomTextFormField extends StatelessWidget { this.filled = true, this.validator, this.keyboardType, + this.onChanged, this.onSaved, }) : super( key: key, @@ -84,6 +85,8 @@ class CustomTextFormField extends StatelessWidget { final void Function(String?)? onSaved; + final ValueChanged? onChanged; + @override Widget build(BuildContext context) { return alignment != null @@ -108,6 +111,7 @@ class CustomTextFormField extends StatelessWidget { validator: validator, keyboardType: keyboardType, onSaved: onSaved, + onChanged: onChanged, inputFormatters: inputFormatters, initialValue: initialValue, ), diff --git a/pubspec.yaml b/pubspec.yaml index 711ce10f..ac6ac205 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -25,6 +25,7 @@ dependencies: carousel_slider: ^4.2.1 flutter_form_builder: ^9.2.1 image_picker: ^1.0.7 + flutter_typeahead: ^5.2.0 dev_dependencies: flutter_test: