1025 lines
36 KiB
Dart
1025 lines
36 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:google_fonts/google_fonts.dart';
|
|
import 'package:smooth_page_indicator/smooth_page_indicator.dart';
|
|
import 'package:hive_flutter/hive_flutter.dart';
|
|
import 'package:uuid/uuid.dart';
|
|
import '../../theme/app_theme.dart';
|
|
import 'package:christian_period_tracker/models/user_profile.dart';
|
|
import 'package:christian_period_tracker/models/cycle_entry.dart';
|
|
import '../home/home_screen.dart';
|
|
import '../husband/husband_home_screen.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import '../../providers/user_provider.dart';
|
|
|
|
class OnboardingScreen extends ConsumerStatefulWidget {
|
|
const OnboardingScreen({super.key});
|
|
|
|
@override
|
|
ConsumerState<OnboardingScreen> createState() => _OnboardingScreenState();
|
|
}
|
|
|
|
class _OnboardingScreenState extends ConsumerState<OnboardingScreen> {
|
|
final PageController _pageController = PageController();
|
|
int _currentPage = 0;
|
|
bool _isNavigating = false; // Debounce flag
|
|
|
|
// Form data
|
|
UserRole _role = UserRole.wife;
|
|
String _name = '';
|
|
RelationshipStatus _relationshipStatus = RelationshipStatus.single;
|
|
FertilityGoal? _fertilityGoal;
|
|
int _averageCycleLength = 28;
|
|
DateTime? _lastPeriodStart;
|
|
bool _isIrregularCycle = false;
|
|
|
|
@override
|
|
void dispose() {
|
|
_pageController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
void _nextPage() async {
|
|
if (_isNavigating) return;
|
|
_isNavigating = true;
|
|
|
|
// Husband Flow: Role (0) -> Name (1) -> Finish
|
|
// Wife Flow: Role (0) -> Name (1) -> Relationship (2) -> [Fertility (3)] -> Cycle (4)
|
|
|
|
int nextPage = _currentPage + 1;
|
|
|
|
// Logic for skipping pages
|
|
if (_role == UserRole.husband) {
|
|
if (_currentPage == 1) {
|
|
await _completeOnboarding();
|
|
return;
|
|
}
|
|
} else {
|
|
// Wife flow
|
|
if (_currentPage == 2 && _relationshipStatus != RelationshipStatus.married) {
|
|
// Skip fertility goal (page 3) if not married
|
|
nextPage = 4;
|
|
}
|
|
}
|
|
|
|
if (nextPage <= 4) { // Max pages
|
|
await _pageController.animateToPage(
|
|
nextPage,
|
|
duration: const Duration(milliseconds: 400),
|
|
curve: Curves.easeInOut,
|
|
);
|
|
} else {
|
|
await _completeOnboarding();
|
|
}
|
|
|
|
// Reset debounce after animation
|
|
Future.delayed(const Duration(milliseconds: 500), () {
|
|
if (mounted) setState(() => _isNavigating = false);
|
|
});
|
|
}
|
|
|
|
void _previousPage() async {
|
|
if (_isNavigating) return;
|
|
_isNavigating = true;
|
|
|
|
int prevPage = _currentPage - 1;
|
|
|
|
// Logic for reverse skipping
|
|
if (_role == UserRole.wife) {
|
|
if (_currentPage == 4 && _relationshipStatus != RelationshipStatus.married) {
|
|
// Skip back over fertility goal (page 3)
|
|
prevPage = 2;
|
|
}
|
|
}
|
|
|
|
if (prevPage >= 0) {
|
|
await _pageController.animateToPage(
|
|
prevPage,
|
|
duration: const Duration(milliseconds: 400),
|
|
curve: Curves.easeInOut,
|
|
);
|
|
}
|
|
|
|
// Reset debounce after animation
|
|
Future.delayed(const Duration(milliseconds: 500), () {
|
|
if (mounted) setState(() => _isNavigating = false);
|
|
});
|
|
}
|
|
|
|
Future<void> _completeOnboarding() async {
|
|
final userProfile = UserProfile(
|
|
id: const Uuid().v4(),
|
|
name: _name,
|
|
role: _role,
|
|
relationshipStatus: _role == UserRole.husband ? RelationshipStatus.married : _relationshipStatus,
|
|
fertilityGoal: (_role == UserRole.wife && _relationshipStatus == RelationshipStatus.married) ? _fertilityGoal : null,
|
|
averageCycleLength: _averageCycleLength,
|
|
lastPeriodStartDate: _lastPeriodStart,
|
|
isIrregularCycle: _isIrregularCycle,
|
|
hasCompletedOnboarding: true,
|
|
createdAt: DateTime.now(),
|
|
updatedAt: DateTime.now(),
|
|
);
|
|
|
|
await ref.read(userProfileProvider.notifier).updateProfile(userProfile);
|
|
|
|
if (mounted) {
|
|
// Navigate to appropriate home screen
|
|
if (_role == UserRole.husband) {
|
|
Navigator.of(context).pushReplacement(
|
|
MaterialPageRoute(
|
|
builder: (_) => const HusbandHomeScreen(),
|
|
),
|
|
);
|
|
} else {
|
|
Navigator.of(context).pushReplacement(
|
|
MaterialPageRoute(builder: (_) => const HomeScreen()),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
<<<<<<< HEAD
|
|
// Different background color for husband flow
|
|
final bgColor = _role == UserRole.husband ? AppColors.warmCream : AppColors.cream;
|
|
=======
|
|
final theme = Theme.of(context);
|
|
final isDark = theme.brightness == Brightness.dark;
|
|
|
|
// Different background color for husband flow
|
|
final isHusband = _role == UserRole.husband;
|
|
final bgColor = isHusband
|
|
? (isDark ? const Color(0xFF1A1C1E) : AppColors.warmCream)
|
|
: theme.scaffoldBackgroundColor;
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
|
|
return Scaffold(
|
|
backgroundColor: bgColor,
|
|
body: SafeArea(
|
|
child: Column(
|
|
children: [
|
|
// Progress indicator (hide on role page 0)
|
|
if (_currentPage > 0)
|
|
Padding(
|
|
padding: const EdgeInsets.all(24),
|
|
child: SmoothPageIndicator(
|
|
controller: _pageController,
|
|
<<<<<<< HEAD
|
|
count: _role == UserRole.husband ? 2 : 5,
|
|
=======
|
|
count: isHusband ? 2 : 5,
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
effect: WormEffect(
|
|
dotHeight: 8,
|
|
dotWidth: 8,
|
|
spacing: 12,
|
|
<<<<<<< HEAD
|
|
activeDotColor: _role == UserRole.husband ? AppColors.navyBlue : AppColors.sageGreen,
|
|
dotColor: AppColors.lightGray.withOpacity(0.3),
|
|
=======
|
|
activeDotColor: isHusband ? AppColors.navyBlue : AppColors.sageGreen,
|
|
dotColor: theme.colorScheme.outline.withOpacity(0.2),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
),
|
|
),
|
|
),
|
|
|
|
// Pages
|
|
Expanded(
|
|
child: PageView(
|
|
controller: _pageController,
|
|
physics: const NeverScrollableScrollPhysics(), // Disable swipe
|
|
onPageChanged: (index) {
|
|
setState(() => _currentPage = index);
|
|
},
|
|
children: [
|
|
_buildRolePage(), // Page 0
|
|
_buildNamePage(), // Page 1
|
|
_buildRelationshipPage(), // Page 2 (Wife only)
|
|
_buildFertilityGoalPage(), // Page 3 (Wife married only)
|
|
_buildCyclePage(), // Page 4 (Wife only)
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildRolePage() {
|
|
<<<<<<< HEAD
|
|
=======
|
|
final theme = Theme.of(context);
|
|
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
return Padding(
|
|
padding: const EdgeInsets.all(32),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Container(
|
|
width: 80,
|
|
height: 80,
|
|
decoration: BoxDecoration(
|
|
gradient: LinearGradient(
|
|
colors: [AppColors.blushPink, AppColors.rose.withOpacity(0.7)],
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
),
|
|
borderRadius: BorderRadius.circular(20),
|
|
),
|
|
child: const Icon(
|
|
Icons.favorite_rounded,
|
|
size: 40,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
const SizedBox(height: 32),
|
|
Text(
|
|
'Who is this app for?',
|
|
textAlign: TextAlign.center,
|
|
<<<<<<< HEAD
|
|
style: GoogleFonts.outfit(
|
|
fontSize: 28,
|
|
fontWeight: FontWeight.w600,
|
|
color: AppColors.charcoal,
|
|
=======
|
|
style: theme.textTheme.displayMedium?.copyWith(
|
|
fontSize: 28,
|
|
fontWeight: FontWeight.w600,
|
|
color: theme.colorScheme.onSurface,
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
),
|
|
),
|
|
const SizedBox(height: 48),
|
|
|
|
_buildRoleOption(UserRole.wife, 'For Her', 'Track cycle, health, and faith', Icons.female),
|
|
const SizedBox(height: 16),
|
|
_buildRoleOption(UserRole.husband, 'For Him', 'Support your wife and grow together', Icons.male),
|
|
|
|
const Spacer(),
|
|
SizedBox(
|
|
width: double.infinity,
|
|
<<<<<<< HEAD
|
|
=======
|
|
height: 54,
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
child: ElevatedButton(
|
|
onPressed: _nextPage,
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: _role == UserRole.husband ? AppColors.navyBlue : AppColors.sageGreen,
|
|
),
|
|
child: const Text('Continue'),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildRoleOption(UserRole role, String title, String subtitle, IconData icon) {
|
|
<<<<<<< HEAD
|
|
final isSelected = _role == role;
|
|
// Dynamic colors based on role selection
|
|
final activeColor = role == UserRole.wife ? AppColors.sageGreen : AppColors.navyBlue;
|
|
final activeBg = role == UserRole.wife ? AppColors.sageGreen.withOpacity(0.1) : AppColors.navyBlue.withOpacity(0.1);
|
|
=======
|
|
final theme = Theme.of(context);
|
|
final isDark = theme.brightness == Brightness.dark;
|
|
final isSelected = _role == role;
|
|
|
|
// Dynamic colors based on role selection
|
|
final activeColor = role == UserRole.wife ? AppColors.sageGreen : AppColors.navyBlue;
|
|
final activeBg = activeColor.withOpacity(isDark ? 0.3 : 0.1);
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
|
|
return GestureDetector(
|
|
onTap: () => setState(() => _role = role),
|
|
child: AnimatedContainer(
|
|
duration: const Duration(milliseconds: 200),
|
|
padding: const EdgeInsets.all(20),
|
|
decoration: BoxDecoration(
|
|
<<<<<<< HEAD
|
|
color: isSelected ? activeBg : Colors.white,
|
|
borderRadius: BorderRadius.circular(16),
|
|
border: Border.all(
|
|
color: isSelected ? activeColor : AppColors.lightGray.withOpacity(0.5),
|
|
width: isSelected ? 2 : 1,
|
|
),
|
|
boxShadow: isSelected ? [
|
|
BoxShadow(
|
|
color: activeColor.withOpacity(0.1),
|
|
blurRadius: 10,
|
|
offset: const Offset(0, 4),
|
|
)
|
|
] : [],
|
|
=======
|
|
color: isSelected ? activeBg : theme.cardTheme.color,
|
|
borderRadius: BorderRadius.circular(16),
|
|
border: Border.all(
|
|
color: isSelected ? activeColor : theme.colorScheme.outline.withOpacity(0.1),
|
|
width: isSelected ? 2 : 1,
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Container(
|
|
padding: const EdgeInsets.all(12),
|
|
decoration: BoxDecoration(
|
|
<<<<<<< HEAD
|
|
color: isSelected ? activeColor : AppColors.lightGray.withOpacity(0.1),
|
|
=======
|
|
color: isSelected ? activeColor : theme.colorScheme.surfaceVariant,
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: Icon(
|
|
icon,
|
|
<<<<<<< HEAD
|
|
color: isSelected ? Colors.white : AppColors.warmGray,
|
|
=======
|
|
color: isSelected ? Colors.white : theme.colorScheme.onSurfaceVariant,
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
size: 24,
|
|
),
|
|
),
|
|
const SizedBox(width: 16),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
title,
|
|
<<<<<<< HEAD
|
|
style: GoogleFonts.outfit(
|
|
fontSize: 18,
|
|
fontWeight: FontWeight.w600,
|
|
color: AppColors.charcoal,
|
|
=======
|
|
style: theme.textTheme.titleLarge?.copyWith(
|
|
fontSize: 18,
|
|
fontWeight: FontWeight.w600,
|
|
color: theme.colorScheme.onSurface,
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
),
|
|
),
|
|
const SizedBox(height: 4),
|
|
Text(
|
|
subtitle,
|
|
<<<<<<< HEAD
|
|
style: GoogleFonts.outfit(
|
|
fontSize: 14,
|
|
color: AppColors.warmGray,
|
|
=======
|
|
style: theme.textTheme.bodyMedium?.copyWith(
|
|
color: theme.colorScheme.onSurfaceVariant,
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
if (isSelected)
|
|
Icon(Icons.check_circle, color: activeColor),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildNamePage() {
|
|
<<<<<<< HEAD
|
|
=======
|
|
final theme = Theme.of(context);
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
final isHusband = _role == UserRole.husband;
|
|
final activeColor = isHusband ? AppColors.navyBlue : AppColors.sageGreen;
|
|
|
|
return Padding(
|
|
padding: const EdgeInsets.all(32),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const SizedBox(height: 40),
|
|
Text(
|
|
isHusband ? 'What\'s your name, sir?' : 'What\'s your name?',
|
|
<<<<<<< HEAD
|
|
style: GoogleFonts.outfit(
|
|
fontSize: 28,
|
|
fontWeight: FontWeight.w600,
|
|
color: isHusband ? AppColors.navyBlue : AppColors.charcoal,
|
|
=======
|
|
style: theme.textTheme.displaySmall?.copyWith(
|
|
fontSize: 28,
|
|
fontWeight: FontWeight.w600,
|
|
color: theme.colorScheme.onSurface,
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
'We\'ll use this to personalize the app.',
|
|
<<<<<<< HEAD
|
|
style: GoogleFonts.outfit(
|
|
fontSize: 14,
|
|
color: AppColors.warmGray,
|
|
=======
|
|
style: theme.textTheme.bodyMedium?.copyWith(
|
|
color: theme.colorScheme.onSurfaceVariant,
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
),
|
|
),
|
|
const SizedBox(height: 32),
|
|
|
|
TextField(
|
|
onChanged: (value) => setState(() => _name = value),
|
|
decoration: InputDecoration(
|
|
hintText: 'Enter your name',
|
|
prefixIcon: Icon(
|
|
Icons.person_outline,
|
|
<<<<<<< HEAD
|
|
color: AppColors.warmGray,
|
|
),
|
|
focusedBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(12),
|
|
borderSide: BorderSide(color: activeColor),
|
|
),
|
|
),
|
|
style: GoogleFonts.outfit(fontSize: 16),
|
|
=======
|
|
color: theme.colorScheme.onSurfaceVariant,
|
|
),
|
|
focusedBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(12),
|
|
borderSide: BorderSide(color: activeColor, width: 2),
|
|
),
|
|
),
|
|
style: theme.textTheme.bodyLarge,
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
textCapitalization: TextCapitalization.words,
|
|
),
|
|
|
|
const Spacer(),
|
|
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
<<<<<<< HEAD
|
|
child: OutlinedButton(
|
|
onPressed: _previousPage,
|
|
style: OutlinedButton.styleFrom(
|
|
foregroundColor: isHusband ? AppColors.navyBlue : AppColors.sageGreen,
|
|
side: BorderSide(color: isHusband ? AppColors.navyBlue : AppColors.sageGreen),
|
|
),
|
|
child: const Text('Back'),
|
|
=======
|
|
child: SizedBox(
|
|
height: 54,
|
|
child: OutlinedButton(
|
|
onPressed: _previousPage,
|
|
style: OutlinedButton.styleFrom(
|
|
foregroundColor: activeColor,
|
|
side: BorderSide(color: activeColor),
|
|
),
|
|
child: const Text('Back'),
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
),
|
|
),
|
|
const SizedBox(width: 16),
|
|
Expanded(
|
|
<<<<<<< HEAD
|
|
child: ElevatedButton(
|
|
onPressed: (_name.isNotEmpty && !_isNavigating) ? _nextPage : null,
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: activeColor,
|
|
),
|
|
child: Text(isHusband ? 'Finish Setup' : 'Continue'),
|
|
=======
|
|
child: SizedBox(
|
|
height: 54,
|
|
child: ElevatedButton(
|
|
onPressed: (_name.isNotEmpty && !_isNavigating) ? _nextPage : null,
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: activeColor,
|
|
),
|
|
child: Text(isHusband ? 'Finish Setup' : 'Continue'),
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildRelationshipPage() {
|
|
<<<<<<< HEAD
|
|
=======
|
|
final theme = Theme.of(context);
|
|
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
return Padding(
|
|
padding: const EdgeInsets.all(32),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const SizedBox(height: 40),
|
|
Text(
|
|
'Tell us about yourself',
|
|
<<<<<<< HEAD
|
|
style: GoogleFonts.outfit(
|
|
fontSize: 28,
|
|
fontWeight: FontWeight.w600,
|
|
color: AppColors.charcoal,
|
|
=======
|
|
style: theme.textTheme.displaySmall?.copyWith(
|
|
fontSize: 28,
|
|
fontWeight: FontWeight.w600,
|
|
color: theme.colorScheme.onSurface,
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
),
|
|
),
|
|
const SizedBox(height: 32),
|
|
|
|
_buildRelationshipOption(RelationshipStatus.single, 'Single', 'Wellness focus', Icons.person_outline),
|
|
const SizedBox(height: 12),
|
|
_buildRelationshipOption(RelationshipStatus.engaged, 'Engaged', 'Prepare for marriage', Icons.favorite_border),
|
|
const SizedBox(height: 12),
|
|
_buildRelationshipOption(RelationshipStatus.married, 'Married', 'Fertility & intimacy', Icons.favorite),
|
|
|
|
const Spacer(),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
<<<<<<< HEAD
|
|
child: OutlinedButton(
|
|
onPressed: _previousPage,
|
|
style: OutlinedButton.styleFrom(foregroundColor: AppColors.sageGreen, side: BorderSide(color: AppColors.sageGreen)),
|
|
child: const Text('Back'),
|
|
=======
|
|
child: SizedBox(
|
|
height: 54,
|
|
child: OutlinedButton(
|
|
onPressed: _previousPage,
|
|
style: OutlinedButton.styleFrom(
|
|
foregroundColor: AppColors.sageGreen,
|
|
side: const BorderSide(color: AppColors.sageGreen)
|
|
),
|
|
child: const Text('Back'),
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
),
|
|
),
|
|
const SizedBox(width: 16),
|
|
Expanded(
|
|
<<<<<<< HEAD
|
|
child: ElevatedButton(
|
|
onPressed: (_relationshipStatus != null && !_isNavigating) ? _nextPage : null,
|
|
child: const Text('Continue'),
|
|
=======
|
|
child: SizedBox(
|
|
height: 54,
|
|
child: ElevatedButton(
|
|
onPressed: (_relationshipStatus != null && !_isNavigating) ? _nextPage : null,
|
|
child: const Text('Continue'),
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildRelationshipOption(RelationshipStatus status, String title, String subtitle, IconData icon) {
|
|
<<<<<<< HEAD
|
|
final isSelected = _relationshipStatus == status;
|
|
=======
|
|
final theme = Theme.of(context);
|
|
final isDark = theme.brightness == Brightness.dark;
|
|
final isSelected = _relationshipStatus == status;
|
|
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
return GestureDetector(
|
|
onTap: () => setState(() => _relationshipStatus = status),
|
|
child: AnimatedContainer(
|
|
duration: const Duration(milliseconds: 200),
|
|
padding: const EdgeInsets.all(16),
|
|
decoration: BoxDecoration(
|
|
<<<<<<< HEAD
|
|
color: isSelected ? AppColors.sageGreen.withOpacity(0.1) : Colors.white,
|
|
borderRadius: BorderRadius.circular(12),
|
|
border: Border.all(
|
|
color: isSelected ? AppColors.sageGreen : AppColors.lightGray.withOpacity(0.5),
|
|
=======
|
|
color: isSelected ? AppColors.sageGreen.withOpacity(isDark ? 0.3 : 0.1) : theme.cardTheme.color,
|
|
borderRadius: BorderRadius.circular(12),
|
|
border: Border.all(
|
|
color: isSelected ? AppColors.sageGreen : theme.colorScheme.outline.withOpacity(0.1),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
width: isSelected ? 2 : 1,
|
|
),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
<<<<<<< HEAD
|
|
Icon(icon, color: isSelected ? AppColors.sageGreen : AppColors.warmGray),
|
|
=======
|
|
Icon(
|
|
icon,
|
|
color: isSelected ? AppColors.sageGreen : theme.colorScheme.onSurfaceVariant
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
const SizedBox(width: 16),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
<<<<<<< HEAD
|
|
Text(title, style: GoogleFonts.outfit(fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.charcoal)),
|
|
Text(subtitle, style: GoogleFonts.outfit(fontSize: 13, color: AppColors.warmGray)),
|
|
=======
|
|
Text(
|
|
title,
|
|
style: theme.textTheme.titleMedium?.copyWith(
|
|
fontWeight: FontWeight.w600,
|
|
color: theme.colorScheme.onSurface
|
|
)
|
|
),
|
|
Text(
|
|
subtitle,
|
|
style: theme.textTheme.bodySmall?.copyWith(
|
|
color: theme.colorScheme.onSurfaceVariant
|
|
)
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
],
|
|
),
|
|
),
|
|
if (isSelected) Icon(Icons.check_circle, color: AppColors.sageGreen),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildFertilityGoalPage() {
|
|
<<<<<<< HEAD
|
|
=======
|
|
final theme = Theme.of(context);
|
|
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
return Padding(
|
|
padding: const EdgeInsets.all(32),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const SizedBox(height: 40),
|
|
<<<<<<< HEAD
|
|
Text('What\'s your goal?', style: GoogleFonts.outfit(fontSize: 28, fontWeight: FontWeight.w600, color: AppColors.charcoal)),
|
|
=======
|
|
Text(
|
|
'What\'s your goal?',
|
|
style: theme.textTheme.displaySmall?.copyWith(
|
|
fontSize: 28,
|
|
fontWeight: FontWeight.w600,
|
|
color: theme.colorScheme.onSurface
|
|
)
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
const SizedBox(height: 32),
|
|
_buildGoalOption(FertilityGoal.tryingToConceive, 'Trying to Conceive', 'Track fertile days', Icons.child_care_outlined),
|
|
const SizedBox(height: 12),
|
|
_buildGoalOption(FertilityGoal.tryingToAvoid, 'Natural Family Planning', 'Track fertility signs', Icons.calendar_today_outlined),
|
|
const SizedBox(height: 12),
|
|
_buildGoalOption(FertilityGoal.justTracking, 'Just Tracking', 'Monitor cycle health', Icons.insights_outlined),
|
|
const Spacer(),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
<<<<<<< HEAD
|
|
child: OutlinedButton(
|
|
onPressed: _previousPage,
|
|
style: OutlinedButton.styleFrom(foregroundColor: AppColors.sageGreen, side: BorderSide(color: AppColors.sageGreen)),
|
|
child: const Text('Back'),
|
|
=======
|
|
child: SizedBox(
|
|
height: 54,
|
|
child: OutlinedButton(
|
|
onPressed: _previousPage,
|
|
style: OutlinedButton.styleFrom(
|
|
foregroundColor: AppColors.sageGreen,
|
|
side: const BorderSide(color: AppColors.sageGreen)
|
|
),
|
|
child: const Text('Back'),
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
),
|
|
),
|
|
const SizedBox(width: 16),
|
|
Expanded(
|
|
<<<<<<< HEAD
|
|
child: ElevatedButton(
|
|
onPressed: (_fertilityGoal != null && !_isNavigating) ? _nextPage : null,
|
|
child: const Text('Continue'),
|
|
=======
|
|
child: SizedBox(
|
|
height: 54,
|
|
child: ElevatedButton(
|
|
onPressed: (_fertilityGoal != null && !_isNavigating) ? _nextPage : null,
|
|
child: const Text('Continue'),
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildGoalOption(FertilityGoal goal, String title, String subtitle, IconData icon) {
|
|
<<<<<<< HEAD
|
|
final isSelected = _fertilityGoal == goal;
|
|
=======
|
|
final theme = Theme.of(context);
|
|
final isDark = theme.brightness == Brightness.dark;
|
|
final isSelected = _fertilityGoal == goal;
|
|
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
return GestureDetector(
|
|
onTap: () => setState(() => _fertilityGoal = goal),
|
|
child: AnimatedContainer(
|
|
duration: const Duration(milliseconds: 200),
|
|
padding: const EdgeInsets.all(16),
|
|
decoration: BoxDecoration(
|
|
<<<<<<< HEAD
|
|
color: isSelected ? AppColors.sageGreen.withOpacity(0.1) : Colors.white,
|
|
borderRadius: BorderRadius.circular(12),
|
|
border: Border.all(
|
|
color: isSelected ? AppColors.sageGreen : AppColors.lightGray.withOpacity(0.5),
|
|
=======
|
|
color: isSelected ? AppColors.sageGreen.withOpacity(isDark ? 0.3 : 0.1) : theme.cardTheme.color,
|
|
borderRadius: BorderRadius.circular(12),
|
|
border: Border.all(
|
|
color: isSelected ? AppColors.sageGreen : theme.colorScheme.outline.withOpacity(0.1),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
width: isSelected ? 2 : 1,
|
|
),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
<<<<<<< HEAD
|
|
Icon(icon, color: isSelected ? AppColors.sageGreen : AppColors.warmGray),
|
|
=======
|
|
Icon(
|
|
icon,
|
|
color: isSelected ? AppColors.sageGreen : theme.colorScheme.onSurfaceVariant
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
const SizedBox(width: 16),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
<<<<<<< HEAD
|
|
Text(title, style: GoogleFonts.outfit(fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.charcoal)),
|
|
Text(subtitle, style: GoogleFonts.outfit(fontSize: 13, color: AppColors.warmGray)),
|
|
=======
|
|
Text(
|
|
title,
|
|
style: theme.textTheme.titleMedium?.copyWith(
|
|
fontWeight: FontWeight.w600,
|
|
color: theme.colorScheme.onSurface
|
|
)
|
|
),
|
|
Text(
|
|
subtitle,
|
|
style: theme.textTheme.bodySmall?.copyWith(
|
|
color: theme.colorScheme.onSurfaceVariant
|
|
)
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
],
|
|
),
|
|
),
|
|
if (isSelected) Icon(Icons.check_circle, color: AppColors.sageGreen),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildCyclePage() {
|
|
<<<<<<< HEAD
|
|
=======
|
|
final theme = Theme.of(context);
|
|
final isDark = theme.brightness == Brightness.dark;
|
|
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
return Padding(
|
|
padding: const EdgeInsets.all(32),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const SizedBox(height: 40),
|
|
<<<<<<< HEAD
|
|
Text('About your cycle', style: GoogleFonts.outfit(fontSize: 28, fontWeight: FontWeight.w600, color: AppColors.charcoal)),
|
|
const SizedBox(height: 32),
|
|
|
|
Text('Average cycle length', style: GoogleFonts.outfit(fontSize: 16, fontWeight: FontWeight.w500, color: AppColors.charcoal)),
|
|
=======
|
|
Text(
|
|
'About your cycle',
|
|
style: theme.textTheme.displaySmall?.copyWith(
|
|
fontSize: 28,
|
|
fontWeight: FontWeight.w600,
|
|
color: theme.colorScheme.onSurface
|
|
)
|
|
),
|
|
const SizedBox(height: 32),
|
|
|
|
Text(
|
|
'Average cycle length',
|
|
style: theme.textTheme.titleMedium?.copyWith(
|
|
fontWeight: FontWeight.w500,
|
|
color: theme.colorScheme.onSurface
|
|
)
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: Slider(
|
|
value: _averageCycleLength.toDouble(),
|
|
min: 21,
|
|
max: 40,
|
|
divisions: 19,
|
|
<<<<<<< HEAD
|
|
onChanged: (value) => setState(() => _averageCycleLength = value.round()),
|
|
),
|
|
),
|
|
Text('$_averageCycleLength days', style: GoogleFonts.outfit(fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.sageGreen)),
|
|
=======
|
|
activeColor: AppColors.sageGreen,
|
|
onChanged: (value) => setState(() => _averageCycleLength = value.round()),
|
|
),
|
|
),
|
|
Text(
|
|
'$_averageCycleLength days',
|
|
style: theme.textTheme.titleMedium?.copyWith(
|
|
fontWeight: FontWeight.w600,
|
|
color: AppColors.sageGreen
|
|
)
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
],
|
|
),
|
|
|
|
// Irregular Cycle Checkbox
|
|
CheckboxListTile(
|
|
<<<<<<< HEAD
|
|
title: Text('My cycles are irregular', style: GoogleFonts.outfit(fontSize: 14, color: AppColors.charcoal)),
|
|
=======
|
|
title: Text(
|
|
'My cycles are irregular',
|
|
style: theme.textTheme.bodyLarge?.copyWith(
|
|
color: theme.colorScheme.onSurface
|
|
)
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
value: _isIrregularCycle,
|
|
onChanged: (val) => setState(() => _isIrregularCycle = val ?? false),
|
|
activeColor: AppColors.sageGreen,
|
|
contentPadding: EdgeInsets.zero,
|
|
controlAffinity: ListTileControlAffinity.leading,
|
|
),
|
|
|
|
const SizedBox(height: 24),
|
|
<<<<<<< HEAD
|
|
Text('Last period start date', style: GoogleFonts.outfit(fontSize: 16, fontWeight: FontWeight.w500, color: AppColors.charcoal)),
|
|
=======
|
|
Text(
|
|
'Last period start date',
|
|
style: theme.textTheme.titleMedium?.copyWith(
|
|
fontWeight: FontWeight.w500,
|
|
color: theme.colorScheme.onSurface
|
|
)
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
const SizedBox(height: 8),
|
|
GestureDetector(
|
|
onTap: () async {
|
|
final date = await showDatePicker(
|
|
context: context,
|
|
initialDate: _lastPeriodStart ?? DateTime.now(),
|
|
firstDate: DateTime.now().subtract(const Duration(days: 60)),
|
|
lastDate: DateTime.now(),
|
|
builder: (context, child) {
|
|
return Theme(
|
|
<<<<<<< HEAD
|
|
data: Theme.of(context).copyWith(
|
|
colorScheme: const ColorScheme.light(primary: AppColors.sageGreen, onPrimary: Colors.white, surface: Colors.white, onSurface: AppColors.charcoal),
|
|
=======
|
|
data: theme.copyWith(
|
|
colorScheme: theme.colorScheme.copyWith(
|
|
primary: AppColors.sageGreen,
|
|
onPrimary: Colors.white,
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
),
|
|
child: child!,
|
|
);
|
|
},
|
|
);
|
|
if (date != null) setState(() => _lastPeriodStart = date);
|
|
},
|
|
child: Container(
|
|
padding: const EdgeInsets.all(16),
|
|
<<<<<<< HEAD
|
|
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColors.lightGray.withOpacity(0.5))),
|
|
child: Row(
|
|
children: [
|
|
Icon(Icons.calendar_today, color: AppColors.warmGray),
|
|
const SizedBox(width: 12),
|
|
Text(_lastPeriodStart != null ? "${_lastPeriodStart!.month}/${_lastPeriodStart!.day}/${_lastPeriodStart!.year}" : "Select Date", style: GoogleFonts.outfit(fontSize: 16, color: AppColors.charcoal)),
|
|
=======
|
|
decoration: BoxDecoration(
|
|
color: theme.cardTheme.color,
|
|
borderRadius: BorderRadius.circular(12),
|
|
border: Border.all(color: theme.colorScheme.outline.withOpacity(0.1))
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Icon(Icons.calendar_today, color: theme.colorScheme.onSurfaceVariant),
|
|
const SizedBox(width: 12),
|
|
Text(
|
|
_lastPeriodStart != null
|
|
? "${_lastPeriodStart!.month}/${_lastPeriodStart!.day}/${_lastPeriodStart!.year}"
|
|
: "Select Date",
|
|
style: theme.textTheme.bodyLarge?.copyWith(
|
|
color: theme.colorScheme.onSurface
|
|
)
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
],
|
|
),
|
|
),
|
|
),
|
|
|
|
const Spacer(),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
<<<<<<< HEAD
|
|
child: OutlinedButton(
|
|
onPressed: _previousPage,
|
|
style: OutlinedButton.styleFrom(foregroundColor: AppColors.sageGreen, side: BorderSide(color: AppColors.sageGreen)),
|
|
child: const Text('Back'),
|
|
=======
|
|
child: SizedBox(
|
|
height: 54,
|
|
child: OutlinedButton(
|
|
onPressed: _previousPage,
|
|
style: OutlinedButton.styleFrom(
|
|
foregroundColor: AppColors.sageGreen,
|
|
side: const BorderSide(color: AppColors.sageGreen)
|
|
),
|
|
child: const Text('Back'),
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
),
|
|
),
|
|
const SizedBox(width: 16),
|
|
Expanded(
|
|
<<<<<<< HEAD
|
|
child: ElevatedButton(
|
|
onPressed: (_lastPeriodStart != null && !_isNavigating) ? _nextPage : null,
|
|
child: const Text('Get Started'),
|
|
=======
|
|
child: SizedBox(
|
|
height: 54,
|
|
child: ElevatedButton(
|
|
onPressed: (_lastPeriodStart != null && !_isNavigating) ? _nextPage : null,
|
|
child: const Text('Get Started'),
|
|
),
|
|
>>>>>>> 6742220 (Your commit message here)
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|