Files
Tracker/lib/screens/husband/husband_home_screen.dart
2025-12-19 22:47:27 -06:00

1119 lines
37 KiB
Dart

import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import '../../theme/app_theme.dart';
import '../../models/cycle_entry.dart';
import '../../models/scripture.dart';
import '../../providers/user_provider.dart';
import '../../services/cycle_service.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
/// Husband's companion app main screen
class HusbandHomeScreen extends ConsumerStatefulWidget {
const HusbandHomeScreen({super.key});
@override
ConsumerState<HusbandHomeScreen> createState() => _HusbandHomeScreenState();
}
class _HusbandHomeScreenState extends ConsumerState<HusbandHomeScreen> {
int _selectedIndex = 0;
@override
Widget build(BuildContext context) {
return Theme(
data: _husbandTheme,
child: Scaffold(
backgroundColor: AppColors.warmCream,
body: IndexedStack(
index: _selectedIndex,
children: [
const _HusbandDashboard(),
<<<<<<< HEAD
=======
const _HusbandWifeStatus(),
>>>>>>> 6742220 (Your commit message here)
const _HusbandTipsScreen(),
const _HusbandLearnScreen(),
const _HusbandSettingsScreen(),
],
),
bottomNavigationBar: Container(
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: AppColors.navyBlue.withOpacity(0.1),
blurRadius: 10,
offset: const Offset(0, -2),
),
],
),
child: BottomNavigationBar(
currentIndex: _selectedIndex,
onTap: (index) => setState(() => _selectedIndex = index),
backgroundColor: Colors.white,
selectedItemColor: AppColors.navyBlue,
unselectedItemColor: AppColors.warmGray,
type: BottomNavigationBarType.fixed,
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home_outlined),
activeIcon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
<<<<<<< HEAD
=======
icon: Icon(Icons.favorite_border),
activeIcon: Icon(Icons.favorite),
label: 'Status',
),
BottomNavigationBarItem(
>>>>>>> 6742220 (Your commit message here)
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 {
return ThemeData(
useMaterial3: true,
brightness: Brightness.light,
scaffoldBackgroundColor: AppColors.warmCream,
colorScheme: const ColorScheme.light(
primary: AppColors.navyBlue,
secondary: AppColors.gold,
surface: AppColors.warmCream,
),
appBarTheme: AppBarTheme(
backgroundColor: AppColors.warmCream,
foregroundColor: AppColors.navyBlue,
elevation: 0,
titleTextStyle: GoogleFonts.outfit(
fontSize: 20,
fontWeight: FontWeight.w600,
color: AppColors.navyBlue,
),
),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.navyBlue,
foregroundColor: Colors.white,
),
),
);
}
}
class _HusbandDashboard extends ConsumerWidget {
const _HusbandDashboard();
@override
Widget build(BuildContext context, WidgetRef ref) {
final user = ref.watch(userProfileProvider);
final cycleInfo = ref.watch(currentCycleInfoProvider);
final wifeName = user?.partnerName ?? "Wife";
final phase = cycleInfo['phase'] as CyclePhase;
final dayOfCycle = cycleInfo['dayOfCycle'] as int;
final daysUntilPeriod = cycleInfo['daysUntilPeriod'] as int;
final scripture = 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),
// 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),
Text(
'Scripture for Husbands',
style: GoogleFonts.outfit(
fontSize: 14,
fontWeight: FontWeight.w500,
color: AppColors.warmGray,
),
),
],
),
const SizedBox(height: 12),
Text(
'"${scripture.verse}"',
style: GoogleFonts.lora(
fontSize: 15,
fontStyle: FontStyle.italic,
color: AppColors.navyBlue,
height: 1.6,
),
),
const SizedBox(height: 8),
Text(
'${scripture.reference}',
style: GoogleFonts.outfit(
fontSize: 12,
fontWeight: FontWeight.w500,
color: AppColors.warmGray,
),
),
],
),
),
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 _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: 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),
_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),
_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',
]),
],
),
),
);
}
Widget _buildTipCategory(String title, List<String> 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('Understanding Her', [
_LearnItem(
icon: Icons.loop,
title: 'The 4 Phases of Her Cycle',
subtitle: 'What\'s happening in her body each month',
),
_LearnItem(
icon: Icons.psychology_outlined,
title: 'Why Does Her Mood Change?',
subtitle: 'Hormones explained simply',
),
_LearnItem(
icon: Icons.medical_information_outlined,
title: 'PMS is Real',
subtitle: 'Medical facts for supportive husbands',
),
]),
const SizedBox(height: 24),
_buildSection('Biblical Manhood', [
_LearnItem(
icon: Icons.favorite,
title: 'Loving Like Christ',
subtitle: 'Ephesians 5 in daily practice',
),
_LearnItem(
icon: Icons.handshake,
title: 'Servant Leadership at Home',
subtitle: 'What it really means',
),
_LearnItem(
icon: Icons.auto_awesome,
title: 'Praying for Your Wife',
subtitle: 'Practical guide',
),
]),
const SizedBox(height: 24),
_buildSection('NFP for Husbands', [
_LearnItem(
icon: Icons.show_chart,
title: 'Reading the Charts Together',
subtitle: 'Understanding fertility signs',
),
_LearnItem(
icon: Icons.schedule,
title: 'Abstinence as Spiritual Discipline',
subtitle: 'Growing together during fertile days',
),
]),
],
),
),
);
}
Widget _buildSection(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: () {},
))
.toList(),
),
),
],
);
}
}
class _LearnItem {
final IconData icon;
final String title;
final String subtitle;
const _LearnItem({
required this.icon,
required this.title,
required this.subtitle,
});
}
class _HusbandSettingsScreen extends ConsumerWidget {
const _HusbandSettingsScreen();
Future<void> _resetApp(BuildContext context, WidgetRef ref) async {
final confirmed = await showDialog<bool>(
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);
}
}
}
@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),
title: Text('Notifications', style: GoogleFonts.outfit()),
trailing: const Icon(Icons.chevron_right),
onTap: () {},
),
ListTile(
leading: const Icon(Icons.link_outlined),
title: Text('Connection', style: GoogleFonts.outfit()),
subtitle: Text('Linked with wife\'s app', style: GoogleFonts.outfit(fontSize: 12)),
trailing: const Icon(Icons.chevron_right),
onTap: () {},
),
ListTile(
leading: const Icon(Icons.logout),
title: Text('Reset App / Logout', style: GoogleFonts.outfit()),
trailing: const Icon(Icons.chevron_right),
onTap: () => _resetApp(context, ref),
),
ListTile(
leading: const Icon(Icons.help_outline),
title: Text('Help & Support', style: GoogleFonts.outfit()),
trailing: const Icon(Icons.chevron_right),
onTap: () {},
),
],
),
),
],
),
),
);
}
}
<<<<<<< HEAD
=======
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'] as CyclePhase;
final dayOfCycle = cycleInfo['dayOfCycle'] as int;
// 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<String> 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<String> _generateChecklist(CycleEntry entry, CyclePhase phase) {
List<String> 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();
}
}
>>>>>>> 6742220 (Your commit message here)