mirror of
https://github.com/vleeuwenmenno/supplements.git
synced 2025-09-12 02:36:53 +02:00
notification overhaul
This commit is contained in:
206
lib/widgets/dialogs/bulk_take_dialog.dart
Normal file
206
lib/widgets/dialogs/bulk_take_dialog.dart
Normal file
@@ -0,0 +1,206 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.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.surfaceVariant.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
color: Theme.of(context).colorScheme.outline.withOpacity(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.withOpacity(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) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Recorded $recorded supplement${recorded == 1 ? '' : 's'}'),
|
||||
backgroundColor: Colors.green,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: const Text('Record All'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
// Dispose controllers
|
||||
for (final c in unitControllers.values) {
|
||||
c.dispose();
|
||||
}
|
||||
notesController.dispose();
|
||||
}
|
Reference in New Issue
Block a user