import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../models/user_profile.dart'; import '../../models/teaching_plan.dart'; import '../../models/cycle_entry.dart'; import '../../models/scripture.dart'; import '../../providers/user_provider.dart'; import '../../theme/app_theme.dart'; import '../../services/notification_service.dart'; import '../../services/mock_data_service.dart'; import '../../services/bible_xml_parser.dart'; import '../calendar/calendar_screen.dart'; import 'husband_devotional_screen.dart'; import 'husband_settings_screen.dart'; import 'husband_appearance_screen.dart'; import 'learn_article_screen.dart'; import 'husband_notes_screen.dart'; /// Husband's companion app main screen class HusbandHomeScreen extends ConsumerStatefulWidget { const HusbandHomeScreen({super.key}); @override ConsumerState createState() => _HusbandHomeScreenState(); } class _HusbandHomeScreenState extends ConsumerState { int _selectedIndex = 0; @override Widget build(BuildContext context) { final husbandTheme = _husbandTheme; final isDark = husbandTheme.brightness == Brightness.dark; return Theme( data: husbandTheme, child: Builder( builder: (context) => Scaffold( backgroundColor: Theme.of(context).scaffoldBackgroundColor, body: IndexedStack( index: _selectedIndex, children: [ const _HusbandDashboard(), const CalendarScreen(readOnly: true), // Reused Calendar const HusbandDevotionalScreen(), // Devotional & Planning const _HusbandTipsScreen(), const _HusbandLearnScreen(), const HusbandSettingsScreen(), ], ), bottomNavigationBar: Container( decoration: BoxDecoration( color: isDark ? const Color(0xFF1E1E1E) : Colors.white, boxShadow: [ BoxShadow( color: (isDark ? Colors.black : AppColors.navyBlue) .withOpacity(0.1), blurRadius: 10, offset: const Offset(0, -2), ), ], ), child: BottomNavigationBar( currentIndex: _selectedIndex, onTap: (index) => setState(() => _selectedIndex = index), backgroundColor: isDark ? const Color(0xFF1E1E1E) : Colors.white, selectedItemColor: Theme.of(context).colorScheme.primary, unselectedItemColor: isDark ? Colors.grey : AppColors.warmGray, type: BottomNavigationBarType.fixed, items: const [ BottomNavigationBarItem( icon: Icon(Icons.home_outlined), activeIcon: Icon(Icons.home), label: 'Home', ), BottomNavigationBarItem( icon: Icon(Icons.calendar_month_outlined), activeIcon: Icon(Icons.calendar_month), label: 'Calendar', ), BottomNavigationBarItem( icon: Icon(Icons.menu_book_outlined), activeIcon: Icon(Icons.menu_book), label: 'Devotion', ), BottomNavigationBarItem( icon: Icon(Icons.lightbulb_outline), activeIcon: Icon(Icons.lightbulb), label: 'Tips', ), BottomNavigationBarItem( icon: Icon(Icons.school_outlined), activeIcon: Icon(Icons.school), label: 'Learn', ), BottomNavigationBarItem( icon: Icon(Icons.settings_outlined), activeIcon: Icon(Icons.settings), label: 'Settings', ), ], ), ), ), ), ); } ThemeData get _husbandTheme { final user = ref.watch(userProfileProvider); final husbandThemeMode = user?.husbandThemeMode ?? AppThemeMode.system; final husbandAccentColor = user?.husbandAccentColor ?? '0xFF1A3A5C'; // Determine brightness based on husbandThemeMode Brightness brightness = MediaQuery.platformBrightnessOf(context); if (husbandThemeMode == AppThemeMode.light) { brightness = Brightness.light; } else if (husbandThemeMode == AppThemeMode.dark) { brightness = Brightness.dark; } final isDark = brightness == Brightness.dark; final accentColor = Color(int.parse(husbandAccentColor)); // Dark theme with good contrast if (isDark) { return ThemeData( useMaterial3: true, brightness: Brightness.dark, scaffoldBackgroundColor: const Color(0xFF121212), colorScheme: ColorScheme.dark( primary: accentColor, secondary: const Color(0xFFD4A574), // Warm gold for contrast surface: const Color(0xFF1E1E1E), onSurface: Colors.white, onBackground: Colors.white, ), // Text theme with high contrast for dark mode textTheme: TextTheme( headlineLarge: GoogleFonts.outfit( fontSize: 28, fontWeight: FontWeight.bold, color: Colors.white, ), headlineMedium: GoogleFonts.outfit( fontSize: 22, fontWeight: FontWeight.w600, color: Colors.white, ), titleLarge: GoogleFonts.outfit( fontSize: 18, fontWeight: FontWeight.w600, color: Colors.white, ), titleMedium: GoogleFonts.outfit( fontSize: 16, fontWeight: FontWeight.w500, color: Colors.white.withOpacity(0.95), ), bodyLarge: GoogleFonts.outfit( fontSize: 16, color: Colors.white.withOpacity(0.9), ), bodyMedium: GoogleFonts.outfit( fontSize: 14, color: Colors.white.withOpacity(0.85), ), bodySmall: GoogleFonts.outfit( fontSize: 12, color: Colors.white.withOpacity(0.7), ), labelLarge: GoogleFonts.outfit( fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white, ), ), appBarTheme: AppBarTheme( backgroundColor: const Color(0xFF1E1E1E), foregroundColor: Colors.white, elevation: 0, iconTheme: const IconThemeData(color: Colors.white), titleTextStyle: GoogleFonts.outfit( fontSize: 20, fontWeight: FontWeight.w600, color: Colors.white, ), ), cardTheme: CardThemeData( color: const Color(0xFF2A2A2A), elevation: 2, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), ), cardColor: const Color(0xFF2A2A2A), dividerColor: Colors.white.withOpacity(0.12), iconTheme: const IconThemeData(color: Colors.white70), elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( backgroundColor: accentColor, foregroundColor: Colors.white, ), ), segmentedButtonTheme: SegmentedButtonThemeData( style: SegmentedButton.styleFrom( backgroundColor: const Color(0xFF2A2A2A), foregroundColor: Colors.white70, selectedBackgroundColor: accentColor, selectedForegroundColor: Colors.white, ), ), ); } else { // Light theme return ThemeData( useMaterial3: true, brightness: Brightness.light, scaffoldBackgroundColor: AppColors.warmCream, colorScheme: ColorScheme.light( primary: accentColor, secondary: AppColors.gold, surface: Colors.white, onSurface: AppColors.charcoal, onBackground: AppColors.charcoal, ), textTheme: TextTheme( headlineLarge: GoogleFonts.outfit( fontSize: 28, fontWeight: FontWeight.bold, color: AppColors.charcoal, ), headlineMedium: GoogleFonts.outfit( fontSize: 22, fontWeight: FontWeight.w600, color: AppColors.charcoal, ), titleLarge: GoogleFonts.outfit( fontSize: 18, fontWeight: FontWeight.w600, color: AppColors.charcoal, ), titleMedium: GoogleFonts.outfit( fontSize: 16, fontWeight: FontWeight.w500, color: AppColors.charcoal.withOpacity(0.9), ), bodyLarge: GoogleFonts.outfit( fontSize: 16, color: AppColors.charcoal, ), bodyMedium: GoogleFonts.outfit( fontSize: 14, color: AppColors.charcoal.withOpacity(0.85), ), bodySmall: GoogleFonts.outfit( fontSize: 12, color: AppColors.warmGray, ), labelLarge: GoogleFonts.outfit( fontSize: 14, fontWeight: FontWeight.w500, color: AppColors.charcoal, ), ), appBarTheme: AppBarTheme( backgroundColor: AppColors.warmCream, foregroundColor: accentColor, elevation: 0, iconTheme: IconThemeData(color: accentColor), titleTextStyle: GoogleFonts.outfit( fontSize: 20, fontWeight: FontWeight.w600, color: accentColor, ), ), cardTheme: CardThemeData( color: Colors.white, elevation: 2, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), ), cardColor: Colors.white, dividerColor: AppColors.lightGray, iconTheme: IconThemeData(color: AppColors.warmGray), elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( backgroundColor: accentColor, foregroundColor: Colors.white, ), ), segmentedButtonTheme: SegmentedButtonThemeData( style: SegmentedButton.styleFrom( backgroundColor: AppColors.lightGray, foregroundColor: AppColors.charcoal, selectedBackgroundColor: accentColor, selectedForegroundColor: Colors.white, ), ), ); } } } class _HusbandDashboard extends ConsumerStatefulWidget { const _HusbandDashboard(); @override ConsumerState<_HusbandDashboard> createState() => _HusbandDashboardState(); } class _HusbandDashboardState extends ConsumerState<_HusbandDashboard> { Scripture? _currentScripture; @override void initState() { super.initState(); _loadNewVerse(); } void _loadNewVerse() { setState(() { _currentScripture = ScriptureDatabase().getHusbandScripture(); }); } @override Widget build(BuildContext context) { final user = ref.watch(userProfileProvider); final cycleInfo = ref.watch(currentCycleInfoProvider); final wifeName = user?.partnerName ?? "Wife"; final phase = cycleInfo.phase; final dayOfCycle = cycleInfo.dayOfCycle; final daysUntilPeriod = cycleInfo.daysUntilPeriod; final scripture = _currentScripture ?? ScriptureDatabase().getHusbandScripture(); return SafeArea( child: SingleChildScrollView( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Greeting Text( 'Hey there,', style: GoogleFonts.outfit( fontSize: 16, color: AppColors.warmGray, ), ), Text( 'Husband', style: GoogleFonts.outfit( fontSize: 28, fontWeight: FontWeight.w600, color: AppColors.navyBlue, ), ), const SizedBox(height: 24), // Wife's Cycle Status Container( width: double.infinity, padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppColors.navyBlue, AppColors.steelBlue, ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(20), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( width: 40, height: 40, decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(10), ), child: const Icon( Icons.favorite, color: Colors.white, size: 22, ), ), const SizedBox(width: 12), Text( '$wifeName\'s Cycle', style: GoogleFonts.outfit( fontSize: 16, fontWeight: FontWeight.w500, color: Colors.white.withOpacity(0.9), ), ), ], ), const SizedBox(height: 16), Text( 'Day $dayOfCycle • ${phase.label}', style: GoogleFonts.outfit( fontSize: 24, fontWeight: FontWeight.w600, color: Colors.white, ), ), const SizedBox(height: 4), Text( daysUntilPeriod > 0 ? '~$daysUntilPeriod days until period' : 'Period expected soon', style: GoogleFonts.outfit( fontSize: 14, color: Colors.white.withOpacity(0.8), ), ), const SizedBox(height: 16), Container( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 6, ), decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(20), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Text(phase.emoji), const SizedBox(width: 6), Text( _getPhaseHint(phase), style: GoogleFonts.outfit( fontSize: 12, color: Colors.white, ), ), ], ), ), ], ), ), const SizedBox(height: 20), // Support Tip Container( width: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: AppColors.navyBlue.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( width: 36, height: 36, decoration: BoxDecoration( color: AppColors.gold.withOpacity(0.2), borderRadius: BorderRadius.circular(10), ), child: const Icon( Icons.lightbulb_outline, color: AppColors.gold, size: 20, ), ), const SizedBox(width: 12), Text( 'How to Support Her', style: GoogleFonts.outfit( fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.navyBlue, ), ), ], ), const SizedBox(height: 12), Text( _getSupportTip(phase), style: GoogleFonts.outfit( fontSize: 14, color: AppColors.charcoal, height: 1.5, ), ), ], ), ), const SizedBox(height: 20), // Recent Cravings (Dynamic) Builder( builder: (context) { // Get recent cravings from the last 3 days final allEntries = ref.read(cycleEntriesProvider); // Sort by date desc final sortedEntries = List.from(allEntries) ..sort((a, b) => b.date.compareTo(a.date)); final recentCravings = {}; final now = DateTime.now(); for (var entry in sortedEntries) { if (now.difference(entry.date).inDays > 3) break; if (entry.cravings != null) { recentCravings.addAll(entry.cravings!); } } if (recentCravings.isEmpty) return const SizedBox.shrink(); return Container( width: double.infinity, margin: const EdgeInsets.only(bottom: 20), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), border: Border.all(color: AppColors.rose.withOpacity(0.3)), boxShadow: [ BoxShadow( color: AppColors.rose.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( width: 36, height: 36, decoration: BoxDecoration( color: AppColors.rose.withOpacity(0.1), borderRadius: BorderRadius.circular(10), ), child: Icon( Icons.fastfood, color: AppColors.rose, size: 20, ), ), const SizedBox(width: 12), Text( 'She is Craving...', style: GoogleFonts.outfit( fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.navyBlue, ), ), ], ), const SizedBox(height: 12), Wrap( spacing: 8, runSpacing: 8, children: recentCravings .map((craving) => Chip( label: Text(craving), backgroundColor: AppColors.rose.withOpacity(0.1), labelStyle: GoogleFonts.outfit( color: AppColors.navyBlue, fontWeight: FontWeight.w500), side: BorderSide.none, )) .toList(), ), ], ), ); }, ), // Scripture for Husbands Container( width: double.infinity, padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppColors.gold.withOpacity(0.15), AppColors.warmCream, ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(16), border: Border.all( color: AppColors.gold.withOpacity(0.3), ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon( Icons.menu_book, color: AppColors.gold, size: 20, ), const SizedBox(width: 8), Expanded( child: Text( 'Scripture for Husbands', style: GoogleFonts.outfit( fontSize: 14, fontWeight: FontWeight.w500, color: AppColors.warmGray, ), ), ), // Quick version toggle GestureDetector( onTap: () => _showVersionPicker(context, ref), child: Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4), decoration: BoxDecoration( color: AppColors.gold.withOpacity(0.15), borderRadius: BorderRadius.circular(12), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Text( user?.bibleTranslation.label ?? 'ESV', style: GoogleFonts.outfit( fontSize: 11, fontWeight: FontWeight.w600, color: AppColors.gold, ), ), const SizedBox(width: 2), Icon(Icons.arrow_drop_down, color: AppColors.gold, size: 16), ], ), ), ), ], ), const SizedBox(height: 12), Text( '"${scripture.getVerse(user?.bibleTranslation ?? BibleTranslation.esv)}"', style: GoogleFonts.lora( fontSize: 15, fontStyle: FontStyle.italic, color: AppColors.navyBlue, height: 1.6, ), ), const SizedBox(height: 8), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '— ${scripture.reference}', style: GoogleFonts.outfit( fontSize: 12, fontWeight: FontWeight.w500, color: AppColors.warmGray, ), ), GestureDetector( onTap: _loadNewVerse, child: Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4), decoration: BoxDecoration( color: AppColors.gold.withOpacity(0.1), borderRadius: BorderRadius.circular(8), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.refresh, color: AppColors.gold, size: 14), const SizedBox(width: 4), Text( 'New Verse', style: GoogleFonts.outfit( fontSize: 11, fontWeight: FontWeight.w500, color: AppColors.gold, ), ), ], ), ), ), ], ), ], ), ), const SizedBox(height: 20), // Prayer Button SizedBox( width: double.infinity, child: OutlinedButton.icon( onPressed: () => _showPrayerPrompt(context, phase), icon: const Text('🙏', style: TextStyle(fontSize: 18)), label: Text( 'Pray for ${wifeName}', style: GoogleFonts.outfit(fontWeight: FontWeight.w500), ), style: OutlinedButton.styleFrom( foregroundColor: AppColors.navyBlue, side: const BorderSide(color: AppColors.navyBlue), padding: const EdgeInsets.symmetric(vertical: 14), ), ), ), const SizedBox(height: 40), ], ), ), ); } String _getPhaseHint(CyclePhase phase) { switch (phase) { case CyclePhase.menstrual: return 'She may need extra rest'; case CyclePhase.follicular: return 'Energy is returning'; case CyclePhase.ovulation: return 'Fertile window'; case CyclePhase.luteal: return 'PMS may occur'; } } String _getSupportTip(CyclePhase phase) { switch (phase) { case CyclePhase.menstrual: return 'This is a time when she needs extra care. Help with household tasks without being asked. ' 'Bring her favorite warm drink, suggest low-key activities, and be extra patient.'; case CyclePhase.follicular: return 'Her energy is returning! This is a great time to plan dates, work on projects together, ' 'and affirm her strengths. She may be more talkative and social.'; case CyclePhase.ovulation: return 'Prioritize connection time. Romance and quality time matter. ' 'If you\'re trying to conceive, this is your fertile window.'; case CyclePhase.luteal: return 'Be patient—PMS may affect her mood. Listen more, "fix" less. ' 'Take initiative on responsibilities and surprise her with comfort foods.'; } } void _showVersionPicker(BuildContext context, WidgetRef ref) { showModalBottomSheet( context: context, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), builder: (context) => Container( padding: const EdgeInsets.all(20), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Choose Translation', style: GoogleFonts.outfit( fontSize: 20, fontWeight: FontWeight.w600, color: AppColors.navyBlue, ), ), const SizedBox(height: 16), ...BibleTranslation.values.map((translation) => ListTile( title: Text( translation.label, style: GoogleFonts.outfit(fontWeight: FontWeight.w500), ), trailing: ref.watch(userProfileProvider)?.bibleTranslation == translation ? const Icon(Icons.check, color: AppColors.sageGreen) : null, onTap: () async { final profile = ref.read(userProfileProvider); if (profile != null) { await ref .read(userProfileProvider.notifier) .updateProfile( profile.copyWith(bibleTranslation: translation), ); } if (context.mounted) Navigator.pop(context); }, )), ], ), ), ); } void _showPrayerPrompt(BuildContext context, CyclePhase phase) { showModalBottomSheet( context: context, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), builder: (context) => Container( padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( '🙏 Prayer for Your Wife', style: GoogleFonts.outfit( fontSize: 20, fontWeight: FontWeight.w600, color: AppColors.navyBlue, ), ), const SizedBox(height: 20), Text( _getPrayer(phase), textAlign: TextAlign.center, style: GoogleFonts.lora( fontSize: 16, fontStyle: FontStyle.italic, color: AppColors.charcoal, height: 1.6, ), ), const SizedBox(height: 24), SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () => Navigator.pop(context), style: ElevatedButton.styleFrom( backgroundColor: AppColors.navyBlue, foregroundColor: Colors.white, ), child: const Text('Amen'), ), ), const SizedBox(height: 12), SizedBox( width: double.infinity, child: TextButton.icon( onPressed: () { final user = ref.read(userProfileProvider); NotificationService().showPartnerUpdateNotification( title: 'Your husband prayed for you!', body: '${user?.name ?? 'He'} just finished praying for you during her ${phase.label.toLowerCase()} phase.', ); Navigator.pop(context); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Sent to wife!')), ); }, icon: const Icon(Icons.share, size: 18), label: const Text('Share with Wife'), style: TextButton.styleFrom( foregroundColor: AppColors.navyBlue, ), ), ), const SizedBox(height: 16), ], ), ), ); } String _getPrayer(CyclePhase phase) { switch (phase) { case CyclePhase.menstrual: return '"Lord, I lift up my wife during this time of rest. ' 'Give her body the renewal it needs and grant her Your peace. ' 'Help me to serve her with patience and love. Amen."'; case CyclePhase.follicular: return '"Father, thank You for my wife\'s renewed energy. ' 'Bless her endeavors and help me to encourage and support her. ' 'May our partnership glorify You. Amen."'; case CyclePhase.ovulation: return '"Creator God, You have designed my wife fearfully and wonderfully. ' 'Whatever Your plans for our family, help us trust Your timing. ' 'Bless our marriage and intimacy. Amen."'; case CyclePhase.luteal: return '"Lord, be near to my wife during this phase. ' 'When emotions are difficult, grant her Your peace that passes understanding. ' 'Help me to be patient, kind, and understanding. Amen."'; } } } class _HusbandTipsScreen extends StatelessWidget { const _HusbandTipsScreen(); @override Widget build(BuildContext context) { return SafeArea( child: SingleChildScrollView( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Supporting Her', style: GoogleFonts.outfit( fontSize: 28, fontWeight: FontWeight.w600, color: AppColors.navyBlue, ), ), const SizedBox(height: 8), Text( 'Practical ways to love your wife well', style: GoogleFonts.outfit( fontSize: 14, color: AppColors.warmGray, ), ), const SizedBox(height: 24), _buildTipCategory('During Her Period', [ '🏠 Help with household tasks without being asked', '🍵 Bring her favorite comfort drink', '📺 Suggest low-key activities (movies, quiet time)', '🙏 Pray for her physical comfort', ]), const SizedBox(height: 16), // Period Supplies (Dynamic) Consumer( builder: (context, ref, child) { final user = ref.watch(userProfileProvider); if (user == null || !user.isPadTrackingEnabled) return const SizedBox.shrink(); final brand = user.padBrand ?? 'Not specified'; final flow = user.typicalFlowIntensity; return Column( children: [ Container( width: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColors.menstrualPhase.withOpacity(0.15), borderRadius: BorderRadius.circular(16), border: Border.all( color: AppColors.menstrualPhase.withOpacity(0.3)), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), ), child: const Icon(Icons.shopping_bag_outlined, color: AppColors.menstrualPhase, size: 20), ), const SizedBox(width: 12), Text( 'Period Supplies', style: GoogleFonts.outfit( fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.navyBlue, ), ), ], ), const SizedBox(height: 12), Text( 'She uses:', style: GoogleFonts.outfit( fontSize: 14, color: AppColors.warmGray), ), const SizedBox(height: 4), Text( brand, style: GoogleFonts.outfit( fontSize: 18, fontWeight: FontWeight.bold, color: AppColors.navyBlue), ), if (flow != null) ...[ const SizedBox(height: 8), Text( 'Typical Flow: $flow/5', style: GoogleFonts.outfit( fontSize: 14, color: AppColors.charcoal), ), ], if (user.padAbsorbency != null) ...[ const SizedBox(height: 4), Text( 'Absorbency: ${user.padAbsorbency}/5', style: GoogleFonts.outfit( fontSize: 14, color: AppColors.charcoal), ), ], // Low Stock Warning if (user.padInventoryCount <= user.lowInventoryThreshold) ...[ const SizedBox(height: 12), Container( width: double.infinity, padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: AppColors.rose.withOpacity(0.1), borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColors.rose), ), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.warning_amber_rounded, color: AppColors.rose, size: 20), const SizedBox(width: 8), Text( 'LOW STOCK! (${user.padInventoryCount} left)', style: GoogleFonts.outfit( fontSize: 14, fontWeight: FontWeight.bold, color: AppColors.rose), ), ], ), const SizedBox(height: 4), GestureDetector( onTap: () { // Navigate to settings final parentState = context.findAncestorStateOfType< _HusbandHomeScreenState>(); if (parentState != null) { parentState.setState(() { parentState._selectedIndex = 5; // Settings tab }); } }, child: Text( 'Check Settings to Sync', style: GoogleFonts.outfit( fontSize: 12, decoration: TextDecoration.underline, color: AppColors.rose, ), ), ), ], ), ), ], ], ), ), const SizedBox(height: 16), ], ); }, ), _buildTipCategory('Follicular Phase', [ '🎉 Plan dates or activities—her energy is returning', '💬 She may be more talkative and social', '💪 Great time for projects together', '❤️ Affirm her strengths and beauty', ]), const SizedBox(height: 16), _buildTipCategory('Luteal Phase (PMS)', [ '😌 Be patient—PMS may affect her mood', '🍫 Surprise with comfort foods', '🧹 Take initiative on responsibilities', '👂 Listen more, "fix" less', ]), const SizedBox(height: 16), const SizedBox(height: 16), // Her Favorites Section Consumer( builder: (context, ref, child) { final user = ref.watch(userProfileProvider); final favorites = user?.favoriteFoods; if (favorites == null || favorites.isEmpty) return const SizedBox.shrink(); return Column( children: [ _buildTipCategory( '❤️ Her Favorites (Cheat Sheet)', favorites), const SizedBox(height: 16), ], ); }, ), _buildTipCategory('General Wisdom', [ '🗣️ Ask how she\'s feeling—and actually listen', '📱 Put your phone down when she\'s talking', '🌹 Small gestures matter more than grand ones', '🙏 Pray for her daily', ]), const SizedBox(height: 16), _buildTipCategory("Men's Health", [ '💪 Exercise regularly to boost energy and mood', '🥗 Eat a balanced diet rich in protein and vegetables', '😴 Prioritize 7-8 hours of sleep for recovery', '💧 Stay hydrated throughout the day', '🧠 Practice stress management techniques', ]), ], ), ), ); } Widget _buildTipCategory(String title, List tips) { return Container( width: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: GoogleFonts.outfit( fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.navyBlue, ), ), const SizedBox(height: 12), ...tips.map((tip) => Padding( padding: const EdgeInsets.only(bottom: 8), child: Text( tip, style: GoogleFonts.outfit( fontSize: 14, color: AppColors.charcoal, height: 1.4, ), ), )), ], ), ); } } class _HusbandLearnScreen extends StatelessWidget { const _HusbandLearnScreen(); @override Widget build(BuildContext context) { return SafeArea( child: SingleChildScrollView( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Learn', style: GoogleFonts.outfit( fontSize: 28, fontWeight: FontWeight.w600, color: AppColors.navyBlue, ), ), const SizedBox(height: 24), _buildSection(context, 'Understanding Her', [ _LearnItem( icon: Icons.loop, title: 'The 4 Phases of Her Cycle', subtitle: 'What\'s happening in her body each month', articleId: 'four_phases', ), _LearnItem( icon: Icons.psychology_outlined, title: 'Why Does Her Mood Change?', subtitle: 'Hormones explained simply', articleId: 'mood_changes', ), _LearnItem( icon: Icons.medical_information_outlined, title: 'PMS is Real', subtitle: 'Medical facts for supportive husbands', articleId: 'pms_is_real', ), ]), const SizedBox(height: 24), _buildSection(context, 'Biblical Manhood', [ _LearnItem( icon: Icons.favorite, title: 'Loving Like Christ', subtitle: 'Ephesians 5 in daily practice', articleId: 'loving_like_christ', ), _LearnItem( icon: Icons.handshake, title: 'Servant Leadership at Home', subtitle: 'What it really means', articleId: 'servant_leadership', ), _LearnItem( icon: Icons.auto_awesome, title: 'Praying for Your Wife', subtitle: 'Practical guide', articleId: 'praying_for_wife', ), ]), const SizedBox(height: 24), _buildSection(context, 'NFP for Husbands', [ _LearnItem( icon: Icons.show_chart, title: 'Reading the Charts Together', subtitle: 'Understanding fertility signs', articleId: 'reading_charts', ), _LearnItem( icon: Icons.schedule, title: 'Abstinence as Spiritual Discipline', subtitle: 'Growing together during fertile days', articleId: 'abstinence_discipline', ), ]), ], ), ), ); } Widget _buildSection( BuildContext context, String title, List<_LearnItem> items) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: GoogleFonts.outfit( fontSize: 14, fontWeight: FontWeight.w500, color: AppColors.warmGray, letterSpacing: 0.5, ), ), const SizedBox(height: 8), Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), ), child: Column( children: items .map((item) => ListTile( leading: Container( width: 40, height: 40, decoration: BoxDecoration( color: AppColors.navyBlue.withOpacity(0.1), borderRadius: BorderRadius.circular(10), ), child: Icon( item.icon, color: AppColors.navyBlue, size: 20, ), ), title: Text( item.title, style: GoogleFonts.outfit( fontSize: 15, fontWeight: FontWeight.w500, color: AppColors.charcoal, ), ), subtitle: Text( item.subtitle, style: GoogleFonts.outfit( fontSize: 13, color: AppColors.warmGray, ), ), trailing: const Icon( Icons.chevron_right, color: AppColors.lightGray, ), onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => LearnArticleScreen(articleId: item.articleId), ), ); }, )) .toList(), ), ), ], ); } } class _LearnItem { final IconData icon; final String title; final String subtitle; final String articleId; const _LearnItem({ required this.icon, required this.title, required this.subtitle, required this.articleId, }); } class _HusbandSettingsScreen extends ConsumerWidget { const _HusbandSettingsScreen(); Future _resetApp(BuildContext context, WidgetRef ref) async { final confirmed = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Reset App?'), content: const Text( 'This will clear all data and return you to onboarding. Are you sure?'), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('Cancel')), TextButton( onPressed: () => Navigator.pop(context, true), child: const Text('Reset', style: TextStyle(color: Colors.red)), ), ], ), ); if (confirmed == true) { await ref.read(userProfileProvider.notifier).clearProfile(); await ref.read(cycleEntriesProvider.notifier).clearEntries(); if (context.mounted) { Navigator.of(context).pushNamedAndRemoveUntil('/', (route) => false); } } } Future _loadDemoData(BuildContext context, WidgetRef ref) async { final confirmed = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Load Demo Data?'), content: const Text( 'This will populate the app with mock cycle entries and a wife profile.'), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('Cancel')), TextButton( onPressed: () => Navigator.pop(context, true), child: const Text('Load Data', style: TextStyle(color: Colors.blue)), ), ], ), ); if (confirmed == true) { final mockService = MockDataService(); // Load mock entries final entries = mockService.generateMockCycleEntries(); for (var entry in entries) { await ref.read(cycleEntriesProvider.notifier).addEntry(entry); } // Update mock profile final mockWife = mockService.generateMockWifeProfile(); // Need to preserve current Husband ID and Role but take other data final currentProfile = ref.read(userProfileProvider); if (currentProfile != null) { final updatedProfile = currentProfile.copyWith( partnerName: mockWife.name, averageCycleLength: mockWife.averageCycleLength, averagePeriodLength: mockWife.averagePeriodLength, lastPeriodStartDate: mockWife.lastPeriodStartDate, favoriteFoods: mockWife.favoriteFoods, ); await ref .read(userProfileProvider.notifier) .updateProfile(updatedProfile); } } } void _showTranslationPicker(BuildContext context, WidgetRef ref) { showModalBottomSheet( context: context, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), builder: (context) => Container( padding: const EdgeInsets.all(20), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Choose Translation', style: GoogleFonts.outfit( fontSize: 20, fontWeight: FontWeight.w600, color: AppColors.navyBlue, ), ), const SizedBox(height: 16), ...BibleTranslation.values.map((translation) => ListTile( title: Text( translation.label, style: GoogleFonts.outfit(fontWeight: FontWeight.w500), ), trailing: ref.watch(userProfileProvider)?.bibleTranslation == translation ? const Icon(Icons.check, color: AppColors.sageGreen) : null, onTap: () async { final profile = ref.read(userProfileProvider); if (profile != null) { await ref .read(userProfileProvider.notifier) .updateProfile( profile.copyWith(bibleTranslation: translation), ); } if (context.mounted) Navigator.pop(context); }, )), ], ), ), ); } void _showConnectDialog(BuildContext context, WidgetRef ref) { final codeController = TextEditingController(); bool shareDevotional = true; showDialog( context: context, builder: (context) => StatefulBuilder( builder: (context, setState) => AlertDialog( title: Row( children: [ const Icon(Icons.link, color: AppColors.navyBlue), const SizedBox(width: 8), const Text('Connect with Wife'), ], ), content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Enter the pairing code from your wife\'s app:', style: GoogleFonts.outfit(fontSize: 14, color: AppColors.warmGray), ), const SizedBox(height: 16), TextField( controller: codeController, decoration: const InputDecoration( hintText: 'e.g., ABC123', border: OutlineInputBorder(), ), textCapitalization: TextCapitalization.characters, ), const SizedBox(height: 16), Text( 'Your wife can find this code in her Settings under "Share with Husband".', style: GoogleFonts.outfit(fontSize: 12, color: AppColors.warmGray), ), const SizedBox(height: 24), Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( height: 24, width: 24, child: Checkbox( value: shareDevotional, onChanged: (val) => setState(() => shareDevotional = val ?? true), activeColor: AppColors.navyBlue, ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Share Devotional Plans', style: GoogleFonts.outfit( fontWeight: FontWeight.bold, fontSize: 14, color: AppColors.charcoal), ), Text( 'Allow her to see the teaching plans you create.', style: GoogleFonts.outfit( fontSize: 12, color: AppColors.warmGray), ), ], ), ), ], ), ], ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('Cancel'), ), ElevatedButton( onPressed: () async { final code = codeController.text.trim(); Navigator.pop(context); // Update preference final user = ref.read(userProfileProvider); if (user != null) { final updatedProfile = user.copyWith(isDataShared: shareDevotional); await ref .read(userProfileProvider.notifier) .updateProfile(updatedProfile); } ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Settings updated & Connected!'), backgroundColor: AppColors.sageGreen, ), ); if (code.isNotEmpty) { // Load demo data as simulation final mockService = MockDataService(); final entries = mockService.generateMockCycleEntries(); for (var entry in entries) { await ref .read(cycleEntriesProvider.notifier) .addEntry(entry); } final mockWife = mockService.generateMockWifeProfile(); final currentProfile = ref.read(userProfileProvider); if (currentProfile != null) { final updatedProfile = currentProfile.copyWith( isDataShared: shareDevotional, partnerName: mockWife.name, averageCycleLength: mockWife.averageCycleLength, averagePeriodLength: mockWife.averagePeriodLength, lastPeriodStartDate: mockWife.lastPeriodStartDate, favoriteFoods: mockWife.favoriteFoods, ); await ref .read(userProfileProvider.notifier) .updateProfile(updatedProfile); } } }, style: ElevatedButton.styleFrom( backgroundColor: AppColors.navyBlue, foregroundColor: Colors.white, ), child: const Text('Connect'), ), ], ), ), ); } @override Widget build(BuildContext context, WidgetRef ref) { return SafeArea( child: SingleChildScrollView( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Settings', style: GoogleFonts.outfit( fontSize: 28, fontWeight: FontWeight.w600, color: AppColors.navyBlue, ), ), const SizedBox(height: 24), Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), ), child: Column( children: [ ListTile( leading: const Icon(Icons.notifications_outlined, color: AppColors.navyBlue), title: Text('Notifications', style: GoogleFonts.outfit(fontWeight: FontWeight.w500)), trailing: Switch(value: true, onChanged: (val) {}), ), const Divider(height: 1), ListTile( leading: const Icon(Icons.link, color: AppColors.navyBlue), title: Text('Connect with Wife', style: GoogleFonts.outfit(fontWeight: FontWeight.w500)), trailing: const Icon(Icons.chevron_right), onTap: () => _showConnectDialog(context, ref), ), const Divider(height: 1), ListTile( leading: const Icon(Icons.menu_book_outlined, color: AppColors.navyBlue), title: Text('Bible Translation', style: GoogleFonts.outfit(fontWeight: FontWeight.w500)), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ Text( ref.watch(userProfileProvider .select((u) => u?.bibleTranslation.label)) ?? 'ESV', style: GoogleFonts.outfit( fontSize: 14, color: AppColors.warmGray, ), ), const Icon(Icons.chevron_right), ], ), onTap: () => _showTranslationPicker(context, ref), ), const Divider(height: 1), ListTile( leading: const Icon(Icons.palette_outlined, color: AppColors.navyBlue), title: Text('Appearance', style: GoogleFonts.outfit(fontWeight: FontWeight.w500)), trailing: const Icon(Icons.chevron_right), onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => const HusbandAppearanceScreen(), ), ); }, ), ], ), ), const SizedBox(height: 20), Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), ), child: Column( children: [ ListTile( leading: const Icon(Icons.cloud_download_outlined, color: Colors.blue), title: Text('Load Demo Data', style: GoogleFonts.outfit( fontWeight: FontWeight.w500, color: Colors.blue)), onTap: () => _loadDemoData(context, ref), ), const Divider(height: 1), ListTile( leading: const Icon(Icons.logout, color: Colors.red), title: Text('Reset App', style: GoogleFonts.outfit( fontWeight: FontWeight.w500, color: Colors.red)), onTap: () => _resetApp(context, ref), ), ], ), ), ], ), ), ); } } class _HusbandWifeStatus extends ConsumerWidget { const _HusbandWifeStatus(); @override Widget build(BuildContext context, WidgetRef ref) { final user = ref.watch(userProfileProvider); final cycleInfo = ref.watch(currentCycleInfoProvider); final entries = ref.watch(cycleEntriesProvider); final wifeName = user?.partnerName ?? "Wife"; final phase = cycleInfo.phase; final dayOfCycle = cycleInfo.dayOfCycle; // Find today's entry final todayEntry = entries.firstWhere( (e) => DateUtils.isSameDay(e.date, DateTime.now()), orElse: () => CycleEntry( id: '', date: DateTime.now(), createdAt: DateTime.now(), updatedAt: DateTime.now(), ), ); return SafeArea( child: SingleChildScrollView( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Wife\'s Status', style: GoogleFonts.outfit( fontSize: 28, fontWeight: FontWeight.w600, color: AppColors.navyBlue, ), ), const SizedBox(height: 8), Text( 'Real-time updates on how $wifeName is doing', style: GoogleFonts.outfit( fontSize: 14, color: AppColors.warmGray, ), ), const SizedBox(height: 24), // Phase and Day summary Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: AppColors.navyBlue.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: Row( children: [ _buildStatusCircle(dayOfCycle, phase), const SizedBox(width: 20), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( phase.label, style: GoogleFonts.outfit( fontSize: 20, fontWeight: FontWeight.w600, color: AppColors.navyBlue, ), ), Text( 'Cycle Day $dayOfCycle', style: GoogleFonts.outfit( fontSize: 14, color: AppColors.warmGray, ), ), const SizedBox(height: 8), Text( phase.description, style: GoogleFonts.outfit( fontSize: 13, color: AppColors.charcoal.withOpacity(0.8), ), ), ], ), ), ], ), ), const SizedBox(height: 24), // Symptoms for Today if (todayEntry.hasSymptoms || todayEntry.mood != null) ...[ Text( 'Today\'s Logs', style: GoogleFonts.outfit( fontSize: 18, fontWeight: FontWeight.w600, color: AppColors.navyBlue, ), ), const SizedBox(height: 12), Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColors.navyBlue.withOpacity(0.03), borderRadius: BorderRadius.circular(16), border: Border.all(color: AppColors.navyBlue.withOpacity(0.05)), ), child: Column( children: [ if (todayEntry.mood != null) _buildLogTile(Icons.emoji_emotions_outlined, 'Mood', '${todayEntry.mood!.emoji} ${todayEntry.mood!.label}'), if (todayEntry.hasSymptoms) _buildLogTile(Icons.healing_outlined, 'Symptoms', _getSymptomsSummary(todayEntry)), if (todayEntry.energyLevel != null) _buildLogTile(Icons.flash_on, 'Energy', '${todayEntry.energyLevel}/5'), ], ), ), const SizedBox(height: 24), ], // Support Checklist Text( 'Support Checklist', style: GoogleFonts.outfit( fontSize: 18, fontWeight: FontWeight.w600, color: AppColors.navyBlue, ), ), const SizedBox(height: 12), ..._generateChecklist(todayEntry, phase) .map((item) => _buildCheckItem(item)), const SizedBox(height: 40), ], ), ), ); } Widget _buildStatusCircle(int day, CyclePhase phase) { return Container( width: 70, height: 70, decoration: BoxDecoration( color: phase.color.withOpacity(0.15), shape: BoxShape.circle, border: Border.all(color: phase.color.withOpacity(0.3), width: 2), ), child: Center( child: Text( day.toString(), style: GoogleFonts.outfit( fontSize: 24, fontWeight: FontWeight.w700, color: phase.color, ), ), ), ); } Widget _buildLogTile(IconData icon, String label, String value) { return Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: Row( children: [ Icon(icon, size: 20, color: AppColors.steelBlue), const SizedBox(width: 12), Text( '$label: ', style: GoogleFonts.outfit(fontWeight: FontWeight.w500, fontSize: 14), ), Expanded( child: Text( value, style: GoogleFonts.outfit(fontSize: 14, color: AppColors.charcoal), ), ), ], ), ); } Widget _buildCheckItem(String text) { return Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColors.navyBlue.withOpacity(0.05)), ), child: Row( children: [ Icon(Icons.check_circle_outline, color: AppColors.sageGreen, size: 20), const SizedBox(width: 12), Expanded( child: Text( text, style: GoogleFonts.outfit(fontSize: 14, color: AppColors.navyBlue), ), ), ], ), ); } String _getSymptomsSummary(CycleEntry entry) { List s = []; if (entry.crampIntensity != null && entry.crampIntensity! > 0) s.add('Cramps'); if (entry.hasHeadache) s.add('Headache'); if (entry.hasBloating) s.add('Bloating'); if (entry.hasFatigue) s.add('Fatigue'); if (entry.hasLowerBackPain) s.add('Back Pain'); return s.isNotEmpty ? s.join(', ') : 'None'; } List _generateChecklist(CycleEntry entry, CyclePhase phase) { List list = []; // Symptom-based tips if (entry.crampIntensity != null && entry.crampIntensity! >= 3) { list.add('Bring her a heating pad or hot water bottle.'); } if (entry.hasHeadache) { list.add('Suggest some quiet time with dimmed lights.'); } if (entry.hasFatigue || (entry.energyLevel != null && entry.energyLevel! <= 2)) { list.add('Take over dinner or household chores tonight.'); } if (entry.mood == MoodLevel.sad || entry.mood == MoodLevel.verySad) { list.add('Offer a listening ear and extra comfort.'); } // Phase-based fallback tips if (list.length < 3) { switch (phase) { case CyclePhase.menstrual: list.add('Suggest a relaxing movie night.'); list.add('Bring her a warm tea or cocoa.'); break; case CyclePhase.follicular: list.add('Plan a fun outdoor activity.'); list.add('Compliment her renewed energy.'); break; case CyclePhase.ovulation: list.add('Plan a romantic date night.'); list.add('Focus on quality connection time.'); break; case CyclePhase.luteal: list.add('Surprise her with her favorite comfort snack.'); list.add('Be extra patient if she\'s easily frustrated.'); break; } } return list.take(4).toList(); } }