feat(app): hint isolation distance when sowing a cross-pollinating crop
Some checks failed
ci / test-commons-core (push) Successful in 58s
ci / analyze (push) Successful in 1m49s
site / deploy (push) Successful in 38s
ci / test-app-seeds (push) Has been cancelled

One passive line in the batch story after a 'sown today' tap — 'this
species crosses, grow it ~400 m from others' — sourced from the bundled
seed-saving guidance (family default + species override). Selfers get
nothing: the trap is recording isolation religiously for beans where it
never mattered. No input fields, no schema change.
This commit is contained in:
vjrj 2026-07-18 12:31:42 +02:00
parent f1aa8f8e66
commit 1a826477f2
8 changed files with 116 additions and 7 deletions

View file

@ -3,6 +3,7 @@ import 'package:intl/intl.dart';
import '../data/variety_repository.dart';
import '../db/enums.dart';
import '../domain/seed_saving.dart';
import '../i18n/strings.g.dart';
import 'quantity_kind_l10n.dart';
@ -14,20 +15,31 @@ Future<void> showLotHistorySheet(
BuildContext context, {
required VarietyRepository repository,
required VarietyLot lot,
SeedSavingGuide? guide,
}) {
return showModalBottomSheet<void>(
context: context,
isScrollControlled: true,
builder: (_) => _LotHistorySheet(repository: repository, lot: lot),
builder: (_) =>
_LotHistorySheet(repository: repository, lot: lot, guide: guide),
);
}
class _LotHistorySheet extends StatefulWidget {
const _LotHistorySheet({required this.repository, required this.lot});
const _LotHistorySheet({
required this.repository,
required this.lot,
this.guide,
});
final VarietyRepository repository;
final VarietyLot lot;
/// Bundled species guidance, or null. Only read to drop the one-line
/// isolation hint when a cross-pollinating crop is sown selfers get
/// nothing (the fields people record religiously where they don't matter).
final SeedSavingGuide? guide;
@override
State<_LotHistorySheet> createState() => _LotHistorySheetState();
}
@ -43,6 +55,10 @@ class _LotHistorySheetState extends State<_LotHistorySheet> {
bool _askOutcome = false;
final _outcomeNote = TextEditingController();
// One passive line after sowing a crosser ("this species crosses — isolate
// ~400 m"). Never shown for selfers, never an input.
bool _showSowingHint = false;
@override
void initState() {
super.initState();
@ -74,9 +90,14 @@ class _LotHistorySheetState extends State<_LotHistorySheet> {
),
),
);
final guide = widget.guide;
setState(() {
_saving = false;
_askOutcome = type == MovementType.harvested;
_showSowingHint =
type == MovementType.sown &&
guide?.pollination == Pollination.cross &&
guide?.isolationMinM != null;
_history = widget.repository.lotHistory(widget.lot.id);
});
}
@ -146,6 +167,25 @@ class _LotHistorySheetState extends State<_LotHistorySheet> {
),
],
),
if (_showSowingHint)
Padding(
key: const Key('history.isolationHint'),
padding: const EdgeInsetsDirectional.only(top: 8, start: 4),
child: Row(
children: [
const Icon(Icons.lightbulb_outline, size: 16),
const SizedBox(width: 6),
Expanded(
child: Text(
context.t.history.isolationHint(
meters: widget.guide!.isolationMinM!,
),
style: Theme.of(context).textTheme.bodySmall,
),
),
],
),
),
if (_askOutcome) ...[
const SizedBox(height: 8),
_OutcomeQuestion(