forked from eatvio/eatvio_app
Autocomplete product names
This commit is contained in:
@@ -30,6 +30,8 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
|
||||
_removePortion); // пользователь нажимает на крестик около продукта
|
||||
on<UploadImages>(_uploadImages); //пользователь нажимает "Добавить фото"
|
||||
on<AddComment>(_addComment); //пользователь нажимает "Добавить комментарий"
|
||||
on<ProductInput>(
|
||||
_inputProduct); //пользователь нажимает "Добавить комментарий"
|
||||
}
|
||||
|
||||
Future<void> _onInitialize(
|
||||
@@ -83,6 +85,7 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
|
||||
diaryId: currentState.diaryId,
|
||||
productQuantityController:
|
||||
currentState.productQuantityController,
|
||||
autocompleteList: currentState.autocompleteList,
|
||||
diaryEditModelObj: currentState.diaryEditModelObj));
|
||||
} else {
|
||||
// Если текущее состояние - начальное, создаем новое загруженное состояние
|
||||
@@ -106,6 +109,7 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
|
||||
productQuantityController: TextEditingController(),
|
||||
diaryId: diaryId,
|
||||
diaryDate: diaryDate,
|
||||
autocompleteList: [],
|
||||
diaryEditModelObj: state.diaryEditModelObj
|
||||
?.copyWith(mealList: fillMealList())));
|
||||
}
|
||||
@@ -284,7 +288,7 @@ class DiaryEditBloc extends Bloc<DiaryEditEvent, DiaryEditState> {
|
||||
}
|
||||
|
||||
Future<http.Response> 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<DiaryEditEvent, DiaryEditState> {
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _removePortion(
|
||||
RemovePortionEvent event, Emitter<DiaryEditState> emit) {}
|
||||
FutureOr<void> _inputProduct(
|
||||
ProductInput event, Emitter<DiaryEditState> 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<String, dynamic>) {
|
||||
var updatedState = currentState.copyWith(
|
||||
autocompleteList: productNutritionalValues.values
|
||||
.map((value) => value['name'])
|
||||
.toList());
|
||||
|
||||
Future<FutureOr<void>> _uploadImages(
|
||||
UploadImages event, Emitter<DiaryEditState> emit) async {
|
||||
String imageUrl = await uploadImageToServer(event.image.path);
|
||||
print(imageUrl);
|
||||
}
|
||||
emit(updatedState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _addComment(AddComment event, Emitter<DiaryEditState> emit) {}
|
||||
Future<String> uploadImageToServer(String imagePath) async {
|
||||
var request = http.MultipartRequest(
|
||||
'POST',
|
||||
Uri.parse('http://your-api-url.com/upload'), // Замените на ваш маршрут API
|
||||
);
|
||||
FutureOr<void> _removePortion(
|
||||
RemovePortionEvent event, Emitter<DiaryEditState> emit) {}
|
||||
|
||||
request.files.add(await http.MultipartFile.fromPath('image', imagePath));
|
||||
Future<FutureOr<void>> _uploadImages(
|
||||
UploadImages event, Emitter<DiaryEditState> 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<void> _addComment(AddComment event, Emitter<DiaryEditState> emit) {}
|
||||
Future<String> 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<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() {
|
||||
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<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() {
|
||||
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"),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -101,6 +101,13 @@ class UploadImages extends DiaryEditEvent {
|
||||
List<Object> get props => [image];
|
||||
}
|
||||
|
||||
class ProductInput extends DiaryEditEvent {
|
||||
ProductInput(this.input);
|
||||
final String input;
|
||||
@override
|
||||
List<Object> get props => [input];
|
||||
}
|
||||
|
||||
class ChangeMeal extends DiaryEditEvent {
|
||||
ChangeMeal({required this.value, required this.meals});
|
||||
|
||||
|
||||
@@ -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<dynamic>? meals;
|
||||
List<dynamic>? portions;
|
||||
List<dynamic>? 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<dynamic>? meals,
|
||||
List<dynamic>? portions,
|
||||
List<dynamic>? 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,
|
||||
|
||||
@@ -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<DiaryEditBloc>().add(ProductInput(value));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20.v),
|
||||
|
||||
@@ -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<String>? 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,
|
||||
),
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user