Files
supplements/lib/widgets/dialogs/bulk_take_dialog.dart

215 lines
9.0 KiB
Dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
import '../../models/supplement.dart';
import '../../providers/supplement_provider.dart';
/// Shows a bulk "Take supplements" dialog for a list of supplements.
/// - No time selection (records as now)
/// - Allows editing units per supplement
/// - Optional shared notes (applies to all)
Future<void> showBulkTakeDialog(
BuildContext context,
List<Supplement> supplements,
) async {
if (supplements.isEmpty) {
return;
}
// Controllers for each supplement's units
final Map<int, TextEditingController> unitControllers = {
for (final s in supplements.where((s) => s.id != null))
s.id!: TextEditingController(text: s.numberOfUnits.toString()),
};
final notesController = TextEditingController();
await showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Take ${supplements.length} supplements'),
content: SizedBox(
width: double.maxFinite,
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 500),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// List of supplements with editable units
// Use a scroll view with explicit max height to avoid intrinsic dimension issues.
ConstrainedBox(
constraints: const BoxConstraints(maxHeight: 320),
child: SingleChildScrollView(
child: Column(
children: [
for (int index = 0; index < supplements.length; index++) ...[
() {
final s = supplements[index];
final controller = unitControllers[s.id] ??
TextEditingController(text: s.numberOfUnits.toString());
return Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceContainerHighest.withValues(alpha: 0.5),
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: Theme.of(context).colorScheme.outline.withValues(alpha: 0.3),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Name and per-unit info
Row(
children: [
Expanded(
child: Text(
s.name,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
),
const SizedBox(width: 8),
Text(
s.unitType,
style: TextStyle(
fontSize: 12,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
],
),
const SizedBox(height: 8),
// Units editor
Row(
children: [
Expanded(
child: TextField(
controller: controller,
keyboardType: const TextInputType.numberWithOptions(decimal: true),
decoration: InputDecoration(
labelText: 'Units',
border: const OutlineInputBorder(),
suffixText: s.unitType,
),
),
),
],
),
const SizedBox(height: 8),
// Dosage line
Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(6),
border: Border.all(
color: Theme.of(context).colorScheme.outline.withValues(alpha: 0.3),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Per unit:',
style: TextStyle(
fontSize: 12,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
Text(
s.ingredientsDisplay,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.onSurface,
),
),
],
),
),
],
),
);
}(),
if (index != supplements.length - 1) const SizedBox(height: 8),
],
],
),
),
),
const SizedBox(height: 12),
// Shared notes
TextField(
controller: notesController,
decoration: const InputDecoration(
labelText: 'Notes for all (optional)',
border: OutlineInputBorder(),
),
maxLines: 2,
),
],
),
)),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('Cancel'),
),
ElevatedButton(
onPressed: () {
final provider = context.read<SupplementProvider>();
int recorded = 0;
for (final s in supplements) {
if (s.id == null) continue;
final controller = unitControllers[s.id]!;
final units = double.tryParse(controller.text) ?? s.numberOfUnits.toDouble();
// totalDosageTaken stays 0.0 for now (ingredients-based tracking later)
provider.recordIntake(
s.id!,
0.0,
unitsTaken: units,
notes: notesController.text.isNotEmpty ? notesController.text : null,
takenAt: null, // "now"
);
recorded++;
}
Navigator.of(context).pop();
if (recorded > 0) {
final sonner = ShadSonner.of(context);
final id = DateTime.now().millisecondsSinceEpoch;
sonner.show(
ShadToast(
id: id,
title: Text('Recorded $recorded supplement${recorded == 1 ? '' : 's'}'),
action: ShadButton(
size: ShadButtonSize.sm,
child: const Text('Dismiss'),
onPressed: () => sonner.hide(id),
),
),
);
}
},
child: const Text('Record All'),
),
],
);
},
);
// Dispose controllers
for (final c in unitControllers.values) {
c.dispose();
}
notesController.dispose();
}