Implement initial features for husband's companion app, including mock data service and husband notes screen. Refactor scripture and cycle services for improved stability and testability. Address iOS Safari web app startup issue by removing deprecated initialization. - Implemented MockDataService and HusbandNotesScreen. - Converted _DashboardTab and DevotionalScreen to StatefulWidgets for robust scripture provider initialization. - Refactored CycleService to use immutable CycleInfo class, reducing UI rebuilds. - Removed deprecated window.flutterConfiguration from index.html, resolving Flutter web app startup failure on iOS Safari. - Updated and fixed related tests.
234 lines
7.7 KiB
Dart
234 lines
7.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:google_fonts/google_fonts.dart';
|
|
import '../theme/app_theme.dart';
|
|
import '../models/cycle_entry.dart';
|
|
|
|
class TipCard extends StatelessWidget {
|
|
final CyclePhase phase;
|
|
final bool isMarried;
|
|
|
|
const TipCard({
|
|
super.key,
|
|
required this.phase,
|
|
required this.isMarried,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final theme = Theme.of(context);
|
|
final isDark = theme.brightness == Brightness.dark;
|
|
final tip = _getTipForPhase(phase, isMarried);
|
|
|
|
return Container(
|
|
width: double.infinity,
|
|
padding: const EdgeInsets.all(16),
|
|
decoration: BoxDecoration(
|
|
color: theme.cardColor,
|
|
borderRadius: BorderRadius.circular(16),
|
|
border:
|
|
isDark ? Border.all(color: Colors.white.withOpacity(0.05)) : null,
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: (isDark ? Colors.black : AppColors.charcoal)
|
|
.withOpacity(0.05),
|
|
blurRadius: 10,
|
|
offset: const Offset(0, 4),
|
|
),
|
|
],
|
|
),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
width: 40,
|
|
height: 40,
|
|
decoration: BoxDecoration(
|
|
color: AppColors.sageGreen.withOpacity(isDark ? 0.2 : 0.15),
|
|
borderRadius: BorderRadius.circular(10),
|
|
),
|
|
child: const Icon(
|
|
Icons.lightbulb_outline,
|
|
color: AppColors.sageGreen,
|
|
size: 22,
|
|
),
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'Today\'s Tip',
|
|
style: theme.textTheme.titleMedium?.copyWith(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
const SizedBox(height: 4),
|
|
Text(
|
|
tip,
|
|
style: theme.textTheme.bodyMedium?.copyWith(
|
|
fontSize: 13,
|
|
height: 1.4,
|
|
),
|
|
),
|
|
const SizedBox(height: 12),
|
|
InkWell(
|
|
onTap: () => _showDetailedInsights(context),
|
|
child: Row(
|
|
children: [
|
|
Text(
|
|
'Learn More',
|
|
style: GoogleFonts.outfit(
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w600,
|
|
color: AppColors.sageGreen,
|
|
),
|
|
),
|
|
const SizedBox(width: 4),
|
|
const Icon(
|
|
Icons.arrow_forward_ios,
|
|
size: 10,
|
|
color: AppColors.sageGreen,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
void _showDetailedInsights(BuildContext context) {
|
|
final details = _getDetailsForPhase(phase);
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
|
title: Column(
|
|
children: [
|
|
Text(
|
|
'Phase Insight: ${phase.label}',
|
|
textAlign: TextAlign.center,
|
|
style: GoogleFonts.outfit(fontWeight: FontWeight.w600),
|
|
),
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
phase.emoji,
|
|
style: const TextStyle(fontSize: 32),
|
|
),
|
|
],
|
|
),
|
|
content: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
_buildDetailSection(
|
|
'Nutrition', details['nutrition']!, Icons.restaurant),
|
|
const SizedBox(height: 16),
|
|
_buildDetailSection(
|
|
'Movement', details['movement']!, Icons.fitness_center),
|
|
const SizedBox(height: 16),
|
|
Text(
|
|
'Note: While these are general trends, your body is unique. Always listen to your own energy levels.',
|
|
style: GoogleFonts.outfit(
|
|
fontSize: 11,
|
|
fontStyle: FontStyle.italic,
|
|
color: AppColors.warmGray,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.pop(context),
|
|
child: Text('Got it',
|
|
style: GoogleFonts.outfit(color: AppColors.sageGreen)),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildDetailSection(String title, String content, IconData icon) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Icon(icon, size: 16, color: AppColors.sageGreen),
|
|
const SizedBox(width: 6),
|
|
Text(
|
|
title,
|
|
style: GoogleFonts.outfit(
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 14,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 6),
|
|
Text(
|
|
content,
|
|
style: GoogleFonts.outfit(
|
|
fontSize: 13,
|
|
color: AppColors.charcoal,
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
String _getTipForPhase(CyclePhase phase, bool isMarried) {
|
|
switch (phase) {
|
|
case CyclePhase.menstrual:
|
|
return 'Focus on iron-rich foods and gentle rest. Your body is working hard; honor it with hydration and Vitamin C.';
|
|
case CyclePhase.follicular:
|
|
return 'Energy is rising! Support your cycle with cruciferous vegetables and lean protein as you transition to more active movement.';
|
|
case CyclePhase.ovulation:
|
|
if (isMarried) {
|
|
return 'Peak energy and connection. Focus on healthy fats for hormonal support and prioritize quality time with your spouse.';
|
|
}
|
|
return 'Peak confidence and social energy. Support your peak energy with complex carbs and social engagement.';
|
|
case CyclePhase.luteal:
|
|
return 'Nourish your nervous system with magnesium-rich foods and steady mobility. Transition to restorative self-care.';
|
|
}
|
|
}
|
|
|
|
Map<String, String> _getDetailsForPhase(CyclePhase phase) {
|
|
switch (phase) {
|
|
case CyclePhase.menstrual:
|
|
return {
|
|
'nutrition':
|
|
'Incorporate leafy greens, red meat or lentils for iron. Pair with citrus for better absorption.',
|
|
'movement':
|
|
'Gentle walking, restorative yoga, or just deep breathing. Avoid high-intensity stress.',
|
|
};
|
|
case CyclePhase.follicular:
|
|
return {
|
|
'nutrition':
|
|
'Broccoli, cauliflower, and fermented foods help balance rising estrogen. Focus on lean proteins.',
|
|
'movement':
|
|
'Strength training and steady cardio. Your body is primed for building and renewal.',
|
|
};
|
|
case CyclePhase.ovulation:
|
|
return {
|
|
'nutrition':
|
|
'Avocados, nuts, and seeds provide healthy fats for peak hormonal health. Keep hydration high.',
|
|
'movement':
|
|
'Highest intensity workouts, HIIT, or group sports. You have peak stamina and strength right now.',
|
|
};
|
|
case CyclePhase.luteal:
|
|
return {
|
|
'nutrition':
|
|
'Dark chocolate (70%+), pumpkin seeds, and bananas for magnesium to help with cramps.',
|
|
'movement':
|
|
'Pilates, steady-state swimming, or hiking. Focus on persistence rather than peak intensity.',
|
|
};
|
|
}
|
|
}
|
|
}
|