feat(offers): asking price on lots, published with sale offers (schema v11)

The data model always meant sale offers to carry an informational price
(data-model §2.8, sharing-model §4.4); with offer state collapsed onto
the Lot, the price lives there. Null amount on a sell lot = 'to be
agreed' — the NIP-99 event simply omits the price tag.

- schema v11: Lots.price_amount/price_currency, guarded migration,
  schema dump + generated schema_v11 for the round-trip test
- ShareableLot/VarietyLot carry the price (sell-only in shareableLots);
  addLot/updateLot persist it and clear it when the lot leaves sale
- OffersCubit.publishLots forwards it (outbox flush picks it up free)
- lot sheet: price + currency inputs revealed only on 'For sale', with
  the €/Ğ1/hours quick-picks extracted to a shared CurrencyQuickPicks
  widget (reused by the sale sheet)
- backup JSON round-trips the new columns
- i18n share.price/priceHint in en/es/pt/ast
This commit is contained in:
vjrj 2026-07-11 07:24:23 +02:00
parent 5ecdd1222a
commit 1103b6ce15
25 changed files with 4690 additions and 31 deletions

View file

@ -303,6 +303,8 @@
"add": "¿Compártesla?",
"title": "¿Compártesla?",
"nudge": "Tienes a esgaya: podríes compartir un poco.",
"price": "Preciu",
"priceHint": "Déxalu baleru p'alcordalu depués",
"private": "Namás pa min",
"gift": "Pa regalar",
"exchange": "Pa trocar",

View file

@ -304,6 +304,8 @@
"add": "Do you share it?",
"title": "Do you share it?",
"nudge": "You have plenty — you could share some.",
"price": "Price",
"priceHint": "Leave it empty to agree it later",
"private": "Just for me",
"gift": "To give away",
"exchange": "To swap",

View file

@ -303,6 +303,8 @@
"add": "¿La compartes?",
"title": "¿La compartes?",
"nudge": "Tienes de sobra: podrías compartir un poco.",
"price": "Precio",
"priceHint": "Déjalo vacío para acordarlo luego",
"private": "Solo para mí",
"gift": "Para regalar",
"exchange": "Para intercambiar",

View file

@ -300,6 +300,8 @@
"add": "Partilhas esta?",
"title": "Partilhas esta?",
"nudge": "Tens de sobra: podias partilhar um pouco.",
"price": "Preço",
"priceHint": "Deixa vazio para combinar depois",
"private": "Só para mim",
"gift": "Para dar",
"exchange": "Para trocar",

View file

@ -4,9 +4,9 @@
/// To regenerate, run: `dart run slang`
///
/// Locales: 4
/// Strings: 1968 (492 per locale)
/// Strings: 1976 (494 per locale)
///
/// Built on 2026-07-11 at 05:50 UTC
/// Built on 2026-07-11 at 06:00 UTC
// coverage:ignore-file
// ignore_for_file: type=lint, unused_import

View file

@ -547,6 +547,8 @@ class _Translations$share$ast extends Translations$share$en {
@override String get add => '¿Compártesla?';
@override String get title => '¿Compártesla?';
@override String get nudge => 'Tienes a esgaya: podríes compartir un poco.';
@override String get price => 'Preciu';
@override String get priceHint => 'Déxalu baleru p\'alcordalu depués';
@override String get private => 'Namás pa min';
@override String get gift => 'Pa regalar';
@override String get exchange => 'Pa trocar';
@ -1501,6 +1503,8 @@ extension on TranslationsAst {
'share.add' => '¿Compártesla?',
'share.title' => '¿Compártesla?',
'share.nudge' => 'Tienes a esgaya: podríes compartir un poco.',
'share.price' => 'Preciu',
'share.priceHint' => 'Déxalu baleru p\'alcordalu depués',
'share.private' => 'Namás pa min',
'share.gift' => 'Pa regalar',
'share.exchange' => 'Pa trocar',

View file

@ -988,6 +988,12 @@ class Translations$share$en {
/// en: 'You have plenty — you could share some.'
String get nudge => 'You have plenty — you could share some.';
/// en: 'Price'
String get price => 'Price';
/// en: 'Leave it empty to agree it later'
String get priceHint => 'Leave it empty to agree it later';
/// en: 'Just for me'
String get private => 'Just for me';
@ -2473,6 +2479,8 @@ extension on Translations {
'share.add' => 'Do you share it?',
'share.title' => 'Do you share it?',
'share.nudge' => 'You have plenty — you could share some.',
'share.price' => 'Price',
'share.priceHint' => 'Leave it empty to agree it later',
'share.private' => 'Just for me',
'share.gift' => 'To give away',
'share.exchange' => 'To swap',

View file

@ -547,6 +547,8 @@ class _Translations$share$es extends Translations$share$en {
@override String get add => '¿La compartes?';
@override String get title => '¿La compartes?';
@override String get nudge => 'Tienes de sobra: podrías compartir un poco.';
@override String get price => 'Precio';
@override String get priceHint => 'Déjalo vacío para acordarlo luego';
@override String get private => 'Solo para mí';
@override String get gift => 'Para regalar';
@override String get exchange => 'Para intercambiar';
@ -1503,6 +1505,8 @@ extension on TranslationsEs {
'share.add' => '¿La compartes?',
'share.title' => '¿La compartes?',
'share.nudge' => 'Tienes de sobra: podrías compartir un poco.',
'share.price' => 'Precio',
'share.priceHint' => 'Déjalo vacío para acordarlo luego',
'share.private' => 'Solo para mí',
'share.gift' => 'Para regalar',
'share.exchange' => 'Para intercambiar',

View file

@ -544,6 +544,8 @@ class _Translations$share$pt extends Translations$share$en {
@override String get add => 'Partilhas esta?';
@override String get title => 'Partilhas esta?';
@override String get nudge => 'Tens de sobra: podias partilhar um pouco.';
@override String get price => 'Preço';
@override String get priceHint => 'Deixa vazio para combinar depois';
@override String get private => 'Só para mim';
@override String get gift => 'Para dar';
@override String get exchange => 'Para trocar';
@ -1497,6 +1499,8 @@ extension on TranslationsPt {
'share.add' => 'Partilhas esta?',
'share.title' => 'Partilhas esta?',
'share.nudge' => 'Tens de sobra: podias partilhar um pouco.',
'share.price' => 'Preço',
'share.priceHint' => 'Deixa vazio para combinar depois',
'share.private' => 'Só para mim',
'share.gift' => 'Para dar',
'share.exchange' => 'Para trocar',