import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../models/routine.dart'; import '../../repositories/routine_repository.dart'; import '../../theme/app_theme.dart'; import '../routines/widgets/routine_card.dart'; class DashboardScreen extends ConsumerWidget { const DashboardScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final todayRoutinesAsync = ref.watch(todayRoutinesProvider); return Scaffold( body: CustomScrollView( slivers: [ // App Bar with greeting SliverAppBar( expandedHeight: 120, floating: true, pinned: true, flexibleSpace: FlexibleSpaceBar( title: Column( mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( _getGreeting(), style: const TextStyle( fontSize: 14, fontWeight: FontWeight.normal, ), ), const Text( 'Ready to flow?', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, ), ), ], ), ), actions: [ IconButton( icon: const Icon(Icons.notifications_outlined), onPressed: () { // Show notifications }, ), IconButton( icon: const Icon(Icons.person_outline), onPressed: () { // Show profile }, ), ], ), // Daily Progress Ring SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.all(16.0), child: _buildDailyProgressCard(context), ), ), // Quick Stats SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: _buildQuickStatsRow(), ), ), // Today's Routines Header SliverPadding( padding: const EdgeInsets.all(16.0), sliver: SliverToBoxAdapter( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( "Today's Routines", style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, ), ), TextButton( onPressed: () { // Navigate to all routines }, child: const Text('See All'), ), ], ), ), ), // Today's Routines List todayRoutinesAsync.when( data: (routines) { if (routines.isEmpty) { return const SliverFillRemaining( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.spa_outlined, size: 64, color: Colors.grey, ), SizedBox(height: 16), Text( 'No routines for today', style: TextStyle( fontSize: 18, color: Colors.grey, ), ), SizedBox(height: 8), Text( 'Add your first routine to get started!', style: TextStyle( color: Colors.grey, ), ), ], ), ), ); } return SliverList( delegate: SliverChildBuilderDelegate( (context, index) { final routine = routines[index]; return RoutineCard( routine: routine, onTap: () => _showRoutineDetails(context, routine), onComplete: () => _completeRoutine(context, ref, routine), ); }, childCount: routines.length, ), ); }, loading: () => const SliverFillRemaining( child: Center(child: CircularProgressIndicator()), ), error: (error, stack) => SliverFillRemaining( child: Center( child: Text('Error: $error'), ), ), ), // Bottom padding const SliverPadding( padding: EdgeInsets.only(bottom: 100), ), ], ), floatingActionButton: FloatingActionButton.extended( onPressed: () => _showAddRoutineDialog(context), icon: const Icon(Icons.add), label: const Text('Add Routine'), ), ); } String _getGreeting() { final hour = DateTime.now().hour; if (hour < 12) return 'Good morning'; if (hour < 17) return 'Good afternoon'; return 'Good evening'; } Widget _buildDailyProgressCard(BuildContext context) { return Card( elevation: 4, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20), ), child: Padding( padding: const EdgeInsets.all(20.0), child: Row( children: [ // Progress Ring SizedBox( width: 100, height: 100, child: Stack( fit: StackFit.expand, children: [ CircularProgressIndicator( value: 0.65, // TODO: Calculate from actual data strokeWidth: 10, backgroundColor: Colors.grey[200], valueColor: AlwaysStoppedAnimation( Theme.of(context).colorScheme.primary, ), ), Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text( '65%', style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, ), ), Text( 'Done', style: TextStyle( fontSize: 12, color: Colors.grey[600], ), ), ], ), ), ], ), ), const SizedBox(width: 20), // Stats Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( "Today's Progress", style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), Text( '7 of 11 routines completed', style: TextStyle( color: Colors.grey[600], ), ), const SizedBox(height: 12), Row( children: [ _buildStatChip( icon: Icons.local_fire_department, label: '5 day streak', color: Colors.orange, ), ], ), ], ), ), ], ), ), ); } Widget _buildStatChip({ required IconData icon, required String label, required Color color, }) { return Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(20), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(icon, size: 16, color: color), const SizedBox(width: 4), Text( label, style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: color, ), ), ], ), ); } Widget _buildQuickStatsRow() { return Row( children: [ Expanded( child: _buildQuickStatCard( icon: Icons.water_drop, label: 'Hydration', value: '1.5L', color: Colors.blue, ), ), const SizedBox(width: 12), Expanded( child: _buildQuickStatCard( icon: Icons.medication, label: 'Meds Taken', value: '2/3', color: Colors.red, ), ), const SizedBox(width: 12), Expanded( child: _buildQuickStatCard( icon: Icons.star, label: 'Points', value: '245', color: Colors.amber, ), ), ], ); } Widget _buildQuickStatCard({ required IconData icon, required String label, required String value, required Color color, }) { return Card( child: Padding( padding: const EdgeInsets.all(12.0), child: Column( children: [ Icon(icon, color: color, size: 28), const SizedBox(height: 8), Text( value, style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, ), ), Text( label, style: TextStyle( fontSize: 12, color: Colors.grey[600], ), ), ], ), ), ); } void _showRoutineDetails(BuildContext context, Routine routine) { showModalBottomSheet( context: context, isScrollControlled: true, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), builder: (context) => DraggableScrollableSheet( initialChildSize: 0.6, maxChildSize: 0.9, minChildSize: 0.4, expand: false, builder: (context, scrollController) { return SingleChildScrollView( controller: scrollController, child: Padding( padding: const EdgeInsets.all(20.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Center( child: Container( width: 40, height: 4, decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(2), ), ), ), const SizedBox(height: 20), Row( children: [ Text( routine.category.icon, style: const TextStyle(fontSize: 40), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( routine.name, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, ), ), Text( routine.category.displayName, style: TextStyle( color: Colors.grey[600], ), ), ], ), ), ], ), const SizedBox(height: 20), if (routine.description != null) ...[ Text( routine.description!, style: TextStyle( fontSize: 16, color: Colors.grey[700], ), ), const SizedBox(height: 20), ], _buildDetailRow( Icons.schedule, 'Scheduled for', routine.schedule.time, ), _buildDetailRow( Icons.repeat, 'Frequency', _getFrequencyText(routine.schedule), ), _buildDetailRow( Icons.star, 'Points', '${routine.points} points', ), const SizedBox(height: 30), SizedBox( width: double.infinity, child: ElevatedButton.icon( onPressed: () { Navigator.pop(context); // Mark as complete }, icon: const Icon(Icons.check_circle), label: const Text('Mark as Complete'), style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 16), ), ), ), ], ), ), ); }, ), ); } Widget _buildDetailRow(IconData icon, String label, String value) { return Padding( padding: const EdgeInsets.symmetric(vertical: 12.0), child: Row( children: [ Icon(icon, color: Colors.grey), const SizedBox(width: 12), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: TextStyle( fontSize: 12, color: Colors.grey[600], ), ), Text( value, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, ), ), ], ), ], ), ); } String _getFrequencyText(Schedule schedule) { switch (schedule.type) { case ScheduleType.daily: return 'Every day'; case ScheduleType.weekly: final days = schedule.daysOfWeek?.map((d) { final dayNames = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; return dayNames[d]; }).join(', '); return days ?? 'Weekly'; case ScheduleType.specificDate: return 'One-time'; case ScheduleType.interval: return 'Every ${schedule.intervalDays} days'; } } void _completeRoutine(BuildContext context, WidgetRef ref, Routine routine) { // TODO: Implement completion logic ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('${routine.name} completed! +${routine.points} points'), backgroundColor: Colors.green, behavior: SnackBarBehavior.floating, action: SnackBarAction( label: 'UNDO', onPressed: () { // Undo completion }, ), ), ); } void _showAddRoutineDialog(BuildContext context) { // TODO: Navigate to add routine screen showModalBottomSheet( context: context, isScrollControlled: true, builder: (context) => const AddRoutineSheet(), ); } } class AddRoutineSheet extends StatelessWidget { const AddRoutineSheet({super.key}); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(20), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Add New Routine', style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 20), ...RoutineCategory.values.map((category) => ListTile( leading: Text(category.icon, style: const TextStyle(fontSize: 28)), title: Text(category.displayName), onTap: () { // Navigate to routine creation with this category Navigator.pop(context); }, )), ], ), ); } }