import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'auth/login_screen.dart'; class OnboardingScreen extends StatefulWidget { const OnboardingScreen({super.key}); @override State createState() => _OnboardingScreenState(); } class _OnboardingScreenState extends State { final PageController _pageController = PageController(); int _currentPage = 0; final List _pages = [ OnboardingData( image: 'assets/images/onboard1.png', title: 'Bidik Menumu, Cepat dan Akurat', description: 'Teknologi Google Vision OCR kami akan membaca daftar menu Amor Coffee secara instan dalam hitungan detik', ), OnboardingData( image: 'assets/images/onboard2.png', title: 'Beri Tahu Amori Seleramu', description: 'Apakah kamu sedang butuh kafein tinggi untuk bekerja atau sekadar camilan manis untuk bersantai? Amori ingin mengenalmu lebih dekat', ), OnboardingData( image: 'assets/images/onboard3.png', title: 'Rekomendasi Cerdas', description: 'Saran Terbaik dari Gemini AI. Dapatkan rekomendasi menu yang paling cocok dengan preferensi pribadimu saat ini', ), ]; @override void dispose() { _pageController.dispose(); super.dispose(); } void _onSkip() async { // Mark onboarding as completed final prefs = await SharedPreferences.getInstance(); await prefs.setBool('is_first_launch', false); if (!mounted) return; Navigator.of(context).pushReplacement( PageRouteBuilder( pageBuilder: (context, animation, secondaryAnimation) => const LoginScreen(), transitionDuration: const Duration(milliseconds: 400), transitionsBuilder: (context, animation, secondaryAnimation, child) { return FadeTransition( opacity: animation.drive( Tween( begin: 0.0, end: 1.0, ).chain(CurveTween(curve: Curves.easeOut)), ), child: child, ); }, ), ); } void _onNext() { if (_currentPage < _pages.length - 1) { _pageController.nextPage( duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, ); } else { _onSkip(); } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: SafeArea( child: Column( children: [ // PageView Expanded( child: PageView.builder( controller: _pageController, onPageChanged: (index) { setState(() { _currentPage = index; }); }, itemCount: _pages.length, itemBuilder: (context, index) { return OnboardingPage(data: _pages[index]); }, ), ), // Bottom controls: Skip, Page Indicator, Arrow Button Padding( padding: const EdgeInsets.fromLTRB(24, 0, 24, 32), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ // Skip button (left) TextButton( onPressed: _onSkip, style: TextButton.styleFrom( minimumSize: const Size(60, 40), padding: EdgeInsets.zero, ), child: Text( 'Skip', style: TextStyle( fontFamily: 'Poppins', fontSize: 16, color: const Color(0xFF4A3C3C).withOpacity(0.6), fontWeight: FontWeight.w400, ), ), ), // Page Indicator (center) Row( mainAxisSize: MainAxisSize.min, children: List.generate( _pages.length, (index) => AnimatedContainer( duration: const Duration(milliseconds: 300), margin: const EdgeInsets.symmetric(horizontal: 4), width: _currentPage == index ? 32 : 8, height: 8, decoration: BoxDecoration( color: _currentPage == index ? const Color(0xFF5A4A3A) : Colors.grey[300], borderRadius: BorderRadius.circular(4), ), ), ), ), // Arrow button (right) with shadow overlay - CIRCULAR Stack( clipBehavior: Clip.none, children: [ // Shadow overlay (offset to top) Positioned( top: -4, left: 4, right: -4, bottom: 4, child: Container( width: 52, height: 52, decoration: BoxDecoration( color: const Color(0xFF5A4A3A).withOpacity(0.3), shape: BoxShape.circle, ), ), ), // Main button - CIRCULAR with touch animation Material( color: const Color(0xFF5A4A3A), shape: const CircleBorder(), child: InkWell( onTap: _onNext, customBorder: const CircleBorder(), splashColor: Colors.white.withOpacity(0.3), highlightColor: Colors.white.withOpacity(0.1), child: Container( width: 52, height: 52, decoration: const BoxDecoration( shape: BoxShape.circle, ), child: const Icon( Icons.arrow_forward, color: Colors.white, size: 24, ), ), ), ), ], ), ], ), ), ], ), ), ); } } class OnboardingPage extends StatelessWidget { final OnboardingData data; const OnboardingPage({super.key, required this.data}); @override Widget build(BuildContext context) { // Define the color with 85% opacity final textColor = const Color(0xFF4A3C3C).withOpacity(0.85); return Padding( padding: const EdgeInsets.all(24.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // Image Expanded( flex: 3, child: Image.asset(data.image, fit: BoxFit.contain), ), const SizedBox(height: 48), // Title Text( data.title, style: TextStyle( fontFamily: 'Poppins', fontSize: 24, fontWeight: FontWeight.w600, // SemiBold color: textColor, height: 1.3, ), textAlign: TextAlign.center, ), const SizedBox(height: 16), // Description Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Text( data.description, style: TextStyle( fontFamily: 'Poppins', fontSize: 14, fontWeight: FontWeight.w400, // Regular color: textColor.withOpacity(0.8), height: 1.6, ), textAlign: TextAlign.center, ), ), const SizedBox(height: 48), ], ), ); } } class OnboardingData { final String image; final String title; final String description; OnboardingData({ required this.image, required this.title, required this.description, }); }