Autocomplete product names

This commit is contained in:
2024-02-27 16:10:11 +03:00
parent c0bffe5ae2
commit c072d46dee
6 changed files with 99 additions and 43 deletions

View File

@@ -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"),
];
}

View File

@@ -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});

View File

@@ -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,

View File

@@ -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),

View File

@@ -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,
),

View File

@@ -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: