201 lines
5.6 KiB
Dart
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,
|
|
),
|
|
),
|
|
);
|
|
}),
|
|
);
|
|
}
|
|
}
|