import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../../core/design/tokens.dart'; import '../../../core/l10n/app_localizations.dart'; import '../../../core/ui/tripz_scaffold.dart'; import '../../../core/ui/tripz_button.dart'; class OnboardingScreen extends StatefulWidget { const OnboardingScreen({super.key}); @override State createState() => _OnboardingScreenState(); } class _OnboardingScreenState extends State with SingleTickerProviderStateMixin { final PageController _pageController = PageController(); int _currentIndex = 0; late final AnimationController _pulseController; late final Animation _pulseAnimation; static const _onboardingKey = 'onboarding_seen'; @override void initState() { super.initState(); _pulseController = AnimationController( vsync: this, duration: const Duration(milliseconds: 1400), )..repeat(reverse: true); _pulseAnimation = Tween(begin: 1.0, end: 1.08).animate( CurvedAnimation(parent: _pulseController, curve: Curves.easeInOut), ); } @override void dispose() { _pulseController.dispose(); _pageController.dispose(); super.dispose(); } Future _markSeen() async { final prefs = await SharedPreferences.getInstance(); await prefs.setBool(_onboardingKey, true); } void _nextPage(int pageCount) { if (_currentIndex < pageCount - 1) { _pageController.nextPage( duration: T.slow, curve: Curves.easeInOut, ); } else { _markSeen(); context.go('/phone'); } } void _skip() { _markSeen(); context.go('/phone'); } @override Widget build(BuildContext context) { final theme = Theme.of(context); final cs = theme.colorScheme; final l10n = AppLocalizations.of(context)!; final pages = [ _OnboardingPageData( title: l10n.onboardingTitle1, subtitle: l10n.onboardingSubtitle1, image: 'assets/images/onboarding_1.png', fallbackIcon: Icons.touch_app_rounded, ), _OnboardingPageData( title: l10n.onboardingTitle2, subtitle: l10n.onboardingSubtitle2, image: 'assets/images/onboarding_2.png', fallbackIcon: Icons.location_on_rounded, ), _OnboardingPageData( title: l10n.onboardingTitle3, subtitle: l10n.onboardingSubtitle3, image: 'assets/images/onboarding_3.png', fallbackIcon: Icons.payment_rounded, ), ]; return TripzScaffold( backgroundColor: cs.surface, padding: false, bottomAction: Column( mainAxisSize: MainAxisSize.min, children: [ // ── Page Indicators ── Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate(pages.length, (index) { final isActive = index == _currentIndex; return AnimatedContainer( duration: T.medium, margin: const EdgeInsets.symmetric(horizontal: T.s4), height: T.s8, width: isActive ? T.s24 : T.s8, decoration: BoxDecoration( color: isActive ? cs.primary : cs.surfaceContainerHighest, borderRadius: BorderRadius.circular(T.rCircle), ), ); }), ), const SizedBox(height: T.s24), // ── Primary Button ── TripzButton( onPressed: () => _nextPage(pages.length), label: _currentIndex == pages.length - 1 ? l10n.getStarted : l10n.next, ), ], ), child: Column( children: [ // ── Skip Button ── Align( alignment: AlignmentDirectional.centerEnd, child: Padding( padding: const EdgeInsets.symmetric( horizontal: T.pagePadding, vertical: T.s8, ), child: TripzButton( onPressed: _skip, style: TripzButtonStyle.text, label: l10n.skip, fullWidth: false, ), ), ), // ── PageView ── Expanded( child: PageView.builder( controller: _pageController, itemCount: pages.length, onPageChanged: (index) { setState(() => _currentIndex = index); }, itemBuilder: (context, index) { final data = pages[index]; return Padding( padding: const EdgeInsets.symmetric(horizontal: T.s24), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // ── الرسم التوضيحي (أصل مسجّل) مع نبض خفيف ── AnimatedScale( scale: _pulseAnimation.value, duration: const Duration(milliseconds: 100), child: SizedBox( width: 240, height: 240, child: Image.asset( data.image, fit: BoxFit.contain, errorBuilder: (_, __, ___) => Container( decoration: BoxDecoration( color: cs.primaryContainer, shape: BoxShape.circle, ), child: Icon( data.fallbackIcon, size: 88, color: cs.onPrimaryContainer, ), ), ), ), ), const SizedBox(height: T.s48), // ── Title ── Text( data.title, style: theme.textTheme.headlineMedium?.copyWith( color: cs.onSurface, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), const SizedBox(height: T.s12), // ── Subtitle ── Text( data.subtitle, style: theme.textTheme.bodyLarge?.copyWith( color: cs.onSurfaceVariant, ), textAlign: TextAlign.center, ), ], ), ); }, ), ), ], ), ); } } class _OnboardingPageData { final String title; final String subtitle; final String image; final IconData fallbackIcon; const _OnboardingPageData({ required this.title, required this.subtitle, required this.image, required this.fallbackIcon, }); }