feat(inventory): informal quantity scale (number + unit) + seed/plant lots
Rework quantities the way seeds are actually described — a number of an informal
unit — and let a lot hold seeds or plants (plantel).
Quantity model (commons_core):
- Quantity is now { kind, count?, label } — "3 cobs", "2 packets", "a few".
Count is optional; uncountable vibes (a few, some, pinch) carry no number.
- QuantityKind reorganised into an ascending scale: vibes → containers
(teaspoon/spoon/cup/jar/sack) → seed & fruit forms → plant units, each tagged
countable/not. Stored by name; count reuses the existing numeric column.
Lot type (schema v2):
- Lots gain a `type` (seed | plant); germination stays meaningful for seeds.
schemaVersion 2 with a from1To2 migration (adds the column), drift_schema_v2
exported, migration test covers v1→v2.
UI:
- New QuantityPicker: a horizontal scale of large seed-glyph icons + a number
stepper (shown only for countable units), plus a seed/plant SegmentedButton.
Used in quick-add and add-lot. Lot lines render "3 cobs" / "a few".
- i18n: unit singular/plural (ES/EN, Weblate-friendly), lot-type labels.
Build: slang moved to its CLI (disabled in build_runner to avoid a multi-file
collision); CI runs `dart run slang` before build_runner. 38 tests green,
Linux migrates the existing v1 DB and runs.
This commit is contained in:
parent
48e9d15772
commit
3942975dba
26 changed files with 4220 additions and 315 deletions
|
|
@ -5,13 +5,17 @@ import 'package:equatable/equatable.dart';
|
|||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../data/variety_repository.dart';
|
||||
import '../db/enums.dart';
|
||||
|
||||
const Object _unset = Object();
|
||||
|
||||
/// Form state for the quick-add sheet. Only [label] is required; everything
|
||||
/// else is progressive disclosure behind [expanded].
|
||||
class QuickAddState extends Equatable {
|
||||
const QuickAddState({
|
||||
this.label = '',
|
||||
this.quantityKind,
|
||||
this.quantity,
|
||||
this.lotType = LotType.seed,
|
||||
this.photoBytes,
|
||||
this.expanded = false,
|
||||
this.submitting = false,
|
||||
|
|
@ -20,7 +24,8 @@ class QuickAddState extends Equatable {
|
|||
});
|
||||
|
||||
final String label;
|
||||
final QuantityKind? quantityKind;
|
||||
final Quantity? quantity;
|
||||
final LotType lotType;
|
||||
final Uint8List? photoBytes;
|
||||
final bool expanded;
|
||||
final bool submitting;
|
||||
|
|
@ -31,7 +36,8 @@ class QuickAddState extends Equatable {
|
|||
|
||||
QuickAddState copyWith({
|
||||
String? label,
|
||||
QuantityKind? quantityKind,
|
||||
Object? quantity = _unset,
|
||||
LotType? lotType,
|
||||
Uint8List? photoBytes,
|
||||
bool? expanded,
|
||||
bool? submitting,
|
||||
|
|
@ -40,7 +46,10 @@ class QuickAddState extends Equatable {
|
|||
}) {
|
||||
return QuickAddState(
|
||||
label: label ?? this.label,
|
||||
quantityKind: quantityKind ?? this.quantityKind,
|
||||
quantity: identical(quantity, _unset)
|
||||
? this.quantity
|
||||
: quantity as Quantity?,
|
||||
lotType: lotType ?? this.lotType,
|
||||
photoBytes: photoBytes ?? this.photoBytes,
|
||||
expanded: expanded ?? this.expanded,
|
||||
submitting: submitting ?? this.submitting,
|
||||
|
|
@ -52,7 +61,8 @@ class QuickAddState extends Equatable {
|
|||
@override
|
||||
List<Object?> get props => [
|
||||
label,
|
||||
quantityKind,
|
||||
quantity,
|
||||
lotType,
|
||||
photoBytes,
|
||||
expanded,
|
||||
submitting,
|
||||
|
|
@ -70,8 +80,10 @@ class QuickAddCubit extends Cubit<QuickAddState> {
|
|||
void labelChanged(String value) =>
|
||||
emit(state.copyWith(label: value, showLabelError: false));
|
||||
|
||||
void selectQuantity(QuantityKind kind) =>
|
||||
emit(state.copyWith(quantityKind: kind));
|
||||
void setQuantity(Quantity? quantity) =>
|
||||
emit(state.copyWith(quantity: quantity));
|
||||
|
||||
void setLotType(LotType type) => emit(state.copyWith(lotType: type));
|
||||
|
||||
void photoPicked(Uint8List bytes) => emit(state.copyWith(photoBytes: bytes));
|
||||
|
||||
|
|
@ -87,9 +99,8 @@ class QuickAddCubit extends Cubit<QuickAddState> {
|
|||
emit(state.copyWith(submitting: true));
|
||||
await _repo.addQuickVariety(
|
||||
label: state.label.trim(),
|
||||
quantity: state.quantityKind == null
|
||||
? null
|
||||
: Quantity(kind: state.quantityKind!),
|
||||
lotType: state.lotType,
|
||||
quantity: state.quantity,
|
||||
photoBytes: state.photoBytes,
|
||||
);
|
||||
emit(state.copyWith(submitting: false, submitted: true));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue