calorimeter/lib/enter_food_widget.dart
Marco b83f547f6b Implement food entry lookup on entering a food name.
Now, an on-the-fly food lookup is created from existing entries on startup. Those entries are used to make suggestions when the user is typing to enter new food entries.
2024-09-04 22:47:37 +02:00

133 lines
4.3 KiB
Dart

import 'dart:developer';
import 'package:calodiary/storage/storage.dart';
import 'package:flutter/material.dart';
import 'package:calodiary/food_entry_bloc.dart';
import 'package:calodiary/row_with_spacers_widget.dart';
class EnterFoodWidget extends StatefulWidget {
final Function(BuildContext context, FoodEntry entry) onAdd;
const EnterFoodWidget({super.key, required this.onAdd});
@override
State<EnterFoodWidget> createState() => _EnterFoodWidgetState();
}
class _EnterFoodWidgetState extends State<EnterFoodWidget> {
String perFoodresult = "dings";
TextEditingController nameController = TextEditingController();
TextEditingController massController = TextEditingController();
TextEditingController kcalPerMassController = TextEditingController();
Map<String, double> suggestions = {};
@override
void initState() {
suggestions = FoodStorage.getInstance().getFoodEntryLookupDatabase;
super.initState();
}
@override
Widget build(BuildContext context) {
var nameWidget = Autocomplete<String>(
optionsViewOpenDirection: OptionsViewOpenDirection.down,
fieldViewBuilder: (context, controller, focusNode, onSubmitted) {
nameController = controller;
return TextFormField(
controller: controller,
focusNode: focusNode,
decoration: const InputDecoration(label: Text("Name")));
},
optionsBuilder: (TextEditingValue textEditingValue) {
if (textEditingValue.text == '') {
return const Iterable<String>.empty();
}
return suggestions.keys.where(
(name) {
return name
.toLowerCase()
.contains(textEditingValue.text.toLowerCase());
},
);
},
onSelected: (selectedFood) {
double kcalPerMassForSelectedFood = suggestions[selectedFood]!;
setState(() {
kcalPerMassController.text = kcalPerMassForSelectedFood.toString();
});
});
var massWidget = TextField(
decoration: const InputDecoration(label: Text("Menge")),
keyboardType: TextInputType.number,
controller: massController,
);
var kcalPerMassWidget = TextField(
decoration: const InputDecoration(label: Text("kcal pro")),
keyboardType: TextInputType.number,
controller: kcalPerMassController);
var enterButton = ElevatedButton(
style: ElevatedButton.styleFrom(
padding: EdgeInsets.zero,
),
onPressed: () {
double massAsNumber = 0.0;
double kcalPerMassAsNumber = 0.0;
try {
massAsNumber =
double.parse(massController.text.replaceAll(",", "."));
} catch (e) {
var snackbar =
const SnackBar(content: Text("Menge muss eine Zahl sein"));
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(snackbar);
return;
}
try {
kcalPerMassAsNumber =
double.parse(kcalPerMassController.text.replaceAll(",", "."));
} catch (e) {
var snackbar = const SnackBar(
content: Text("'kcal pro 100g' muss eine Zahl sein"));
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(snackbar);
return;
}
try {
massAsNumber =
double.parse(massController.text.replaceAll(",", "."));
} catch (e) {
var snackbar =
const SnackBar(content: Text("Menge muss eine Zahl sein"));
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(snackbar);
return;
}
var entry = FoodEntry(
name: nameController.text,
mass: massAsNumber,
kcalPerMass: kcalPerMassAsNumber);
widget.onAdd(context, entry);
},
child: const Icon(Icons.add));
return Padding(
padding: const EdgeInsets.only(left: 8.0, right: 4.0),
child: RowWidget(
nameWidget,
massWidget,
kcalPerMassWidget,
null,
enterButton,
),
);
}
}