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.
184 lines
5.9 KiB
Dart
184 lines
5.9 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:google_fonts/google_fonts.dart';
|
|
import '../theme/app_theme.dart';
|
|
import 'onboarding/onboarding_screen.dart';
|
|
import 'home/home_screen.dart';
|
|
import '../models/user_profile.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import '../providers/user_provider.dart';
|
|
import 'husband/husband_home_screen.dart';
|
|
|
|
class SplashScreen extends ConsumerStatefulWidget {
|
|
const SplashScreen({super.key});
|
|
|
|
@override
|
|
ConsumerState<SplashScreen> createState() => _SplashScreenState();
|
|
}
|
|
|
|
class _SplashScreenState extends ConsumerState<SplashScreen> with SingleTickerProviderStateMixin {
|
|
late AnimationController _controller;
|
|
late Animation<double> _fadeAnimation;
|
|
late Animation<double> _scaleAnimation;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_controller = AnimationController(
|
|
duration: const Duration(milliseconds: 1500),
|
|
vsync: this,
|
|
);
|
|
|
|
_fadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
|
|
CurvedAnimation(
|
|
parent: _controller,
|
|
curve: const Interval(0.0, 0.5, curve: Curves.easeIn),
|
|
),
|
|
);
|
|
|
|
_scaleAnimation = Tween<double>(begin: 0.8, end: 1.0).animate(
|
|
CurvedAnimation(
|
|
parent: _controller,
|
|
curve: const Interval(0.0, 0.5, curve: Curves.easeOutBack),
|
|
),
|
|
);
|
|
|
|
_controller.forward();
|
|
|
|
// Navigate after splash
|
|
Future.delayed(const Duration(milliseconds: 1200), () {
|
|
_navigateToNextScreen();
|
|
});
|
|
}
|
|
|
|
void _navigateToNextScreen() {
|
|
final user = ref.read(userProfileProvider);
|
|
final hasProfile = user != null;
|
|
|
|
Widget nextScreen;
|
|
if (!hasProfile) {
|
|
nextScreen = const OnboardingScreen();
|
|
} else if (user.role == UserRole.husband) {
|
|
nextScreen = const HusbandHomeScreen();
|
|
} else {
|
|
nextScreen = const HomeScreen();
|
|
}
|
|
|
|
Navigator.of(context).pushReplacement(
|
|
PageRouteBuilder(
|
|
pageBuilder: (context, animation, secondaryAnimation) => nextScreen,
|
|
transitionsBuilder: (context, animation, secondaryAnimation, child) {
|
|
return FadeTransition(opacity: animation, child: child);
|
|
},
|
|
transitionDuration: const Duration(milliseconds: 500),
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_controller.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: AppColors.cream,
|
|
body: Center(
|
|
child: AnimatedBuilder(
|
|
animation: _controller,
|
|
builder: (context, child) {
|
|
return FadeTransition(
|
|
opacity: _fadeAnimation,
|
|
child: ScaleTransition(
|
|
scale: _scaleAnimation,
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
// App Icon/Logo
|
|
Container(
|
|
width: 120,
|
|
height: 120,
|
|
decoration: BoxDecoration(
|
|
gradient: LinearGradient(
|
|
colors: [
|
|
AppColors.blushPink,
|
|
AppColors.rose.withOpacity(0.8),
|
|
],
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
),
|
|
borderRadius: BorderRadius.circular(30),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: AppColors.rose.withOpacity(0.3),
|
|
blurRadius: 20,
|
|
offset: const Offset(0, 10),
|
|
),
|
|
],
|
|
),
|
|
child: const Icon(
|
|
Icons.favorite_rounded,
|
|
size: 60,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
const SizedBox(height: 24),
|
|
|
|
// App Name placeholder
|
|
Text(
|
|
'Period Tracker',
|
|
style: GoogleFonts.outfit(
|
|
fontSize: 28,
|
|
fontWeight: FontWeight.w600,
|
|
color: AppColors.charcoal,
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
|
|
// Tagline
|
|
Text(
|
|
'Faith-Centered Wellness',
|
|
style: GoogleFonts.outfit(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w400,
|
|
color: AppColors.warmGray,
|
|
letterSpacing: 1.2,
|
|
),
|
|
),
|
|
const SizedBox(height: 48),
|
|
|
|
// Scripture
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 48),
|
|
child: Text(
|
|
'"I praise you because I am\nfearfully and wonderfully made."',
|
|
textAlign: TextAlign.center,
|
|
style: GoogleFonts.lora(
|
|
fontSize: 16,
|
|
fontStyle: FontStyle.italic,
|
|
color: AppColors.charcoal,
|
|
height: 1.5,
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
'— Psalm 139:14',
|
|
style: GoogleFonts.outfit(
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w500,
|
|
color: AppColors.warmGray,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|