From 7e92410728b4c26bb7e81fd201ff9d526dcd47e8 Mon Sep 17 00:00:00 2001 From: vjrj Date: Wed, 8 Jul 2026 11:03:57 +0200 Subject: [PATCH] refine(quantity): drop handful, reorder scale, potted-plant icon, year dropdown Feedback from the running app: - Remove "handful" from the scale (redundant with spoon); keep the enum value. - Reorder so "packet" (sobre) follows "spoon" (cuchara). - Use the Material Symbols potted-plant for the plant lot type and plant unit (adds material_symbols_icons). - Harvest year is now a dropdown of recent years instead of free text. 38 tests green; Linux build runs with the new icon font bundled. --- apps/app_seeds/lib/ui/quantity_picker.dart | 7 ++++--- apps/app_seeds/lib/ui/seed_glyph.dart | 3 ++- .../lib/ui/variety_detail_screen.dart | 20 ++++++++++++++----- apps/app_seeds/pubspec.yaml | 1 + .../test/ui/variety_detail_screen_test.dart | 9 ++++++--- pubspec.lock | 8 ++++++++ 6 files changed, 36 insertions(+), 12 deletions(-) diff --git a/apps/app_seeds/lib/ui/quantity_picker.dart b/apps/app_seeds/lib/ui/quantity_picker.dart index c03f0b7..e380095 100644 --- a/apps/app_seeds/lib/ui/quantity_picker.dart +++ b/apps/app_seeds/lib/ui/quantity_picker.dart @@ -1,5 +1,6 @@ import 'package:commons_core/commons_core.dart'; import 'package:flutter/material.dart'; +import 'package:material_symbols_icons/symbols.dart'; import '../db/enums.dart'; import '../i18n/strings.g.dart'; @@ -8,15 +9,15 @@ import 'seed_glyph.dart'; import 'theme.dart'; /// Informal seed amounts, ascending: vibes → containers → seed/fruit forms. +/// ([QuantityKind.handful] is intentionally omitted — it overlaps with spoon.) const seedScaleKinds = [ QuantityKind.aFew, - QuantityKind.handful, QuantityKind.teaspoon, QuantityKind.spoon, + QuantityKind.packet, QuantityKind.cup, QuantityKind.jar, QuantityKind.sack, - QuantityKind.packet, QuantityKind.cob, QuantityKind.pod, QuantityKind.ear, @@ -61,7 +62,7 @@ class LotTypeSelector extends StatelessWidget { ButtonSegment( value: LotType.plant, label: Text(t.lotType.plant), - icon: const Icon(Icons.local_florist_outlined, size: 18), + icon: const Icon(Symbols.potted_plant, size: 18), ), ], selected: {value}, diff --git a/apps/app_seeds/lib/ui/seed_glyph.dart b/apps/app_seeds/lib/ui/seed_glyph.dart index 1da185b..4489967 100644 --- a/apps/app_seeds/lib/ui/seed_glyph.dart +++ b/apps/app_seeds/lib/ui/seed_glyph.dart @@ -1,5 +1,6 @@ import 'package:commons_core/commons_core.dart'; import 'package:flutter/material.dart'; +import 'package:material_symbols_icons/symbols.dart'; /// Renders a glyph from the bundled `seedks` icon font, whose characters `a`–`k` /// map to seed-themed pictograms (jar, packet, spoon…). See @@ -63,7 +64,7 @@ IconData _materialIconForKind(QuantityKind kind) => switch (kind) { QuantityKind.cob || QuantityKind.ear => Icons.grass, QuantityKind.head || QuantityKind.seedHead => Icons.filter_vintage_outlined, QuantityKind.fruit => Icons.local_florist_outlined, - QuantityKind.plant => Icons.local_florist_outlined, + QuantityKind.plant => Symbols.potted_plant, QuantityKind.pot => Icons.yard_outlined, QuantityKind.tray => Icons.grid_on_outlined, QuantityKind.bulb || diff --git a/apps/app_seeds/lib/ui/variety_detail_screen.dart b/apps/app_seeds/lib/ui/variety_detail_screen.dart index d1d6de7..c8252d8 100644 --- a/apps/app_seeds/lib/ui/variety_detail_screen.dart +++ b/apps/app_seeds/lib/ui/variety_detail_screen.dart @@ -477,7 +477,11 @@ class _EditVarietySheetState extends State<_EditVarietySheet> { Future _showAddLotSheet(BuildContext context, VarietyDetailCubit cubit) { final t = context.t; - final yearController = TextEditingController(); + final currentYear = DateTime.now().year; + // Harvest years: current year down through the last four decades. Newest + // first because a freshly harvested lot is the common case. + final years = [for (var y = currentYear; y >= currentYear - 40; y--) y]; + var selectedYear = currentYear; var selectedType = LotType.seed; Quantity? selectedQuantity; return showModalBottomSheet( @@ -508,14 +512,20 @@ Future _showAddLotSheet(BuildContext context, VarietyDetailCubit cubit) { }), ), const SizedBox(height: 12), - TextField( + DropdownButtonFormField( key: const Key('addLot.year'), - controller: yearController, - keyboardType: TextInputType.number, + initialValue: selectedYear, decoration: InputDecoration( labelText: t.addLot.year, border: const OutlineInputBorder(), ), + items: [ + for (final y in years) + DropdownMenuItem(value: y, child: Text('$y')), + ], + onChanged: (value) { + if (value != null) setState(() => selectedYear = value); + }, ), const SizedBox(height: 16), Text( @@ -541,7 +551,7 @@ Future _showAddLotSheet(BuildContext context, VarietyDetailCubit cubit) { onPressed: () { cubit.addLot( type: selectedType, - year: int.tryParse(yearController.text.trim()), + year: selectedYear, quantity: selectedQuantity, ); Navigator.of(sheetContext).pop(); diff --git a/apps/app_seeds/pubspec.yaml b/apps/app_seeds/pubspec.yaml index f2cf588..9c6f9b8 100644 --- a/apps/app_seeds/pubspec.yaml +++ b/apps/app_seeds/pubspec.yaml @@ -48,6 +48,7 @@ dependencies: path_provider: ^2.1.5 cupertino_icons: ^1.0.8 + material_symbols_icons: ^4.2951.0 dev_dependencies: flutter_test: diff --git a/apps/app_seeds/test/ui/variety_detail_screen_test.dart b/apps/app_seeds/test/ui/variety_detail_screen_test.dart index d0a2160..38f3c06 100644 --- a/apps/app_seeds/test/ui/variety_detail_screen_test.dart +++ b/apps/app_seeds/test/ui/variety_detail_screen_test.dart @@ -83,14 +83,17 @@ void main() { await tester.tap(find.byKey(const Key('detail.addLot'))); await tester.pumpAndSettle(); - await tester.enterText(find.byKey(const Key('addLot.year')), '2023'); - await tester.tap(find.text('handful')); // pick the unit from the scale + await tester.tap(find.byKey(const Key('addLot.year'))); + await tester.pumpAndSettle(); + await tester.tap(find.text('2023').last); // pick the year from the dropdown + await tester.pumpAndSettle(); + await tester.tap(find.text('spoon')); // pick the unit from the scale await tester.pumpAndSettle(); await tester.enterText(find.byKey(const Key('quantity.count')), '2'); await tester.tap(find.byKey(const Key('addLot.save'))); await tester.pumpAndSettle(); - expect(find.text('Year 2023 · 2 handfuls'), findsOneWidget); + expect(find.text('Year 2023 · 2 spoons'), findsOneWidget); await disposeTree(tester); }); diff --git a/pubspec.lock b/pubspec.lock index c86fb7e..e1f463d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -644,6 +644,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.13.0" + material_symbols_icons: + dependency: transitive + description: + name: material_symbols_icons + sha256: "49c532dd0b74544e9d8d93ec0f821d52ec532e7c9263c889ebe71b1be4f34ba7" + url: "https://pub.dev" + source: hosted + version: "4.2951.0" meta: dependency: transitive description: