feat(block1): variety detail + edit screen with reactive lots
Tapping an inventory item now opens its detail (the /variety/:id route was a
placeholder). Read + edit one variety end-to-end:
- Detail view: photo, category, "also known as" names, notes and lots, driven
by a reactive VarietyDetailCubit.
- Edit core fields (label/category/notes, LWW) via a bottom sheet.
- Add a lot (harvest year + quantity) — the list refreshes reactively.
- Soft-delete (tombstone) with a confirm dialog.
Repository:
- watchVariety(id): merges Drift table-change streams (variety, lots, names,
attachments) via StreamGroup and reloads the full detail on any change, so a
lot added to a *different* table still refreshes the view.
- updateVariety (LWW), addLot, softDeleteVariety.
i18n: detail/edit/addLot strings (ES/EN); switched slang to {param} braces
interpolation (translator- and Weblate-friendly).
Tests: repository (reactive watchVariety, update, soft-delete) and widget tests
(render, edit updates title, add-lot appears, delete shows not-found). Full
suite green: 23 passing, 1 skipped (SQLCipher-only encryption guard).
This commit is contained in:
parent
040f15a898
commit
7ff4e38a15
15 changed files with 1093 additions and 18 deletions
|
|
@ -41,8 +41,12 @@ class Translations with BaseTranslations<AppLocale, Translations> {
|
|||
|
||||
// Translations
|
||||
late final Translations$app$en app = Translations$app$en.internal(_root);
|
||||
late final Translations$common$en common = Translations$common$en.internal(_root);
|
||||
late final Translations$inventory$en inventory = Translations$inventory$en.internal(_root);
|
||||
late final Translations$quickAdd$en quickAdd = Translations$quickAdd$en.internal(_root);
|
||||
late final Translations$detail$en detail = Translations$detail$en.internal(_root);
|
||||
late final Translations$editVariety$en editVariety = Translations$editVariety$en.internal(_root);
|
||||
late final Translations$addLot$en addLot = Translations$addLot$en.internal(_root);
|
||||
late final Translations$quantityKind$en quantityKind = Translations$quantityKind$en.internal(_root);
|
||||
}
|
||||
|
||||
|
|
@ -58,6 +62,27 @@ class Translations$app$en {
|
|||
String get title => 'Tanemaki';
|
||||
}
|
||||
|
||||
// Path: common
|
||||
class Translations$common$en {
|
||||
Translations$common$en.internal(this._root);
|
||||
|
||||
final Translations _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
|
||||
/// en: 'Save'
|
||||
String get save => 'Save';
|
||||
|
||||
/// en: 'Cancel'
|
||||
String get cancel => 'Cancel';
|
||||
|
||||
/// en: 'Delete'
|
||||
String get delete => 'Delete';
|
||||
|
||||
/// en: 'Edit'
|
||||
String get edit => 'Edit';
|
||||
}
|
||||
|
||||
// Path: inventory
|
||||
class Translations$inventory$en {
|
||||
Translations$inventory$en.internal(this._root);
|
||||
|
|
@ -112,6 +137,81 @@ class Translations$quickAdd$en {
|
|||
String get cancel => 'Cancel';
|
||||
}
|
||||
|
||||
// Path: detail
|
||||
class Translations$detail$en {
|
||||
Translations$detail$en.internal(this._root);
|
||||
|
||||
final Translations _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
|
||||
/// en: 'This seed is no longer here.'
|
||||
String get notFound => 'This seed is no longer here.';
|
||||
|
||||
/// en: 'Lots'
|
||||
String get lots => 'Lots';
|
||||
|
||||
/// en: 'No lots yet.'
|
||||
String get noLots => 'No lots yet.';
|
||||
|
||||
/// en: 'Also known as'
|
||||
String get names => 'Also known as';
|
||||
|
||||
/// en: 'Notes'
|
||||
String get notes => 'Notes';
|
||||
|
||||
/// en: 'Add lot'
|
||||
String get addLot => 'Add lot';
|
||||
|
||||
/// en: 'Delete this seed?'
|
||||
String get deleteConfirm => 'Delete this seed?';
|
||||
|
||||
/// en: 'Year {year}'
|
||||
String year({required Object year}) => 'Year ${year}';
|
||||
|
||||
/// en: 'Year unknown'
|
||||
String get noYear => 'Year unknown';
|
||||
}
|
||||
|
||||
// Path: editVariety
|
||||
class Translations$editVariety$en {
|
||||
Translations$editVariety$en.internal(this._root);
|
||||
|
||||
final Translations _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
|
||||
/// en: 'Edit seed'
|
||||
String get title => 'Edit seed';
|
||||
|
||||
/// en: 'Name'
|
||||
String get name => 'Name';
|
||||
|
||||
/// en: 'Category'
|
||||
String get category => 'Category';
|
||||
|
||||
/// en: 'Notes'
|
||||
String get notes => 'Notes';
|
||||
}
|
||||
|
||||
// Path: addLot
|
||||
class Translations$addLot$en {
|
||||
Translations$addLot$en.internal(this._root);
|
||||
|
||||
final Translations _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
|
||||
/// en: 'Add lot'
|
||||
String get title => 'Add lot';
|
||||
|
||||
/// en: 'Harvest year'
|
||||
String get year => 'Harvest year';
|
||||
|
||||
/// en: 'Quantity'
|
||||
String get quantity => 'Quantity';
|
||||
}
|
||||
|
||||
// Path: quantityKind
|
||||
class Translations$quantityKind$en {
|
||||
Translations$quantityKind$en.internal(this._root);
|
||||
|
|
@ -184,6 +284,10 @@ extension on Translations {
|
|||
dynamic _flatMapFunction(String path) {
|
||||
return switch (path) {
|
||||
'app.title' => 'Tanemaki',
|
||||
'common.save' => 'Save',
|
||||
'common.cancel' => 'Cancel',
|
||||
'common.delete' => 'Delete',
|
||||
'common.edit' => 'Edit',
|
||||
'inventory.title' => 'Inventory',
|
||||
'inventory.searchHint' => 'Search seeds',
|
||||
'inventory.empty' => 'No seeds yet. Tap + to add your first.',
|
||||
|
|
@ -196,6 +300,22 @@ extension on Translations {
|
|||
'quickAdd.more' => 'Add more…',
|
||||
'quickAdd.save' => 'Save',
|
||||
'quickAdd.cancel' => 'Cancel',
|
||||
'detail.notFound' => 'This seed is no longer here.',
|
||||
'detail.lots' => 'Lots',
|
||||
'detail.noLots' => 'No lots yet.',
|
||||
'detail.names' => 'Also known as',
|
||||
'detail.notes' => 'Notes',
|
||||
'detail.addLot' => 'Add lot',
|
||||
'detail.deleteConfirm' => 'Delete this seed?',
|
||||
'detail.year' => ({required Object year}) => 'Year ${year}',
|
||||
'detail.noYear' => 'Year unknown',
|
||||
'editVariety.title' => 'Edit seed',
|
||||
'editVariety.name' => 'Name',
|
||||
'editVariety.category' => 'Category',
|
||||
'editVariety.notes' => 'Notes',
|
||||
'addLot.title' => 'Add lot',
|
||||
'addLot.year' => 'Harvest year',
|
||||
'addLot.quantity' => 'Quantity',
|
||||
'quantityKind.aFew' => 'a few',
|
||||
'quantityKind.some' => 'some',
|
||||
'quantityKind.plenty' => 'plenty',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue