feat(labels): print seed labels with QR from an inventory selection

Add multi-select to the inventory and a "Print labels" flow that renders a
PDF sheet of labels (small stickers or large cards), each carrying the seed's
common name, variety, scientific name, year/origin and a tanemaki://seed QR
that holds the seed's data offline (future scan-to-import).

- SeedLabelCodec: compact, versioned tanemaki://seed URI (encode/decode)
- LabelSheetService: pure-Dart PDF grid (pdf + barcode + DejaVu), RTL-aware
- VarietyRepository.labelRows: one row per lot, locale-picked common name
- InventoryCubit selection mode; contextual app bar + label print sheet
- i18n en/es/pt (printLabels.*)

Tests: codec, PDF service (both formats + RTL), labelRows, selection cubit,
inventory widget selection.
This commit is contained in:
vjrj 2026-07-10 19:14:04 +02:00
parent 432acded29
commit efb369eb81
19 changed files with 1465 additions and 116 deletions

View file

@ -262,6 +262,23 @@
"catalogSaved": "Catalog saved",
"cancelled": "Cancelled"
},
"printLabels": {
"action": "Print labels",
"title": "Print labels",
"selectHint": "Pick the seeds to print labels for",
"selectAll": "Select all",
"selected": "{n} selected",
"none": "Select seeds first",
"format": "Label size",
"formatStickers": "Small stickers",
"formatStickersHint": "Many small labels per page — to peel onto packets",
"formatCards": "Large cards",
"formatCardsHint": "Fewer, bigger labels — for jars and boxes",
"count": "{n} labels",
"save": "Save labels",
"saved": "Labels saved",
"cancelled": "Cancelled"
},
"cropCalendar": {
"add": "Crop calendar",
"title": "Crop calendar",