feat(block2): publish my seeds to the network (completes publish->discover)
The other half of the market: share your marked lots as offers. - VarietyRepository.shareableLots(): non-private lots WITH their id (stable, updatable offer id) + the variety label. Private lots never leave the device. - OffersCubit.publishLots(): maps each via OfferMapper and publishes, tagged with the coarse area + signed by the derived key; counts acceptances; no-op offline or with no area. - Market screen: a 'share my seeds' action (online only) — publishes, then re-discovers to show them; 'mark some seeds first' when nothing's shared. - i18n en/es/pt. 14 tests green (repo query, cubit publish, market UI); analyzer clean for new code.
This commit is contained in:
parent
cb5f55e146
commit
f8f73c4153
12 changed files with 284 additions and 5 deletions
|
|
@ -117,6 +117,33 @@ class SharedCatalogEntry extends Equatable {
|
|||
];
|
||||
}
|
||||
|
||||
/// A lot the user has marked for sharing, carrying the lot [lotId] (so the
|
||||
/// published offer has a stable, updatable id) plus the summary a network offer
|
||||
/// needs. Distinct from [SharedCatalogEntry], which is for the printable local
|
||||
/// catalog and has no id.
|
||||
class ShareableLot extends Equatable {
|
||||
const ShareableLot({
|
||||
required this.lotId,
|
||||
required this.summary,
|
||||
required this.offerStatus,
|
||||
this.category,
|
||||
this.harvestYear,
|
||||
});
|
||||
|
||||
final String lotId;
|
||||
|
||||
/// What to publish: the variety label (never the full inventory).
|
||||
final String summary;
|
||||
|
||||
/// Never [OfferStatus.private] — private lots don't leave the device.
|
||||
final OfferStatus offerStatus;
|
||||
final String? category;
|
||||
final int? harvestYear;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [lotId, summary, offerStatus, category, harvestYear];
|
||||
}
|
||||
|
||||
/// One germination test on a lot; [rate] is derived (0..1), null when it can't
|
||||
/// be computed.
|
||||
class GerminationEntry extends Equatable {
|
||||
|
|
@ -1210,6 +1237,42 @@ class VarietyRepository {
|
|||
return entries;
|
||||
}
|
||||
|
||||
/// Lots the user marked to share (not private), each with its id and the
|
||||
/// variety label — the input for publishing offers to the network (Block 2).
|
||||
Future<List<ShareableLot>> shareableLots() async {
|
||||
final lots =
|
||||
await (_db.select(_db.lots)..where(
|
||||
(l) =>
|
||||
l.isDeleted.equals(false) &
|
||||
l.offerStatus.equalsValue(OfferStatus.private).not(),
|
||||
))
|
||||
.get();
|
||||
if (lots.isEmpty) return const [];
|
||||
|
||||
final varietyIds = lots.map((l) => l.varietyId).toSet();
|
||||
final varieties =
|
||||
await (_db.select(_db.varieties)..where(
|
||||
(v) =>
|
||||
v.id.isIn(varietyIds) &
|
||||
v.isDeleted.equals(false) &
|
||||
v.isDraft.equals(false),
|
||||
))
|
||||
.get();
|
||||
final byId = {for (final v in varieties) v.id: v};
|
||||
|
||||
return [
|
||||
for (final l in lots)
|
||||
if (byId[l.varietyId] case final v?)
|
||||
ShareableLot(
|
||||
lotId: l.id,
|
||||
summary: v.label,
|
||||
offerStatus: l.offerStatus,
|
||||
category: v.category,
|
||||
harvestYear: l.harvestYear,
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
/// Soft-deletes a lot (tombstone); it leaves the variety's lot list.
|
||||
Future<void> softDeleteLot(String lotId) async {
|
||||
final (_, updated) = await _stamp();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue