209 lines
5.9 KiB
Dart
Raw Normal View History

2025-08-27 15:07:49 +07:00
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:carousel_slider/carousel_slider.dart';
import '../../../common/theme/theme.dart';
import '../../components/assets/assets.gen.dart';
import '../../components/button/button.dart';
import '../../components/image/image.dart';
2025-08-27 16:19:54 +07:00
import '../../router/app_router.gr.dart';
2025-08-27 15:07:49 +07:00
@RoutePage()
class OnboardingPage extends StatefulWidget {
const OnboardingPage({super.key});
@override
State<OnboardingPage> createState() => _OnboardingPageState();
}
class _OnboardingPageState extends State<OnboardingPage> {
int currentIndex = 0;
final CarouselSliderController _carouselController =
CarouselSliderController();
final List<OnboardingData> onboardingData = [
OnboardingData(
image: Assets.images.onboarding1.path,
title: 'Nikmati Hidangan Kapanpun, Dimanapun',
subtitle:
'Bebas pilih cara penyajian, bisa dine-in di restoran atau pesan antar langsung ke lokasimu',
),
OnboardingData(
image: Assets.images.onboarding2.path,
title: 'Bahan Berkualitas Premium',
subtitle:
'Kami hanya menggunakan bahan segar pilihan untuk menghadirkan cita rasa terbaik di setiap hidangan',
),
OnboardingData(
image: Assets.images.onboarding3.path,
title: 'Pesan dengan Praktis',
subtitle:
'Aplikasi dengan tampilan sederhana memudahkanmu memesan makanan favorit kapan saja',
),
];
@override
Widget build(BuildContext context) {
final screenHeight = MediaQuery.of(context).size.height;
final imageHeight = screenHeight * 0.6; // 60% dari tinggi layar
return Scaffold(
backgroundColor: Colors.white, // Changed to white background
body: Column(
children: [
// Image carousel - 60% of screen height
SizedBox(height: imageHeight, child: _buildImageCarousel()),
// Bottom content - remaining space
Expanded(child: _buildBottomContent()),
],
),
);
}
Widget _buildImageCarousel() {
return Stack(
children: [
// Carousel
CarouselSlider.builder(
carouselController: _carouselController,
itemCount: onboardingData.length,
itemBuilder: (context, index, realIndex) {
return SizedBox(
width: double.infinity, // Full width
child: ClipRRect(
child: Image.asset(
onboardingData[index].image,
fit: BoxFit.fill,
width: double.infinity,
errorBuilder: (context, error, stackTrace) {
return ImagePlaceholder();
},
),
),
);
},
options: CarouselOptions(
height: double.infinity,
viewportFraction: 1.0,
enableInfiniteScroll: true,
autoPlay: true,
onPageChanged: (index, reason) {
setState(() {
currentIndex = index;
});
},
),
),
// White overlay gradient at bottom
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
height: 100,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.white.withOpacity(0.1),
Color(0x80FFFFFF), // White with 50% opacity
Colors.white, // Pure white
],
),
),
),
),
// Dots indicator positioned over the white overlay
Positioned(
bottom: 30,
left: 0,
right: 0,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(
onboardingData.length,
(index) => Container(
margin: const EdgeInsets.symmetric(horizontal: 4),
height: 8,
width: currentIndex == index ? 24 : 8,
decoration: BoxDecoration(
color: currentIndex == index
? AppColor.primary
: AppColor.borderLight,
borderRadius: BorderRadius.circular(4),
),
),
),
),
),
],
);
}
Widget _buildBottomContent() {
return Padding(
padding: const EdgeInsets.all(24),
child: Column(
children: [
const SizedBox(height: 16),
// Title
Text(
onboardingData[currentIndex].title,
textAlign: TextAlign.center,
style: AppStyle.xl.copyWith(fontWeight: FontWeight.w800),
),
const SizedBox(height: 12),
// Subtitle
Text(
onboardingData[currentIndex].subtitle,
textAlign: TextAlign.center,
style: AppStyle.md.copyWith(
fontWeight: FontWeight.w500,
color: AppColor.textSecondary,
),
),
const Spacer(),
2025-08-27 16:19:54 +07:00
AppElevatedButton(
onPressed: () => context.router.push(const LoginRoute()),
title: 'Masuk',
),
2025-08-27 15:07:49 +07:00
const SizedBox(height: 12),
TextButton(
2025-08-29 15:30:15 +07:00
onPressed: () => context.router.push(const MainRoute()),
2025-08-27 15:07:49 +07:00
child: Text(
'Lewati tahap ini',
style: AppStyle.md.copyWith(
color: AppColor.textSecondary,
fontWeight: FontWeight.w600,
),
),
),
],
),
);
}
}
class OnboardingData {
final String image;
final String title;
final String subtitle;
OnboardingData({
required this.image,
required this.title,
required this.subtitle,
});
}