calorimeter/lib/food_entry/enter_food_widget.dart
Marco a7a7f44050 Make scanned widgets appear in the list instead of putting the info into
the EnterFoodWidget.

1. Make scanned foods appear in the list of foods
2. Remove Controller for entering food

This commit removes the EnterFoodController that was used to put a
scanned food into the EnterFoodWidget.
This is now unnecessary because scanning a product will be distributed
via the FoodBLoC.
2024-09-24 14:41:42 +02:00

141 lines
4.5 KiB
Dart

import 'package:calorimeter/storage/storage.dart';
import 'package:flutter/material.dart';
import 'package:calorimeter/food_entry/food_entry_bloc.dart';
import 'package:calorimeter/utils/row_with_spacers_widget.dart';
import 'package:provider/provider.dart';
class EnterFoodWidget extends StatefulWidget {
final Function(BuildContext context, FoodEntryState entry) onAdd;
const EnterFoodWidget({super.key, required this.onAdd});
@override
State<EnterFoodWidget> createState() => _EnterFoodWidgetState();
}
class _EnterFoodWidgetState extends State<EnterFoodWidget> {
late TextEditingController nameController;
late TextEditingController massController;
late TextEditingController kcalPerMassController;
late Map<String, int> suggestions;
@override
void initState() {
nameController = TextEditingController();
massController = TextEditingController();
kcalPerMassController = TextEditingController();
suggestions = FoodStorage.getInstance().getFoodEntryLookupDatabase;
super.initState();
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: RowWidget(
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) {
int kcalPerMassForSelectedFood = suggestions[selectedFood]!;
setState(() {
nameController.text = selectedFood;
kcalPerMassController.text =
kcalPerMassForSelectedFood.toString();
});
}),
TextField(
textAlign: TextAlign.end,
decoration: const InputDecoration(
label:
Align(alignment: Alignment.centerRight, child: Text("Menge")),
),
keyboardType: TextInputType.number,
controller: massController,
onSubmitted: (value) => onSubmitAction(),
),
TextField(
textAlign: TextAlign.end,
decoration: const InputDecoration(
label: Align(
alignment: Alignment.centerRight, child: Text("kcal pro"))),
keyboardType: TextInputType.number,
controller: kcalPerMassController,
onSubmitted: (value) => onSubmitAction(),
),
Padding(
padding: const EdgeInsets.only(left: 16.0),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
padding: EdgeInsets.zero,
),
onPressed: () => onSubmitAction(),
child: const Icon(Icons.add)),
),
),
);
}
void onSubmitAction() {
int massAsNumber = 0;
int kcalPerMassAsNumber = 0;
try {
massAsNumber = int.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 =
int.parse(kcalPerMassController.text.replaceAll(",", "."));
} catch (e) {
var snackbar =
const SnackBar(content: Text("'kcal pro 100g' muss eine Zahl sein"));
ScaffoldMessenger.of(context).removeCurrentSnackBar();
ScaffoldMessenger.of(context).showSnackBar(snackbar);
return;
}
var entry = FoodEntryState(
name: nameController.text,
mass: massAsNumber,
kcalPerMass: kcalPerMassAsNumber,
waitingForNetwork: false,
);
widget.onAdd(context, entry);
setState(() {
nameController.text = "";
massController.text = "";
kcalPerMassController.text = "";
});
}
}