import 'package:commons_core/commons_core.dart'; import 'package:flutter/material.dart'; import 'package:material_symbols_icons/symbols.dart'; import '../db/enums.dart'; import '../i18n/strings.g.dart'; import 'quantity_kind_l10n.dart'; import 'seed_glyph.dart'; import 'theme.dart'; /// Informal seed amounts, ascending: vibes → containers → seed/fruit forms. /// ([QuantityKind.handful] is intentionally omitted — it overlaps with spoon.) const seedScaleKinds = [ QuantityKind.aFew, QuantityKind.teaspoon, QuantityKind.spoon, QuantityKind.packet, QuantityKind.cup, QuantityKind.jar, QuantityKind.sack, QuantityKind.cob, QuantityKind.pod, QuantityKind.ear, QuantityKind.head, QuantityKind.fruit, QuantityKind.bulb, QuantityKind.tuber, QuantityKind.bunch, ]; /// Units for a plant/seedling lot. const plantScaleKinds = [ QuantityKind.plant, QuantityKind.pot, QuantityKind.tray, ]; List kindsForType(LotType type) => type == LotType.seed ? seedScaleKinds : plantScaleKinds; /// Seed vs plant/seedling segmented selector. class LotTypeSelector extends StatelessWidget { const LotTypeSelector({ required this.value, required this.onChanged, super.key, }); final LotType value; final ValueChanged onChanged; @override Widget build(BuildContext context) { final t = context.t; return SegmentedButton( segments: [ ButtonSegment( value: LotType.seed, label: Text(t.lotType.seed), icon: const SeedGlyph(SeedGlyphs.jars, size: 18), ), ButtonSegment( value: LotType.plant, label: Text(t.lotType.plant), icon: const Icon(Symbols.potted_plant, size: 18), ), ], selected: {value}, showSelectedIcon: false, onSelectionChanged: (s) => onChanged(s.first), ); } } /// A horizontal scale of large unit icons + an optional number stepper. Emits a /// [Quantity] (or null while nothing is picked) via [onChanged]. class QuantityPicker extends StatefulWidget { const QuantityPicker({ required this.type, required this.onChanged, this.value, super.key, }); final LotType type; final Quantity? value; final ValueChanged onChanged; @override State createState() => _QuantityPickerState(); } class _QuantityPickerState extends State { QuantityKind? _kind; final _countController = TextEditingController(); @override void initState() { super.initState(); _kind = widget.value?.kind; final c = widget.value?.count; if (c != null) _countController.text = _fmt(c); } @override void didUpdateWidget(QuantityPicker old) { super.didUpdateWidget(old); // Switching seed/plant, or the owner clearing the value, drops a stale // selection. We only update local fields here (no onChanged during build); // the owner clears its own value alongside the type change. if (widget.value == null && _kind != null) { _kind = null; _countController.clear(); } else if (widget.type != old.type && _kind != null && !kindsForType(widget.type).contains(_kind)) { _kind = null; _countController.clear(); } } @override void dispose() { _countController.dispose(); super.dispose(); } void _emit() { final kind = _kind; if (kind == null) { widget.onChanged(null); return; } final n = num.tryParse(_countController.text.trim().replaceAll(',', '.')); widget.onChanged(Quantity(kind: kind, count: kind.countable ? n : null)); } void _select(QuantityKind kind) { setState(() => _kind = kind); _emit(); } void _bump(int delta) { final current = int.tryParse(_countController.text.trim()) ?? 0; final next = (current + delta).clamp(0, 9999); _countController.text = next == 0 ? '' : '$next'; _emit(); } @override Widget build(BuildContext context) { final t = context.t; final kinds = kindsForType(widget.type); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( height: 76, child: ListView.separated( scrollDirection: Axis.horizontal, itemCount: kinds.length, separatorBuilder: (_, _) => const SizedBox(width: 4), itemBuilder: (context, i) { final kind = kinds[i]; return _ScaleItem( kind: kind, label: unitLabel(t, kind), selected: _kind == kind, onTap: () => _select(kind), ); }, ), ), if (_kind?.countable ?? false) ...[ const SizedBox(height: 8), Row( children: [ IconButton.filledTonal( onPressed: () => _bump(-1), icon: const Icon(Icons.remove), ), SizedBox( width: 64, child: TextField( key: const Key('quantity.count'), controller: _countController, textAlign: TextAlign.center, keyboardType: TextInputType.number, decoration: const InputDecoration(isDense: true), onChanged: (_) => _emit(), ), ), IconButton.filledTonal( onPressed: () => _bump(1), icon: const Icon(Icons.add), ), const SizedBox(width: 12), Expanded( child: Text( unitLabel(t, _kind!), style: Theme.of(context).textTheme.bodyLarge, ), ), ], ), ], ], ); } } String _fmt(num n) => n == n.roundToDouble() ? n.toInt().toString() : n.toString(); class _ScaleItem extends StatelessWidget { const _ScaleItem({ required this.kind, required this.label, required this.selected, required this.onTap, }); final QuantityKind kind; final String label; final bool selected; final VoidCallback onTap; @override Widget build(BuildContext context) { final color = selected ? seedGreenDark : Colors.black54; return InkWell( onTap: onTap, borderRadius: BorderRadius.circular(10), child: Container( width: 68, padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 4), decoration: BoxDecoration( color: selected ? seedGreen.withValues(alpha: 0.15) : null, borderRadius: BorderRadius.circular(10), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ QuantityKindIcon(kind, size: 30, color: color), const SizedBox(height: 4), Text( label, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(fontSize: 11, color: color), ), ], ), ), ); } }