2025-09-18 13:01:31 +07:00

201 lines
5.6 KiB
Dart

import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../../application/auth/auth_bloc.dart';
import '../../../../../application/customer/customer_point_loader/customer_point_loader_bloc.dart';
import '../../../../../common/theme/theme.dart';
import '../../../../components/image/image.dart';
import '../../../../router/app_router.gr.dart';
import 'widgets/feature_section.dart';
import 'widgets/lottery_card.dart';
import 'widgets/point_card.dart';
import 'widgets/popular_merchant_section.dart';
@RoutePage()
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _currentCarouselIndex = 0;
final CarouselSliderController _carouselController =
CarouselSliderController();
final List<String> _carouselImages = [
'https://images.unsplash.com/photo-1509042239860-f550ce710b93?w=800&h=400&fit=crop',
'https://images.unsplash.com/photo-1495474472287-4d71bcdd2085?w=800&h=400&fit=crop',
'https://images.unsplash.com/photo-1461023058943-07fcbe16d735?w=800&h=400&fit=crop',
'https://images.unsplash.com/photo-1574848794584-c740d6a5595f?w=800&h=400&fit=crop',
];
@override
void initState() {
super.initState();
if (context.read<AuthBloc>().state.isAuthenticated) {
context.read<CustomerPointLoaderBloc>().add(
CustomerPointLoaderEvent.fetched(),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildHeaderSection(),
const SizedBox(height: 70),
HomeFeatureSection(),
HomeLotteryBanner(onTap: () => context.router.push(DrawRoute())),
HomePopularMerchantSection(),
],
),
),
);
}
Widget _buildHeaderSection() {
return Stack(
clipBehavior: Clip.none,
children: [
_buildCarouselBanner(),
_buildNotificationButton(),
Positioned(
left: 0,
right: 0,
top: 225,
child: _buildCarouselIndicators(),
),
Positioned(
left: 16,
right: 16,
top: 240,
child: HomePointCard(
point: context
.read<CustomerPointLoaderBloc>()
.state
.customerPoint
.totalPoints
.toString(),
),
),
],
);
}
// Notification Button
Widget _buildNotificationButton() {
return Positioned(
top: MediaQuery.of(context).padding.top + 10,
right: 16,
child: GestureDetector(
onTap: () => context.router.push(NotificationRoute()),
child: Stack(
children: [
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: AppColor.black.withOpacity(0.3),
shape: BoxShape.circle,
),
child: const Icon(
Icons.notifications_outlined,
color: AppColor.white,
size: 20,
),
),
Positioned(
right: 8,
top: 8,
child: Container(
width: 8,
height: 8,
decoration: const BoxDecoration(
color: AppColor.primary,
shape: BoxShape.circle,
),
),
),
],
),
),
);
}
// Carousel Banner (Full Width)
Widget _buildCarouselBanner() {
return CarouselSlider(
carouselController: _carouselController,
options: CarouselOptions(
height: 280,
viewportFraction: 1.0, // Full width
enlargeCenterPage: false,
autoPlay: true,
autoPlayInterval: const Duration(seconds: 4),
onPageChanged: (index, reason) {
setState(() {
_currentCarouselIndex = index;
});
},
),
items: _carouselImages
.skip(1)
.map((imageUrl) => _buildImageSlide(imageUrl))
.toList(),
);
}
Widget _buildImageSlide(String imageUrl) {
return SizedBox(
width: double.infinity,
child: Image.network(
imageUrl,
fit: BoxFit.cover,
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) return child;
return Container(
color: AppColor.textLight,
child: const Center(
child: CircularProgressIndicator(color: AppColor.primary),
),
);
},
errorBuilder: (context, error, stackTrace) {
return ImagePlaceholder();
},
),
);
}
Widget _buildCarouselIndicators() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(4, (index) {
return GestureDetector(
onTap: () => _carouselController.animateToPage(index),
child: Container(
width: _currentCarouselIndex == index ? 24 : 8,
height: 8,
margin: const EdgeInsets.symmetric(horizontal: 3),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
color: _currentCarouselIndex == index
? AppColor.primary
: AppColor.textLight,
),
),
);
}),
);
}
}