feat(inventory): filter by category and lot form + a11y polish

Add filter chips above the inventory list, one per category in use and
one per lot form actually held; results apply search ∧ category ∧ form.
An active filter that empties the list shows a distinct 'no matches'
state and a clear-filters button. VarietyListItem now carries the set of
lot forms it holds (one aggregate query), and the stream re-emits on lot
changes.

Accessibility: category headers use the text theme so they honour the
system font scale; the list avatar is excluded from semantics (the tile
title already announces the name); the edit action uses the green action
colour (≥3:1 on the canvas, up from 2.62:1). Add category/form/clear
filter tests and a tap-target-size guideline test.
This commit is contained in:
vjrj 2026-07-09 12:00:34 +02:00
parent 42c16c0e3f
commit 9558115c1e
9 changed files with 337 additions and 24 deletions

View file

@ -60,6 +60,8 @@
"title": "Inventory",
"searchHint": "Search seeds",
"empty": "No seeds yet. Tap + to add your first.",
"noMatches": "No seeds match your filters.",
"clearFilters": "Clear filters",
"uncategorized": "Uncategorized"
},
"quickAdd": {

View file

@ -60,6 +60,8 @@
"title": "Inventario",
"searchHint": "Buscar semillas",
"empty": "Aún no hay semillas. Toca + para añadir la primera.",
"noMatches": "Ninguna semilla coincide con los filtros.",
"clearFilters": "Quitar filtros",
"uncategorized": "Sin categoría"
},
"quickAdd": {

View file

@ -4,9 +4,9 @@
/// To regenerate, run: `dart run slang`
///
/// Locales: 2
/// Strings: 332 (166 per locale)
/// Strings: 336 (168 per locale)
///
/// Built on 2026-07-09 at 09:25 UTC
/// Built on 2026-07-09 at 09:55 UTC
// coverage:ignore-file
// ignore_for_file: type=lint, unused_import

View file

@ -268,6 +268,12 @@ class Translations$inventory$en {
/// en: 'No seeds yet. Tap + to add your first.'
String get empty => 'No seeds yet. Tap + to add your first.';
/// en: 'No seeds match your filters.'
String get noMatches => 'No seeds match your filters.';
/// en: 'Clear filters'
String get clearFilters => 'Clear filters';
/// en: 'Uncategorized'
String get uncategorized => 'Uncategorized';
}
@ -984,6 +990,8 @@ extension on Translations {
'inventory.title' => 'Inventory',
'inventory.searchHint' => 'Search seeds',
'inventory.empty' => 'No seeds yet. Tap + to add your first.',
'inventory.noMatches' => 'No seeds match your filters.',
'inventory.clearFilters' => 'Clear filters',
'inventory.uncategorized' => 'Uncategorized',
'quickAdd.title' => 'Add a seed',
'quickAdd.labelField' => 'Name',

View file

@ -174,6 +174,8 @@ class _Translations$inventory$es extends Translations$inventory$en {
@override String get title => 'Inventario';
@override String get searchHint => 'Buscar semillas';
@override String get empty => 'Aún no hay semillas. Toca + para añadir la primera.';
@override String get noMatches => 'Ninguna semilla coincide con los filtros.';
@override String get clearFilters => 'Quitar filtros';
@override String get uncategorized => 'Sin categoría';
}
@ -673,6 +675,8 @@ extension on TranslationsEs {
'inventory.title' => 'Inventario',
'inventory.searchHint' => 'Buscar semillas',
'inventory.empty' => 'Aún no hay semillas. Toca + para añadir la primera.',
'inventory.noMatches' => 'Ninguna semilla coincide con los filtros.',
'inventory.clearFilters' => 'Quitar filtros',
'inventory.uncategorized' => 'Sin categoría',
'quickAdd.title' => 'Añadir una semilla',
'quickAdd.labelField' => 'Nombre',