import 'package:flutter/material.dart'; import '../data/variety_repository.dart'; import '../db/enums.dart'; import '../i18n/strings.g.dart'; import 'theme.dart'; /// Opens the "add a Plantare" sheet — a reproduction commitment. Optionally /// pre-attached to [varietyId] (when opened from a variety's detail). Future showPlantareSheet( BuildContext context, { required VarietyRepository repository, String? varietyId, }) { return showModalBottomSheet( context: context, isScrollControlled: true, builder: (_) => _PlantareSheet(repository: repository, varietyId: varietyId), ); } class _PlantareSheet extends StatefulWidget { const _PlantareSheet({required this.repository, this.varietyId}); final VarietyRepository repository; final String? varietyId; @override State<_PlantareSheet> createState() => _PlantareSheetState(); } class _PlantareSheetState extends State<_PlantareSheet> { PlantareDirection _direction = PlantareDirection.iReturn; final _counterparty = TextEditingController(); final _owed = TextEditingController(); final _note = TextEditingController(); bool _saving = false; @override void dispose() { _counterparty.dispose(); _owed.dispose(); _note.dispose(); super.dispose(); } String? _nullIfBlank(String s) => s.trim().isEmpty ? null : s.trim(); Future _save() async { setState(() => _saving = true); await widget.repository.createPlantare( direction: _direction, varietyId: widget.varietyId, counterparty: _nullIfBlank(_counterparty.text), owedDescription: _nullIfBlank(_owed.text), note: _nullIfBlank(_note.text), ); if (mounted) Navigator.of(context).pop(); } @override Widget build(BuildContext context) { final t = context.t; return Padding( padding: EdgeInsets.only( left: 16, right: 16, top: 16, bottom: MediaQuery.of(context).viewInsets.bottom + 16, ), child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text(t.plantare.add, style: Theme.of(context).textTheme.titleLarge), const SizedBox(height: 4), Text(t.plantare.help, style: const TextStyle(color: seedMuted, fontSize: 13)), const SizedBox(height: 16), Text(t.plantare.direction, style: Theme.of(context).textTheme.labelLarge), const SizedBox(height: 6), // Two big, human choices — no jargon. for (final d in PlantareDirection.values) ListTile( key: Key('plantare.direction.${d.name}'), contentPadding: EdgeInsets.zero, leading: Icon( _direction == d ? Icons.radio_button_checked : Icons.radio_button_unchecked, color: _direction == d ? seedGreen : seedMuted, ), title: Text(d == PlantareDirection.iReturn ? t.plantare.iReturn : t.plantare.owedToMe), onTap: () => setState(() => _direction = d), ), const SizedBox(height: 8), TextField( key: const Key('plantare.counterparty'), controller: _counterparty, textCapitalization: TextCapitalization.words, decoration: InputDecoration( labelText: t.plantare.counterparty, helperText: t.plantare.counterpartyHint, border: const OutlineInputBorder(), ), ), const SizedBox(height: 12), TextField( key: const Key('plantare.owed'), controller: _owed, decoration: InputDecoration( labelText: t.plantare.owed, helperText: t.plantare.owedHint, helperMaxLines: 2, border: const OutlineInputBorder(), ), ), const SizedBox(height: 12), TextField( key: const Key('plantare.note'), controller: _note, minLines: 1, maxLines: 3, decoration: InputDecoration( labelText: t.plantare.note, border: const OutlineInputBorder(), ), ), const SizedBox(height: 20), FilledButton( key: const Key('plantare.save'), onPressed: _saving ? null : _save, child: Text(t.plantare.save), ), ], ), ), ); } }