feat(app): show each batch's story as a composite timeline
The Movement log (history + provenance DAG) was recorded but invisible. A new history sheet on every lot tile narrates the batch: movements, germination tests, storage checks and how it entered the collection (origin attached), most-recent first. Two one-tap chips record 'sown today' / 'harvested today' — the first UI door to the sown/harvested movement types. No schema change; one-shot reads only (no live subscriptions in a transient sheet).
This commit is contained in:
parent
11cbdf3022
commit
92fd84590b
10 changed files with 835 additions and 2 deletions
|
|
@ -700,6 +700,25 @@
|
|||
"promiseGave": "They'll return me seed",
|
||||
"promiseReceived": "I'll return seed"
|
||||
},
|
||||
"history": {
|
||||
"title": "Story of this batch",
|
||||
"tooltip": "Story",
|
||||
"sowToday": "Sown today",
|
||||
"harvestToday": "Harvested today",
|
||||
"sownRecorded": "Sowing noted",
|
||||
"harvestRecorded": "Harvest noted",
|
||||
"movementReceived": "Received",
|
||||
"movementGiven": "Given away",
|
||||
"movementSown": "Sown",
|
||||
"movementHarvested": "Harvested",
|
||||
"movementGerminationTest": "Germination test",
|
||||
"movementSplit": "Split into batches",
|
||||
"movementDiscarded": "Discarded",
|
||||
"created": "Added to your collection",
|
||||
"from": "From {origin}",
|
||||
"germinationResult": "Germination test — {percent}%",
|
||||
"linkedEarlier": "Comes from an earlier batch"
|
||||
},
|
||||
"sale": {
|
||||
"title": "Sales",
|
||||
"help": "Record seed you sold or bought — money, Ğ1, or any currency. A separate model from a gift or a Plantare. No commission is ever taken on seeds.",
|
||||
|
|
|
|||
|
|
@ -699,6 +699,25 @@
|
|||
"promiseGave": "Me devolverán semilla",
|
||||
"promiseReceived": "Devolveré semilla"
|
||||
},
|
||||
"history": {
|
||||
"title": "Historia de este lote",
|
||||
"tooltip": "Historia",
|
||||
"sowToday": "Sembrado hoy",
|
||||
"harvestToday": "Cosechado hoy",
|
||||
"sownRecorded": "Siembra anotada",
|
||||
"harvestRecorded": "Cosecha anotada",
|
||||
"movementReceived": "Recibido",
|
||||
"movementGiven": "Regalado",
|
||||
"movementSown": "Sembrado",
|
||||
"movementHarvested": "Cosechado",
|
||||
"movementGerminationTest": "Prueba de germinación",
|
||||
"movementSplit": "Repartido en lotes",
|
||||
"movementDiscarded": "Descartado",
|
||||
"created": "Entró en tu colección",
|
||||
"from": "De {origin}",
|
||||
"germinationResult": "Prueba de germinación — {percent}%",
|
||||
"linkedEarlier": "Viene de un lote anterior"
|
||||
},
|
||||
"sale": {
|
||||
"title": "Ventas",
|
||||
"help": "Registra semilla vendida o comprada — dinero, Ğ1 o cualquier moneda. Un modelo aparte del regalo y del Plantare. Nunca se cobra comisión por las semillas.",
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@
|
|||
/// To regenerate, run: `dart run slang`
|
||||
///
|
||||
/// Locales: 7
|
||||
/// Strings: 3494 (499 per locale)
|
||||
/// Strings: 3528 (504 per locale)
|
||||
///
|
||||
/// Built on 2026-07-17 at 11:10 UTC
|
||||
/// Built on 2026-07-18 at 04:22 UTC
|
||||
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint, unused_import
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ class Translations with BaseTranslations<AppLocale, Translations> {
|
|||
late final Translations$notifications$en notifications = Translations$notifications$en.internal(_root);
|
||||
late final Translations$plantare$en plantare = Translations$plantare$en.internal(_root);
|
||||
late final Translations$handover$en handover = Translations$handover$en.internal(_root);
|
||||
late final Translations$history$en history = Translations$history$en.internal(_root);
|
||||
late final Translations$sale$en sale = Translations$sale$en.internal(_root);
|
||||
late final Translations$legal$en legal = Translations$legal$en.internal(_root);
|
||||
late final Translations$marketGate$en marketGate = Translations$marketGate$en.internal(_root);
|
||||
|
|
@ -1980,6 +1981,66 @@ class Translations$handover$en {
|
|||
String get promiseReceived => 'I\'ll return seed';
|
||||
}
|
||||
|
||||
// Path: history
|
||||
class Translations$history$en {
|
||||
Translations$history$en.internal(this._root);
|
||||
|
||||
final Translations _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
|
||||
/// en: 'Story of this batch'
|
||||
String get title => 'Story of this batch';
|
||||
|
||||
/// en: 'Story'
|
||||
String get tooltip => 'Story';
|
||||
|
||||
/// en: 'Sown today'
|
||||
String get sowToday => 'Sown today';
|
||||
|
||||
/// en: 'Harvested today'
|
||||
String get harvestToday => 'Harvested today';
|
||||
|
||||
/// en: 'Sowing noted'
|
||||
String get sownRecorded => 'Sowing noted';
|
||||
|
||||
/// en: 'Harvest noted'
|
||||
String get harvestRecorded => 'Harvest noted';
|
||||
|
||||
/// en: 'Received'
|
||||
String get movementReceived => 'Received';
|
||||
|
||||
/// en: 'Given away'
|
||||
String get movementGiven => 'Given away';
|
||||
|
||||
/// en: 'Sown'
|
||||
String get movementSown => 'Sown';
|
||||
|
||||
/// en: 'Harvested'
|
||||
String get movementHarvested => 'Harvested';
|
||||
|
||||
/// en: 'Germination test'
|
||||
String get movementGerminationTest => 'Germination test';
|
||||
|
||||
/// en: 'Split into batches'
|
||||
String get movementSplit => 'Split into batches';
|
||||
|
||||
/// en: 'Discarded'
|
||||
String get movementDiscarded => 'Discarded';
|
||||
|
||||
/// en: 'Added to your collection'
|
||||
String get created => 'Added to your collection';
|
||||
|
||||
/// en: 'From {origin}'
|
||||
String from({required Object origin}) => 'From ${origin}';
|
||||
|
||||
/// en: 'Germination test — {percent}%'
|
||||
String germinationResult({required Object percent}) => 'Germination test — ${percent}%';
|
||||
|
||||
/// en: 'Comes from an earlier batch'
|
||||
String get linkedEarlier => 'Comes from an earlier batch';
|
||||
}
|
||||
|
||||
// Path: sale
|
||||
class Translations$sale$en {
|
||||
Translations$sale$en.internal(this._root);
|
||||
|
|
@ -3199,6 +3260,23 @@ extension on Translations {
|
|||
'handover.paymentChip' => 'Money changed hands',
|
||||
'handover.promiseGave' => 'They\'ll return me seed',
|
||||
'handover.promiseReceived' => 'I\'ll return seed',
|
||||
'history.title' => 'Story of this batch',
|
||||
'history.tooltip' => 'Story',
|
||||
'history.sowToday' => 'Sown today',
|
||||
'history.harvestToday' => 'Harvested today',
|
||||
'history.sownRecorded' => 'Sowing noted',
|
||||
'history.harvestRecorded' => 'Harvest noted',
|
||||
'history.movementReceived' => 'Received',
|
||||
'history.movementGiven' => 'Given away',
|
||||
'history.movementSown' => 'Sown',
|
||||
'history.movementHarvested' => 'Harvested',
|
||||
'history.movementGerminationTest' => 'Germination test',
|
||||
'history.movementSplit' => 'Split into batches',
|
||||
'history.movementDiscarded' => 'Discarded',
|
||||
'history.created' => 'Added to your collection',
|
||||
'history.from' => ({required Object origin}) => 'From ${origin}',
|
||||
'history.germinationResult' => ({required Object percent}) => 'Germination test — ${percent}%',
|
||||
'history.linkedEarlier' => 'Comes from an earlier batch',
|
||||
'sale.title' => 'Sales',
|
||||
'sale.help' => 'Record seed you sold or bought — money, Ğ1, or any currency. A separate model from a gift or a Plantare. No commission is ever taken on seeds.',
|
||||
'sale.add' => 'Record a sale',
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ class TranslationsEs extends Translations with BaseTranslations<AppLocale, Trans
|
|||
@override late final _Translations$notifications$es notifications = _Translations$notifications$es._(_root);
|
||||
@override late final _Translations$plantare$es plantare = _Translations$plantare$es._(_root);
|
||||
@override late final _Translations$handover$es handover = _Translations$handover$es._(_root);
|
||||
@override late final _Translations$history$es history = _Translations$history$es._(_root);
|
||||
@override late final _Translations$sale$es sale = _Translations$sale$es._(_root);
|
||||
@override late final _Translations$legal$es legal = _Translations$legal$es._(_root);
|
||||
@override late final _Translations$marketGate$es marketGate = _Translations$marketGate$es._(_root);
|
||||
|
|
@ -1021,6 +1022,32 @@ class _Translations$handover$es extends Translations$handover$en {
|
|||
@override String get promiseReceived => 'Devolveré semilla';
|
||||
}
|
||||
|
||||
// Path: history
|
||||
class _Translations$history$es extends Translations$history$en {
|
||||
_Translations$history$es._(TranslationsEs root) : this._root = root, super.internal(root);
|
||||
|
||||
final TranslationsEs _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
@override String get title => 'Historia de este lote';
|
||||
@override String get tooltip => 'Historia';
|
||||
@override String get sowToday => 'Sembrado hoy';
|
||||
@override String get harvestToday => 'Cosechado hoy';
|
||||
@override String get sownRecorded => 'Siembra anotada';
|
||||
@override String get harvestRecorded => 'Cosecha anotada';
|
||||
@override String get movementReceived => 'Recibido';
|
||||
@override String get movementGiven => 'Regalado';
|
||||
@override String get movementSown => 'Sembrado';
|
||||
@override String get movementHarvested => 'Cosechado';
|
||||
@override String get movementGerminationTest => 'Prueba de germinación';
|
||||
@override String get movementSplit => 'Repartido en lotes';
|
||||
@override String get movementDiscarded => 'Descartado';
|
||||
@override String get created => 'Entró en tu colección';
|
||||
@override String from({required Object origin}) => 'De ${origin}';
|
||||
@override String germinationResult({required Object percent}) => 'Prueba de germinación — ${percent}%';
|
||||
@override String get linkedEarlier => 'Viene de un lote anterior';
|
||||
}
|
||||
|
||||
// Path: sale
|
||||
class _Translations$sale$es extends Translations$sale$en {
|
||||
_Translations$sale$es._(TranslationsEs root) : this._root = root, super.internal(root);
|
||||
|
|
@ -2011,6 +2038,23 @@ extension on TranslationsEs {
|
|||
'handover.paymentChip' => 'Hubo dinero por medio',
|
||||
'handover.promiseGave' => 'Me devolverán semilla',
|
||||
'handover.promiseReceived' => 'Devolveré semilla',
|
||||
'history.title' => 'Historia de este lote',
|
||||
'history.tooltip' => 'Historia',
|
||||
'history.sowToday' => 'Sembrado hoy',
|
||||
'history.harvestToday' => 'Cosechado hoy',
|
||||
'history.sownRecorded' => 'Siembra anotada',
|
||||
'history.harvestRecorded' => 'Cosecha anotada',
|
||||
'history.movementReceived' => 'Recibido',
|
||||
'history.movementGiven' => 'Regalado',
|
||||
'history.movementSown' => 'Sembrado',
|
||||
'history.movementHarvested' => 'Cosechado',
|
||||
'history.movementGerminationTest' => 'Prueba de germinación',
|
||||
'history.movementSplit' => 'Repartido en lotes',
|
||||
'history.movementDiscarded' => 'Descartado',
|
||||
'history.created' => 'Entró en tu colección',
|
||||
'history.from' => ({required Object origin}) => 'De ${origin}',
|
||||
'history.germinationResult' => ({required Object percent}) => 'Prueba de germinación — ${percent}%',
|
||||
'history.linkedEarlier' => 'Viene de un lote anterior',
|
||||
'sale.title' => 'Ventas',
|
||||
'sale.help' => 'Registra semilla vendida o comprada — dinero, Ğ1 o cualquier moneda. Un modelo aparte del regalo y del Plantare. Nunca se cobra comisión por las semillas.',
|
||||
'sale.add' => 'Registrar venta',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue