Files
supplements/lib/widgets/dialogs/take_supplement_dialog.dart
Menno van Leeuwen 666008f05d Refactor and enhance UI components across multiple screens
- Updated date and time formatting in debug notifications screen for clarity.
- Wrapped context-dependent state updates in post-frame callbacks in history screen to ensure proper context usage.
- Improved layout and styling in settings screen by reordering radio list tiles.
- Enhanced logging in auto sync service for better error tracking.
- Added context mounted checks in notification router to prevent errors during navigation.
- Updated bulk take dialog to use new UI components from shadcn_ui package.
- Refactored take supplement dialog to utilize shadcn_ui for a more modern look and feel.
- Adjusted info chip and supplement card widgets to use updated color schemes and layouts.
- Updated pubspec.yaml and pubspec.lock to include new dependencies and versions.
2025-08-31 19:15:32 +02:00

246 lines
11 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 the "Take supplement" dialog.
/// - If [hideTime] is true, the time selection UI is hidden and intake is recorded as "now".
Future<void> showTakeSupplementDialog(
BuildContext context,
Supplement supplement, {
bool hideTime = false,
}) async {
final unitsController = TextEditingController(text: supplement.numberOfUnits.toString());
final notesController = TextEditingController();
DateTime selectedDateTime = DateTime.now();
bool useCustomTime = false;
await showShadDialog(
context: context,
builder: (context) => StatefulBuilder(
builder: (context, setState) {
return ShadDialog(
title: Text('Take ${supplement.name}'),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
Expanded(
child: ShadInput(
controller: unitsController,
keyboardType: const TextInputType.numberWithOptions(decimal: true),
placeholder: Text('Number of ${supplement.unitType}'),
onChanged: (value) => setState(() {}),
),
),
],
),
const SizedBox(height: 8),
ShadCard(
child: Padding(
padding: const EdgeInsets.all(8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Total dosage:',
style: TextStyle(
fontSize: 12,
color: ShadTheme.of(context).colorScheme.foreground,
),
),
Text(
supplement.ingredientsDisplay,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: ShadTheme.of(context).colorScheme.foreground,
),
),
],
),
),
),
const SizedBox(height: 16),
if (!hideTime) ...[
ShadCard(
child: Padding(
padding: const EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
Icons.access_time,
size: 16,
color: ShadTheme.of(context).colorScheme.primary,
),
const SizedBox(width: 6),
Text(
'When did you take it?',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: ShadTheme.of(context).colorScheme.primary,
),
),
],
),
const SizedBox(height: 8),
ShadRadioGroupFormField<bool>(
initialValue: useCustomTime,
onChanged: (value) => setState(() => useCustomTime = value!),
items: [
ShadRadio(
value: false,
label: const Text('Just now', style: TextStyle(fontSize: 12)),
),
ShadRadio(
value: true,
label: const Text('Custom time', style: TextStyle(fontSize: 12)),
),
],
),
if (useCustomTime) ...[
const SizedBox(height: 8),
ShadCard(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
child: Column(
children: [
Row(
children: [
Icon(
Icons.calendar_today,
size: 14,
color: ShadTheme.of(context).colorScheme.foreground,
),
const SizedBox(width: 8),
Expanded(
child: Text(
'Date: ${selectedDateTime.day}/${selectedDateTime.month}/${selectedDateTime.year}',
style: const TextStyle(fontSize: 12),
),
),
ShadButton.outline(
onPressed: () async {
final date = await showDatePicker(
context: context,
initialDate: selectedDateTime,
firstDate: DateTime.now().subtract(const Duration(days: 7)),
lastDate: DateTime.now(),
);
if (date != null) {
setState(() {
selectedDateTime = DateTime(
date.year,
date.month,
date.day,
selectedDateTime.hour,
selectedDateTime.minute,
);
});
}
},
child: const Text('Change', style: TextStyle(fontSize: 10)),
),
],
),
const SizedBox(height: 4),
Row(
children: [
Icon(
Icons.access_time,
size: 14,
color: ShadTheme.of(context).colorScheme.foreground,
),
const SizedBox(width: 8),
Expanded(
child: Text(
'Time: ${selectedDateTime.hour.toString().padLeft(2, '0')}:${selectedDateTime.minute.toString().padLeft(2, '0')}',
style: const TextStyle(fontSize: 12),
),
),
ShadButton.outline(
onPressed: () async {
final time = await showTimePicker(
context: context,
initialTime: TimeOfDay.fromDateTime(selectedDateTime),
);
if (time != null) {
setState(() {
selectedDateTime = DateTime(
selectedDateTime.year,
selectedDateTime.month,
selectedDateTime.day,
time.hour,
time.minute,
);
});
}
},
child: const Text('Change', style: TextStyle(fontSize: 10)),
),
],
),
],
),
),
),
],
],
),
),
),
const SizedBox(height: 16),
],
ShadInput(
controller: notesController,
placeholder: const Text('Notes (optional)'),
maxLines: 2,
),
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
ShadButton.outline(
onPressed: () => Navigator.of(context).pop(),
child: const Text('Cancel'),
),
const SizedBox(width: 8),
ShadButton(
onPressed: () {
final unitsTaken = double.tryParse(unitsController.text) ?? supplement.numberOfUnits.toDouble();
final totalDosageTaken = 0.0;
context.read<SupplementProvider>().recordIntake(
supplement.id!,
totalDosageTaken,
unitsTaken: unitsTaken,
notes: notesController.text.isNotEmpty ? notesController.text : null,
takenAt: hideTime ? null : (useCustomTime ? selectedDateTime : null),
);
Navigator.of(context).pop();
ShadToaster.of(context).show(
ShadToast(
title: Text('${supplement.name} recorded!'),
),
);
},
child: const Text('Record'),
),
],
),
],
),
),
);
},
),
);
}