mirror of
https://github.com/vleeuwenmenno/supplements.git
synced 2025-09-11 18:29:12 +02:00
Refactor supplement intake handling to support fractional units and update notification service initialization for Linux
This commit is contained in:
@@ -120,62 +120,98 @@ class _HistoryScreenState extends State<HistoryScreen> with SingleTickerProvider
|
||||
}
|
||||
|
||||
final intakes = snapshot.data!;
|
||||
|
||||
// Group intakes by supplement
|
||||
final Map<String, List<Map<String, dynamic>>> groupedIntakes = {};
|
||||
for (final intake in intakes) {
|
||||
final supplementName = intake['supplementName'] as String;
|
||||
groupedIntakes.putIfAbsent(supplementName, () => []);
|
||||
groupedIntakes[supplementName]!.add(intake);
|
||||
}
|
||||
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.all(16),
|
||||
itemCount: intakes.length,
|
||||
itemCount: groupedIntakes.length,
|
||||
itemBuilder: (context, index) {
|
||||
final intake = intakes[index];
|
||||
final takenAt = DateTime.parse(intake['takenAt']);
|
||||
final supplementName = groupedIntakes.keys.elementAt(index);
|
||||
final supplementIntakes = groupedIntakes[supplementName]!;
|
||||
|
||||
// Calculate totals
|
||||
double totalDosage = 0;
|
||||
double totalUnits = 0;
|
||||
final firstIntake = supplementIntakes.first;
|
||||
|
||||
for (final intake in supplementIntakes) {
|
||||
totalDosage += intake['dosageTaken'] as double;
|
||||
totalUnits += (intake['unitsTaken'] as num?)?.toDouble() ?? 1.0;
|
||||
}
|
||||
|
||||
return Card(
|
||||
margin: const EdgeInsets.only(bottom: 8),
|
||||
child: ListTile(
|
||||
margin: const EdgeInsets.only(bottom: 12),
|
||||
child: ExpansionTile(
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
child: Icon(Icons.medication, color: Theme.of(context).colorScheme.onPrimary),
|
||||
),
|
||||
title: Text(intake['supplementName']),
|
||||
title: Text(
|
||||
supplementName,
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('${intake['dosageTaken']} ${intake['supplementUnit']}'),
|
||||
Text(
|
||||
'Taken at ${DateFormat('HH:mm').format(takenAt)}',
|
||||
'${totalDosage.toStringAsFixed(totalDosage % 1 == 0 ? 0 : 1)} ${firstIntake['supplementUnit']} total',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'${totalUnits.toStringAsFixed(totalUnits % 1 == 0 ? 0 : 1)} ${firstIntake['supplementUnitType'] ?? 'units'} • ${supplementIntakes.length} intake${supplementIntakes.length > 1 ? 's' : ''}',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
if (intake['notes'] != null && intake['notes'].toString().isNotEmpty)
|
||||
Text(
|
||||
intake['notes'],
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
fontStyle: FontStyle.italic,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
trailing: PopupMenuButton(
|
||||
onSelected: (value) {
|
||||
if (value == 'delete') {
|
||||
_deleteIntake(context, intake['id'], intake['supplementName']);
|
||||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
const PopupMenuItem(
|
||||
value: 'delete',
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.delete, color: Colors.red),
|
||||
SizedBox(width: 8),
|
||||
Text('Delete', style: TextStyle(color: Colors.red)),
|
||||
],
|
||||
),
|
||||
children: supplementIntakes.map((intake) {
|
||||
final takenAt = DateTime.parse(intake['takenAt']);
|
||||
final units = (intake['unitsTaken'] as num?)?.toDouble() ?? 1.0;
|
||||
|
||||
return ListTile(
|
||||
contentPadding: const EdgeInsets.only(left: 72, right: 16),
|
||||
title: Text(
|
||||
'${(intake['dosageTaken'] as double).toStringAsFixed((intake['dosageTaken'] as double) % 1 == 0 ? 0 : 1)} ${intake['supplementUnit']}',
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
],
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${units.toStringAsFixed(units % 1 == 0 ? 0 : 1)} ${intake['supplementUnitType'] ?? 'units'} at ${DateFormat('HH:mm').format(takenAt)}',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
if (intake['notes'] != null && intake['notes'].toString().isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 4),
|
||||
child: Text(
|
||||
intake['notes'],
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontStyle: FontStyle.italic,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@@ -133,7 +133,7 @@ class SupplementsListScreen extends StatelessWidget {
|
||||
context: context,
|
||||
builder: (context) => StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
final units = int.tryParse(unitsController.text) ?? supplement.numberOfUnits;
|
||||
final units = double.tryParse(unitsController.text) ?? supplement.numberOfUnits.toDouble();
|
||||
final totalDosage = supplement.dosageAmount * units;
|
||||
|
||||
return AlertDialog(
|
||||
@@ -146,7 +146,7 @@ class SupplementsListScreen extends StatelessWidget {
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: unitsController,
|
||||
keyboardType: TextInputType.number,
|
||||
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Number of ${supplement.unitType}',
|
||||
border: const OutlineInputBorder(),
|
||||
@@ -175,7 +175,7 @@ class SupplementsListScreen extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'${totalDosage.toStringAsFixed(1)} ${supplement.unit}',
|
||||
'${totalDosage.toStringAsFixed(totalDosage % 1 == 0 ? 0 : 1)} ${supplement.unit}',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
@@ -203,7 +203,7 @@ class SupplementsListScreen extends StatelessWidget {
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
final unitsTaken = int.tryParse(unitsController.text) ?? supplement.numberOfUnits;
|
||||
final unitsTaken = double.tryParse(unitsController.text) ?? supplement.numberOfUnits.toDouble();
|
||||
final totalDosageTaken = supplement.dosageAmount * unitsTaken;
|
||||
context.read<SupplementProvider>().recordIntake(
|
||||
supplement.id!,
|
||||
|
Reference in New Issue
Block a user