feat: add support for alternative ingredients; implement JSON storage and parsing logic
Test Suite / test (24.15.0) (push) Has been cancelled

This commit is contained in:
Nils-Johan Gynther
2026-05-04 22:06:57 +02:00
parent 64f63b3392
commit 2c8d6b69ae
9 changed files with 180 additions and 9 deletions
@@ -23,6 +23,7 @@ class ParsedIngredient {
final String unit;
final String? note;
final List<IngredientSuggestion> suggestions;
final List<String> alternatives;
const ParsedIngredient({
required this.rawName,
@@ -30,6 +31,7 @@ class ParsedIngredient {
required this.unit,
this.note,
required this.suggestions,
this.alternatives = const [],
});
factory ParsedIngredient.fromJson(Map<String, dynamic> json) {
@@ -42,6 +44,9 @@ class ParsedIngredient {
suggestions: rawSuggestions
.map((s) => IngredientSuggestion.fromJson(s as Map<String, dynamic>))
.toList(),
alternatives: (json['alternatives'] as List<dynamic>? ?? [])
.map((a) => a as String)
.toList(),
);
}
}
@@ -149,11 +149,21 @@ class _CreateRecipeScreenState extends ConsumerState<CreateRecipeScreen> {
_parsed!.ingredients[i].quantity;
final unit = _unitControllers[i]!.text.trim();
final note = _noteControllers[i]!.text.trim();
final ing = _parsed!.ingredients[i];
// Alternativa produkter: alla suggestions vars productId matchar ett alternativ
final alternativeProductIds = ing.alternatives.length > 1
? ing.suggestions
.where((s) => s.productId != productId)
.map((s) => s.productId)
.toList()
: <int>[];
ingredients.add({
'productId': productId,
'quantity': qty,
'unit': unit,
if (note.isNotEmpty) 'note': note,
if (alternativeProductIds.isNotEmpty)
'alternativeProductIds': alternativeProductIds,
});
}
@@ -339,7 +349,19 @@ class _CreateRecipeScreenState extends ConsumerState<CreateRecipeScreen> {
CheckboxListTile(
value: isIncluded,
onChanged: (v) => setState(() => _included[index] = v ?? false),
title: Text(ing.rawName),
title: ing.alternatives.length > 1
? Wrap(
spacing: 4,
children: ing.alternatives
.map((alt) => Chip(
label: Text(alt),
padding: EdgeInsets.zero,
materialTapTargetSize:
MaterialTapTargetSize.shrinkWrap,
))
.toList(),
)
: Text(ing.rawName),
subtitle: noProductFound
? Text(
context.l10n.recipeCreateNoProductFound,