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:
parent
432acded29
commit
efb369eb81
19 changed files with 1465 additions and 116 deletions
|
|
@ -63,6 +63,7 @@ class Translations with BaseTranslations<AppLocale, Translations> {
|
|||
late final Translations$provenance$en provenance = Translations$provenance$en.internal(_root);
|
||||
late final Translations$abundance$en abundance = Translations$abundance$en.internal(_root);
|
||||
late final Translations$share$en share = Translations$share$en.internal(_root);
|
||||
late final Translations$printLabels$en printLabels = Translations$printLabels$en.internal(_root);
|
||||
late final Translations$cropCalendar$en cropCalendar = Translations$cropCalendar$en.internal(_root);
|
||||
late final Translations$needsReproduction$en needsReproduction = Translations$needsReproduction$en.internal(_root);
|
||||
late final Translations$preservation$en preservation = Translations$preservation$en.internal(_root);
|
||||
|
|
@ -872,6 +873,60 @@ class Translations$share$en {
|
|||
String get cancelled => 'Cancelled';
|
||||
}
|
||||
|
||||
// Path: printLabels
|
||||
class Translations$printLabels$en {
|
||||
Translations$printLabels$en.internal(this._root);
|
||||
|
||||
final Translations _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
|
||||
/// en: 'Print labels'
|
||||
String get action => 'Print labels';
|
||||
|
||||
/// en: 'Print labels'
|
||||
String get title => 'Print labels';
|
||||
|
||||
/// en: 'Pick the seeds to print labels for'
|
||||
String get selectHint => 'Pick the seeds to print labels for';
|
||||
|
||||
/// en: 'Select all'
|
||||
String get selectAll => 'Select all';
|
||||
|
||||
/// en: '{n} selected'
|
||||
String selected({required Object n}) => '${n} selected';
|
||||
|
||||
/// en: 'Select seeds first'
|
||||
String get none => 'Select seeds first';
|
||||
|
||||
/// en: 'Label size'
|
||||
String get format => 'Label size';
|
||||
|
||||
/// en: 'Small stickers'
|
||||
String get formatStickers => 'Small stickers';
|
||||
|
||||
/// en: 'Many small labels per page — to peel onto packets'
|
||||
String get formatStickersHint => 'Many small labels per page — to peel onto packets';
|
||||
|
||||
/// en: 'Large cards'
|
||||
String get formatCards => 'Large cards';
|
||||
|
||||
/// en: 'Fewer, bigger labels — for jars and boxes'
|
||||
String get formatCardsHint => 'Fewer, bigger labels — for jars and boxes';
|
||||
|
||||
/// en: '{n} labels'
|
||||
String count({required Object n}) => '${n} labels';
|
||||
|
||||
/// en: 'Save labels'
|
||||
String get save => 'Save labels';
|
||||
|
||||
/// en: 'Labels saved'
|
||||
String get saved => 'Labels saved';
|
||||
|
||||
/// en: 'Cancelled'
|
||||
String get cancelled => 'Cancelled';
|
||||
}
|
||||
|
||||
// Path: cropCalendar
|
||||
class Translations$cropCalendar$en {
|
||||
Translations$cropCalendar$en.internal(this._root);
|
||||
|
|
@ -1876,6 +1931,21 @@ extension on Translations {
|
|||
'share.catalogTitle' => 'What I share',
|
||||
'share.catalogSaved' => 'Catalog saved',
|
||||
'share.cancelled' => 'Cancelled',
|
||||
'printLabels.action' => 'Print labels',
|
||||
'printLabels.title' => 'Print labels',
|
||||
'printLabels.selectHint' => 'Pick the seeds to print labels for',
|
||||
'printLabels.selectAll' => 'Select all',
|
||||
'printLabels.selected' => ({required Object n}) => '${n} selected',
|
||||
'printLabels.none' => 'Select seeds first',
|
||||
'printLabels.format' => 'Label size',
|
||||
'printLabels.formatStickers' => 'Small stickers',
|
||||
'printLabels.formatStickersHint' => 'Many small labels per page — to peel onto packets',
|
||||
'printLabels.formatCards' => 'Large cards',
|
||||
'printLabels.formatCardsHint' => 'Fewer, bigger labels — for jars and boxes',
|
||||
'printLabels.count' => ({required Object n}) => '${n} labels',
|
||||
'printLabels.save' => 'Save labels',
|
||||
'printLabels.saved' => 'Labels saved',
|
||||
'printLabels.cancelled' => 'Cancelled',
|
||||
'cropCalendar.add' => 'Crop calendar',
|
||||
'cropCalendar.title' => 'Crop calendar',
|
||||
'cropCalendar.sow' => 'Sow',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue