diff --git a/lib/widgets/nutrition/forms.dart b/lib/widgets/nutrition/forms.dart index f5b2e7c1..7ba3443e 100644 --- a/lib/widgets/nutrition/forms.dart +++ b/lib/widgets/nutrition/forms.dart @@ -169,7 +169,6 @@ class IngredientFormState extends State { final _timeController = TextEditingController(); // optional final _mealItem = MealItem.empty(); - bool validIngredientId = false; @override void initState() { super.initState(); @@ -287,7 +286,7 @@ class IngredientFormState extends State { ), ], ), - if (validIngredientId) + if (ingredientIdController.text.isNotEmpty) Padding( padding: const EdgeInsets.all(8.0), child: Column( @@ -302,10 +301,9 @@ class IngredientFormState extends State { builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.hasData) { _mealItem.ingredient = snapshot.data!; - return ListTile( - leading: IngredientAvatar(ingredient: _mealItem.ingredient), - title: - Text(getShortNutritionValues(_mealItem.nutritionalValues, context)), + return MealItemTile( + ingredient: _mealItem.ingredient, + nutritionalValues: _mealItem.nutritionalValues, ); } else if (snapshot.hasError) { return Padding( @@ -365,14 +363,13 @@ class IngredientFormState extends State { return Card( child: ListTile( onTap: () { - _ingredientController.text = widget.recent[index].ingredient.name; - _ingredientIdController.text = - widget.recent[index].ingredient.id.toString(); - _amountController.text = widget.recent[index].amount.toStringAsFixed(0); setState(() { + _ingredientController.text = widget.recent[index].ingredient.name; + _ingredientIdController.text = + widget.recent[index].ingredient.id.toString(); + _amountController.text = widget.recent[index].amount.toStringAsFixed(0); _mealItem.ingredientId = widget.recent[index].ingredientId; _mealItem.amount = widget.recent[index].amount; - validIngredientId = true; }); }, title: Text( diff --git a/lib/widgets/nutrition/widgets.dart b/lib/widgets/nutrition/widgets.dart index 0cc2d24c..074d5713 100644 --- a/lib/widgets/nutrition/widgets.dart +++ b/lib/widgets/nutrition/widgets.dart @@ -32,6 +32,7 @@ import 'package:wger/models/exercises/ingredient_api.dart'; import 'package:wger/models/nutrition/ingredient.dart'; import 'package:wger/models/nutrition/log.dart'; import 'package:wger/models/nutrition/nutritional_plan.dart'; +import 'package:wger/models/nutrition/nutritional_values.dart'; import 'package:wger/providers/nutrition.dart'; import 'package:wger/widgets/core/core.dart'; import 'package:wger/widgets/nutrition/helpers.dart'; @@ -118,6 +119,11 @@ class _IngredientTypeaheadState extends State { } return null; }, + onChanged: (value) { + // if user changes the pattern, it means they want to drop the + // currently loaded ingredient (if any) and start a new search + widget._ingredientIdController.text = ''; + }, decoration: InputDecoration( prefixIcon: const Icon(Icons.search), labelText: AppLocalizations.of(context).searchIngredient, @@ -126,7 +132,8 @@ class _IngredientTypeaheadState extends State { ); }, suggestionsCallback: (pattern) { - if (pattern == '') { + // don't do search if user has already loaded a specific item + if (pattern == '' || widget._ingredientIdController.text.isNotEmpty) { return null; } @@ -188,6 +195,7 @@ class _IngredientTypeaheadState extends State { } final result = await Provider.of(context, listen: false) .searchIngredientWithCode(barcode); + // TODO: show spinner... if (!mounted) { return; } @@ -198,7 +206,16 @@ class _IngredientTypeaheadState extends State { builder: (ctx) => AlertDialog( key: const Key('found-dialog'), title: Text(AppLocalizations.of(context).productFound), - content: Text(AppLocalizations.of(context).productFoundDescription(result.name)), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text(AppLocalizations.of(context).productFoundDescription(result.name)), + MealItemTile( + ingredient: result, + nutritionalValues: result.nutritionalValues, + ), + ], + ), actions: [ TextButton( key: const Key('found-dialog-confirm-button'), @@ -357,3 +374,23 @@ class IngredientAvatar extends StatelessWidget { : const CircleIconAvatar(Icon(Icons.image, color: Colors.grey)); } } + +class MealItemTile extends StatelessWidget { + final Ingredient ingredient; + final NutritionalValues nutritionalValues; + + const MealItemTile({ + super.key, + required this.ingredient, + required this.nutritionalValues, + }); + + @override + Widget build(BuildContext context) { + return ListTile( + leading: IngredientAvatar(ingredient: ingredient), + title: Text(getShortNutritionValues(nutritionalValues, context)), + subtitle: Text(ingredient.id.toString()), + ); + } +}