import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../models/supplement.dart'; import '../providers/settings_provider.dart'; import '../providers/supplement_provider.dart'; import '../providers/sync_provider.dart'; import '../widgets/supplement_card.dart'; import 'add_supplement_screen.dart'; import 'archived_supplements_screen.dart'; class SupplementsListScreen extends StatelessWidget { const SupplementsListScreen({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('My Supplements'), backgroundColor: Theme.of(context).colorScheme.inversePrimary, actions: [ Consumer( builder: (context, syncProvider, child) { if (!syncProvider.isConfigured) { return const SizedBox.shrink(); } return IconButton( icon: syncProvider.isSyncing ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2), ) : syncProvider.status.name == 'success' && DateTime.now().difference(syncProvider.lastSyncTime ?? DateTime.now()).inSeconds < 5 ? const Icon(Icons.check, color: Colors.green) : const Icon(Icons.sync), onPressed: syncProvider.isSyncing ? null : () { syncProvider.performManualSync(); }, tooltip: syncProvider.isSyncing ? 'Syncing...' : 'Force Sync', ); }, ), IconButton( icon: const Icon(Icons.archive), onPressed: () { Navigator.of(context).push( MaterialPageRoute( builder: (context) => const ArchivedSupplementsScreen(), ), ); }, tooltip: 'Archived Supplements', ), ], ), body: Consumer3( builder: (context, provider, settingsProvider, syncProvider, child) { if (provider.isLoading) { return const Center(child: CircularProgressIndicator()); } if (provider.supplements.isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.medication_outlined, size: 64, color: Theme.of(context).colorScheme.onSurfaceVariant, ), const SizedBox(height: 16), Text( 'No supplements added yet', style: TextStyle( fontSize: 18, color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), const SizedBox(height: 8), Text( 'Tap the + button to add your first supplement', style: TextStyle( color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ], ), ); } return RefreshIndicator( onRefresh: () async { await provider.loadSupplements(); await provider.refreshDailyStatus(); }, child: _buildGroupedSupplementsList(context, provider.supplements, settingsProvider), ); }, ), ); } Widget _buildGroupedSupplementsList(BuildContext context, List supplements, SettingsProvider settingsProvider) { final groupedSupplements = _groupSupplementsByTimeOfDay(supplements, settingsProvider); return ListView( padding: const EdgeInsets.all(16), children: [ if (groupedSupplements['morning']!.isNotEmpty) ...[ _buildSectionHeader('Morning (${settingsProvider.morningRange})', Icons.wb_sunny, Colors.orange, groupedSupplements['morning']!.length), ...groupedSupplements['morning']!.map((supplement) => SupplementCard( supplement: supplement, onTake: () => _showTakeDialog(context, supplement), onEdit: () => _editSupplement(context, supplement), onDelete: () => _deleteSupplement(context, supplement), onArchive: () => _archiveSupplement(context, supplement), ), ), const SizedBox(height: 16), ], if (groupedSupplements['afternoon']!.isNotEmpty) ...[ _buildSectionHeader('Afternoon (${settingsProvider.afternoonRange})', Icons.light_mode, Colors.blue, groupedSupplements['afternoon']!.length), ...groupedSupplements['afternoon']!.map((supplement) => SupplementCard( supplement: supplement, onTake: () => _showTakeDialog(context, supplement), onEdit: () => _editSupplement(context, supplement), onDelete: () => _deleteSupplement(context, supplement), onArchive: () => _archiveSupplement(context, supplement), ), ), const SizedBox(height: 16), ], if (groupedSupplements['evening']!.isNotEmpty) ...[ _buildSectionHeader('Evening (${settingsProvider.eveningRange})', Icons.nightlight_round, Colors.indigo, groupedSupplements['evening']!.length), ...groupedSupplements['evening']!.map((supplement) => SupplementCard( supplement: supplement, onTake: () => _showTakeDialog(context, supplement), onEdit: () => _editSupplement(context, supplement), onDelete: () => _deleteSupplement(context, supplement), onArchive: () => _archiveSupplement(context, supplement), ), ), const SizedBox(height: 16), ], if (groupedSupplements['night']!.isNotEmpty) ...[ _buildSectionHeader('Night (${settingsProvider.nightRange})', Icons.bedtime, Colors.purple, groupedSupplements['night']!.length), ...groupedSupplements['night']!.map((supplement) => SupplementCard( supplement: supplement, onTake: () => _showTakeDialog(context, supplement), onEdit: () => _editSupplement(context, supplement), onDelete: () => _deleteSupplement(context, supplement), onArchive: () => _archiveSupplement(context, supplement), ), ), const SizedBox(height: 16), ], if (groupedSupplements['anytime']!.isNotEmpty) ...[ _buildSectionHeader('Anytime', Icons.schedule, Colors.grey, groupedSupplements['anytime']!.length), ...groupedSupplements['anytime']!.map((supplement) => SupplementCard( supplement: supplement, onTake: () => _showTakeDialog(context, supplement), onEdit: () => _editSupplement(context, supplement), onDelete: () => _deleteSupplement(context, supplement), onArchive: () => _archiveSupplement(context, supplement), ), ), ], ], ); } Widget _buildSectionHeader(String title, IconData icon, Color color, int count) { return Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(12), border: Border.all( color: color.withOpacity(0.3), width: 1, ), ), child: Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: color.withOpacity(0.2), shape: BoxShape.circle, ), child: Icon( icon, size: 20, color: color, ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title.contains('(') ? title.split('(')[0].trim() : title, style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: color, ), ), if (title.contains('(')) ...[ Text( '(${title.split('(')[1]}', style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, color: color.withOpacity(0.8), ), ), ], ], ), ), Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: color.withOpacity(0.15), borderRadius: BorderRadius.circular(12), ), child: Text( count.toString(), style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: color, ), ), ), ], ), ); } Map> _groupSupplementsByTimeOfDay(List supplements, SettingsProvider settingsProvider) { final Map> grouped = { 'morning': [], 'afternoon': [], 'evening': [], 'night': [], 'anytime': [], }; for (final supplement in supplements) { final category = settingsProvider.determineTimeCategory(supplement.reminderTimes); grouped[category]!.add(supplement); } return grouped; } void _showTakeDialog(BuildContext context, Supplement supplement) { final unitsController = TextEditingController(text: supplement.numberOfUnits.toString()); final notesController = TextEditingController(); DateTime selectedDateTime = DateTime.now(); bool useCustomTime = false; showDialog( context: context, builder: (context) => StatefulBuilder( builder: (context, setState) { return AlertDialog( title: Text('Take ${supplement.name}'), content: Column( mainAxisSize: MainAxisSize.min, children: [ Row( children: [ Expanded( child: TextField( controller: unitsController, keyboardType: const TextInputType.numberWithOptions(decimal: true), decoration: InputDecoration( labelText: 'Number of ${supplement.unitType}', border: const OutlineInputBorder(), suffixText: supplement.unitType, ), onChanged: (value) => setState(() {}), ), ), ], ), const SizedBox(height: 8), Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: Theme.of(context).colorScheme.surfaceVariant, borderRadius: BorderRadius.circular(4), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Total dosage:', style: TextStyle( fontSize: 12, color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), Text( supplement.ingredientsDisplay, style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: Theme.of(context).colorScheme.onSurface, ), ), ], ), ), const SizedBox(height: 16), // Time selection section Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Theme.of(context).colorScheme.primaryContainer.withOpacity(0.3), borderRadius: BorderRadius.circular(8), border: Border.all( color: Theme.of(context).colorScheme.primary.withOpacity(0.3), ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon( Icons.access_time, size: 16, color: Theme.of(context).colorScheme.primary, ), const SizedBox(width: 6), Text( 'When did you take it?', style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: Theme.of(context).colorScheme.primary, ), ), ], ), const SizedBox(height: 8), Row( children: [ Expanded( child: RadioListTile( dense: true, contentPadding: EdgeInsets.zero, title: const Text('Just now', style: TextStyle(fontSize: 12)), value: false, groupValue: useCustomTime, onChanged: (value) => setState(() => useCustomTime = value!), ), ), Expanded( child: RadioListTile( dense: true, contentPadding: EdgeInsets.zero, title: const Text('Custom time', style: TextStyle(fontSize: 12)), value: true, groupValue: useCustomTime, onChanged: (value) => setState(() => useCustomTime = value!), ), ), ], ), if (useCustomTime) ...[ const SizedBox(height: 8), Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(6), border: Border.all( color: Theme.of(context).colorScheme.outline.withOpacity(0.5), ), ), child: Column( children: [ // Date picker Row( children: [ Icon( Icons.calendar_today, size: 14, color: Theme.of(context).colorScheme.onSurfaceVariant, ), const SizedBox(width: 8), Expanded( child: Text( 'Date: ${selectedDateTime.day}/${selectedDateTime.month}/${selectedDateTime.year}', style: const TextStyle(fontSize: 12), ), ), TextButton( 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), // Time picker Row( children: [ Icon( Icons.access_time, size: 14, color: Theme.of(context).colorScheme.onSurfaceVariant, ), 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), ), ), TextButton( 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), TextField( controller: notesController, decoration: const InputDecoration( labelText: 'Notes (optional)', border: OutlineInputBorder(), ), maxLines: 2, ), ], ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Cancel'), ), ElevatedButton( onPressed: () { final unitsTaken = double.tryParse(unitsController.text) ?? supplement.numberOfUnits.toDouble(); // For now, we'll record 0 as total dosage since we're transitioning to ingredients // This will be properly implemented when we add the full ingredient tracking final totalDosageTaken = 0.0; context.read().recordIntake( supplement.id!, totalDosageTaken, unitsTaken: unitsTaken, notes: notesController.text.isNotEmpty ? notesController.text : null, takenAt: useCustomTime ? selectedDateTime : null, ); Navigator.of(context).pop(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('${supplement.name} recorded!'), backgroundColor: Colors.green, ), ); }, child: const Text('Record'), ), ], ); }, ), ); } void _editSupplement(BuildContext context, Supplement supplement) { Navigator.of(context).push( MaterialPageRoute( builder: (context) => AddSupplementScreen(supplement: supplement), ), ); } void _deleteSupplement(BuildContext context, Supplement supplement) { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Delete Supplement'), content: Text('Are you sure you want to delete ${supplement.name}?'), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Cancel'), ), ElevatedButton( onPressed: () { context.read().deleteSupplement(supplement.id!); Navigator.of(context).pop(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('${supplement.name} deleted'), backgroundColor: Colors.red, ), ); }, style: ElevatedButton.styleFrom(backgroundColor: Colors.red), child: const Text('Delete'), ), ], ), ); } void _archiveSupplement(BuildContext context, Supplement supplement) { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Archive Supplement'), content: Text('Are you sure you want to archive ${supplement.name}? You can unarchive it later from the archived supplements list.'), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Cancel'), ), ElevatedButton( onPressed: () { context.read().archiveSupplement(supplement.id!); Navigator.of(context).pop(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('${supplement.name} archived'), backgroundColor: Colors.orange, ), ); }, style: ElevatedButton.styleFrom(backgroundColor: Colors.orange), child: const Text('Archive'), ), ], ), ); } }