import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:intl/intl.dart'; import '../providers/supplement_provider.dart'; class HistoryScreen extends StatefulWidget { const HistoryScreen({super.key}); @override State createState() => _HistoryScreenState(); } class _HistoryScreenState extends State with SingleTickerProviderStateMixin { late TabController _tabController; DateTime _selectedDate = DateTime.now(); int _selectedMonth = DateTime.now().month; int _selectedYear = DateTime.now().year; @override void initState() { super.initState(); _tabController = TabController(length: 2, vsync: this); WidgetsBinding.instance.addPostFrameCallback((_) { context.read().loadMonthlyIntakes(_selectedYear, _selectedMonth); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Intake History'), backgroundColor: Theme.of(context).colorScheme.inversePrimary, bottom: TabBar( controller: _tabController, tabs: const [ Tab(text: 'Daily View'), Tab(text: 'Monthly View'), ], ), ), body: TabBarView( controller: _tabController, children: [ _buildDailyView(), _buildMonthlyView(), ], ), ); } Widget _buildDailyView() { return Column( children: [ Container( padding: const EdgeInsets.all(16), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ IconButton( onPressed: () { setState(() { _selectedDate = _selectedDate.subtract(const Duration(days: 1)); }); }, icon: const Icon(Icons.chevron_left), ), InkWell( onTap: _selectDate, child: Text( DateFormat('EEEE, MMM d, yyyy').format(_selectedDate), style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), ), IconButton( onPressed: _selectedDate.isBefore(DateTime.now()) ? () { setState(() { _selectedDate = _selectedDate.add(const Duration(days: 1)); }); } : null, icon: const Icon(Icons.chevron_right), ), ], ), ), Expanded( child: FutureBuilder>>( future: context.read().getIntakesForDate(_selectedDate), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } if (!snapshot.hasData || snapshot.data!.isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.event_note, size: 64, color: Theme.of(context).colorScheme.onSurfaceVariant, ), const SizedBox(height: 16), Text( 'No supplements taken on this day', style: TextStyle( fontSize: 18, color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ], ), ); } final intakes = snapshot.data!; return ListView.builder( padding: const EdgeInsets.all(16), itemCount: intakes.length, itemBuilder: (context, index) { final intake = intakes[index]; final takenAt = DateTime.parse(intake['takenAt']); return Card( margin: const EdgeInsets.only(bottom: 8), child: ListTile( leading: CircleAvatar( backgroundColor: Theme.of(context).colorScheme.primary, child: Icon(Icons.medication, color: Theme.of(context).colorScheme.onPrimary), ), title: Text(intake['supplementName']), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('${intake['dosageTaken']} ${intake['supplementUnit']}'), Text( 'Taken at ${DateFormat('HH:mm').format(takenAt)}', 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)), ], ), ), ], ), ), ); }, ); }, ), ), ], ); } Widget _buildMonthlyView() { return Column( children: [ Container( padding: const EdgeInsets.all(16), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ IconButton( onPressed: () { setState(() { if (_selectedMonth == 1) { _selectedMonth = 12; _selectedYear--; } else { _selectedMonth--; } }); context.read().loadMonthlyIntakes(_selectedYear, _selectedMonth); }, icon: const Icon(Icons.chevron_left), ), Text( DateFormat('MMMM yyyy').format(DateTime(_selectedYear, _selectedMonth)), style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), IconButton( onPressed: () { final now = DateTime.now(); if (_selectedYear < now.year || (_selectedYear == now.year && _selectedMonth < now.month)) { setState(() { if (_selectedMonth == 12) { _selectedMonth = 1; _selectedYear++; } else { _selectedMonth++; } }); context.read().loadMonthlyIntakes(_selectedYear, _selectedMonth); } }, icon: const Icon(Icons.chevron_right), ), ], ), ), Expanded( child: Consumer( builder: (context, provider, child) { if (provider.monthlyIntakes.isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.calendar_month, size: 64, color: Theme.of(context).colorScheme.onSurfaceVariant, ), const SizedBox(height: 16), Text( 'No supplements taken this month', style: TextStyle( fontSize: 18, color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ], ), ); } // Group intakes by date final groupedIntakes = >>{}; for (final intake in provider.monthlyIntakes) { final date = DateTime.parse(intake['takenAt']); final dateKey = DateFormat('yyyy-MM-dd').format(date); groupedIntakes.putIfAbsent(dateKey, () => []); groupedIntakes[dateKey]!.add(intake); } final sortedDates = groupedIntakes.keys.toList() ..sort((a, b) => b.compareTo(a)); // Most recent first return ListView.builder( padding: const EdgeInsets.all(16), itemCount: sortedDates.length, itemBuilder: (context, index) { final dateKey = sortedDates[index]; final dayIntakes = groupedIntakes[dateKey]!; final date = DateTime.parse(dateKey); return Card( margin: const EdgeInsets.only(bottom: 16), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( DateFormat('EEEE, MMM d').format(date), style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), ...dayIntakes.map((intake) { final takenAt = DateTime.parse(intake['takenAt']); return Padding( padding: const EdgeInsets.only(bottom: 4), child: Row( children: [ Icon( Icons.circle, size: 8, color: Theme.of(context).colorScheme.primary, ), const SizedBox(width: 8), Expanded( child: Text( '${intake['supplementName']} - ${intake['dosageTaken']} ${intake['supplementUnit']} at ${DateFormat('HH:mm').format(takenAt)}', style: const TextStyle(fontSize: 14), ), ), ], ), ); }), const SizedBox(height: 4), Text( '${dayIntakes.length} supplement${dayIntakes.length != 1 ? 's' : ''} taken', style: TextStyle( fontSize: 12, color: Theme.of(context).colorScheme.onSurfaceVariant, fontWeight: FontWeight.w500, ), ), ], ), ), ); }, ); }, ), ), ], ); } void _selectDate() async { final picked = await showDatePicker( context: context, initialDate: _selectedDate, firstDate: DateTime(2020), lastDate: DateTime.now(), ); if (picked != null) { setState(() { _selectedDate = picked; }); } } void _deleteIntake(BuildContext context, int intakeId, String supplementName) { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Delete Intake'), content: Text('Are you sure you want to delete this $supplementName intake?'), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Cancel'), ), ElevatedButton( onPressed: () { context.read().deleteIntake(intakeId); Navigator.of(context).pop(); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Intake deleted'), backgroundColor: Colors.red, ), ); setState(() {}); // Refresh the view }, style: ElevatedButton.styleFrom(backgroundColor: Colors.red), child: const Text('Delete'), ), ], ), ); } @override void dispose() { _tabController.dispose(); super.dispose(); } }