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": "Catálogo guardado",
"cancelled": "Cancelado"
},
"printLabels": {
"action": "Imprimir etiquetas",
"title": "Imprimir etiquetas",
"selectHint": "Elige las semillas para imprimir sus etiquetas",
"selectAll": "Seleccionar todo",
"selected": "{n} seleccionadas",
"none": "Selecciona semillas primero",
"format": "Tamaño de etiqueta",
"formatStickers": "Pegatinas pequeñas",
"formatStickersHint": "Muchas etiquetas pequeñas por hoja — para pegar en sobres",
"formatCards": "Tarjetas grandes",
"formatCardsHint": "Menos etiquetas, más grandes — para botes y cajas",
"count": "{n} etiquetas",
"save": "Guardar etiquetas",
"saved": "Etiquetas guardadas",
"cancelled": "Cancelado"
},
"cropCalendar": {
"add": "Calendario de cultivo",
"title": "Calendario de cultivo",