diff --git a/lib/features/shopping_list/models/shopping_item.dart b/lib/features/shopping_list/models/shopping_item.dart index 8f8854d..e126947 100644 --- a/lib/features/shopping_list/models/shopping_item.dart +++ b/lib/features/shopping_list/models/shopping_item.dart @@ -2,29 +2,34 @@ class ShoppingItem { final String id; final String name; final bool checked; + final int quantity; const ShoppingItem({ required this.id, required this.name, this.checked = false, + this.quantity = 1, }); - ShoppingItem copyWith({String? id, String? name, bool? checked}) => + ShoppingItem copyWith({String? id, String? name, bool? checked, int? quantity}) => ShoppingItem( id: id ?? this.id, name: name ?? this.name, checked: checked ?? this.checked, + quantity: quantity ?? this.quantity, ); Map toJson() => { 'id': id, 'name': name, 'checked': checked, + 'quantity': quantity, }; factory ShoppingItem.fromJson(Map json) => ShoppingItem( id: json['id'] as String, name: json['name'] as String, checked: json['checked'] as bool? ?? false, + quantity: json['quantity'] as int? ?? 1, ); } diff --git a/lib/features/shopping_list/presentation/widgets/shopping_item_tile.dart b/lib/features/shopping_list/presentation/widgets/shopping_item_tile.dart index d022c8c..fccc768 100644 --- a/lib/features/shopping_list/presentation/widgets/shopping_item_tile.dart +++ b/lib/features/shopping_list/presentation/widgets/shopping_item_tile.dart @@ -32,14 +32,33 @@ class ShoppingItemTile extends StatelessWidget { ), ), Expanded( - child: Text( - item.name, - style: item.checked - ? theme.textTheme.bodyMedium?.copyWith( - decoration: TextDecoration.lineThrough, - color: muted, - ) - : theme.textTheme.bodyMedium, + child: Row( + children: [ + Expanded( + child: Text( + item.name, + style: item.checked + ? theme.textTheme.bodyMedium?.copyWith( + decoration: TextDecoration.lineThrough, + color: muted, + ) + : theme.textTheme.bodyMedium, + ), + ), + if (item.quantity > 1) + Padding( + padding: const EdgeInsets.only(left: 6), + child: Text( + '(x${item.quantity})', + style: theme.textTheme.bodySmall?.copyWith( + color: item.checked + ? muted + : theme.colorScheme.primary, + fontWeight: FontWeight.w600, + ), + ), + ), + ], ), ), IconButton( diff --git a/lib/features/shopping_list/providers/shopping_list_provider.dart b/lib/features/shopping_list/providers/shopping_list_provider.dart index e4b020a..d100f40 100644 --- a/lib/features/shopping_list/providers/shopping_list_provider.dart +++ b/lib/features/shopping_list/providers/shopping_list_provider.dart @@ -49,16 +49,26 @@ class ShoppingListProvider extends ChangeNotifier { void addAll(List names) { final existing = _items.map((i) => i.name.toLowerCase()).toSet(); - final seen = {}; - final toAdd = []; + + // Conta le occorrenze mantenendo il nome nella sua forma originale (prima occorrenza) + final counts = {}; + final canonical = {}; for (final name in names) { final key = name.toLowerCase().trim(); - if (key.isNotEmpty && !existing.contains(key) && seen.add(key)) { - toAdd.add(ShoppingItem( - id: '${DateTime.now().millisecondsSinceEpoch}_${seen.length}', - name: name.trim(), - )); - } + if (key.isEmpty) continue; + counts[key] = (counts[key] ?? 0) + 1; + canonical.putIfAbsent(key, () => name.trim()); + } + + final toAdd = []; + var i = 0; + for (final entry in counts.entries) { + if (existing.contains(entry.key)) continue; + toAdd.add(ShoppingItem( + id: '${DateTime.now().millisecondsSinceEpoch}_${i++}', + name: canonical[entry.key]!, + quantity: entry.value, + )); } if (toAdd.isEmpty) return; _items = [..._items, ...toAdd];