The quick-add sheet no longer closes on every save: a new 'Save & add another' action saves the seed, clears the form (keeping the chosen lot type), refocuses the name field and shows an 'N added' running count, so a whole shelf can be entered without reopening the sheet each time. Plain Save still closes it. Adds a dedicated label field with its own controller, submitAndAddAnother() on the cubit, and cubit + widget tests.
135 lines
3.9 KiB
Dart
135 lines
3.9 KiB
Dart
import 'dart:typed_data';
|
|
|
|
import 'package:commons_core/commons_core.dart';
|
|
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.quantity,
|
|
this.lotType = LotType.seed,
|
|
this.photoBytes,
|
|
this.expanded = false,
|
|
this.submitting = false,
|
|
this.submitted = false,
|
|
this.showLabelError = false,
|
|
this.addedCount = 0,
|
|
});
|
|
|
|
final String label;
|
|
final Quantity? quantity;
|
|
final LotType lotType;
|
|
final Uint8List? photoBytes;
|
|
final bool expanded;
|
|
final bool submitting;
|
|
final bool submitted;
|
|
final bool showLabelError;
|
|
|
|
/// How many seeds this sheet has saved via "save & add another" (it stays
|
|
/// open); drives the "N added" feedback and resets of the label field.
|
|
final int addedCount;
|
|
|
|
bool get hasValidLabel => label.trim().isNotEmpty;
|
|
|
|
QuickAddState copyWith({
|
|
String? label,
|
|
Object? quantity = _unset,
|
|
LotType? lotType,
|
|
Uint8List? photoBytes,
|
|
bool? expanded,
|
|
bool? submitting,
|
|
bool? submitted,
|
|
bool? showLabelError,
|
|
int? addedCount,
|
|
}) {
|
|
return QuickAddState(
|
|
label: label ?? this.label,
|
|
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,
|
|
submitted: submitted ?? this.submitted,
|
|
showLabelError: showLabelError ?? this.showLabelError,
|
|
addedCount: addedCount ?? this.addedCount,
|
|
);
|
|
}
|
|
|
|
@override
|
|
List<Object?> get props => [
|
|
label,
|
|
quantity,
|
|
lotType,
|
|
photoBytes,
|
|
expanded,
|
|
submitting,
|
|
submitted,
|
|
showLabelError,
|
|
addedCount,
|
|
];
|
|
}
|
|
|
|
/// Drives the 20-second quick-add flow and persists via [VarietyRepository].
|
|
class QuickAddCubit extends Cubit<QuickAddState> {
|
|
QuickAddCubit(this._repo) : super(const QuickAddState());
|
|
|
|
final VarietyRepository _repo;
|
|
|
|
void labelChanged(String value) =>
|
|
emit(state.copyWith(label: value, showLabelError: false));
|
|
|
|
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));
|
|
|
|
void toggleExpanded() => emit(state.copyWith(expanded: !state.expanded));
|
|
|
|
/// Validates and saves. No-op (sets [showLabelError]) if the label is empty.
|
|
Future<void> submit() async {
|
|
if (!state.hasValidLabel) {
|
|
emit(state.copyWith(showLabelError: true));
|
|
return;
|
|
}
|
|
if (state.submitting) return;
|
|
emit(state.copyWith(submitting: true));
|
|
await _repo.addQuickVariety(
|
|
label: state.label.trim(),
|
|
lotType: state.lotType,
|
|
quantity: state.quantity,
|
|
photoBytes: state.photoBytes,
|
|
);
|
|
emit(state.copyWith(submitting: false, submitted: true));
|
|
}
|
|
|
|
/// Saves and keeps the sheet open for the next seed: resets the form to a
|
|
/// clean state (keeping the chosen [lotType]) and bumps [addedCount]. Lets a
|
|
/// user rip through a whole shelf without reopening the sheet each time.
|
|
Future<void> submitAndAddAnother() async {
|
|
if (!state.hasValidLabel) {
|
|
emit(state.copyWith(showLabelError: true));
|
|
return;
|
|
}
|
|
if (state.submitting) return;
|
|
emit(state.copyWith(submitting: true));
|
|
await _repo.addQuickVariety(
|
|
label: state.label.trim(),
|
|
lotType: state.lotType,
|
|
quantity: state.quantity,
|
|
photoBytes: state.photoBytes,
|
|
);
|
|
emit(QuickAddState(lotType: state.lotType, addedCount: state.addedCount + 1));
|
|
}
|
|
}
|