/// Page: Home Page /// /// Main dashboard screen of the Worker app. /// Displays member card, promotions, and quick action sections. library; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:go_router/go_router.dart'; import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:shimmer/shimmer.dart'; import 'package:worker/core/router/app_router.dart'; import 'package:worker/core/utils/extensions.dart'; import 'package:worker/features/cart/presentation/providers/cart_provider.dart'; import 'package:worker/features/home/presentation/providers/member_card_provider.dart'; import 'package:worker/features/home/presentation/providers/promotions_provider.dart'; import 'package:worker/features/home/presentation/widgets/member_card_widget.dart'; import 'package:worker/features/home/presentation/widgets/promotion_slider.dart'; import 'package:worker/features/home/presentation/widgets/quick_action_section.dart'; import 'package:worker/generated/l10n/app_localizations.dart'; /// Home Page /// /// Main entry point of the app after login. /// Shows: /// - Member card (Diamond/Platinum/Gold) /// - Promotional banners /// - Quick action sections /// - Bottom navigation /// - Floating action button (Chat) /// /// Initializes cart on mount to load items from API. class HomePage extends ConsumerStatefulWidget { const HomePage({super.key}); @override ConsumerState createState() => _HomePageState(); } class _HomePageState extends ConsumerState { @override void initState() { super.initState(); // Initialize cart from API on app startup WidgetsBinding.instance.addPostFrameCallback((_) { ref.read(cartProvider.notifier).initialize(); }); } @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context); // Watch member card state final memberCardAsync = ref.watch(memberCardProvider); // Watch promotions state final promotionsAsync = ref.watch(promotionsProvider); // Watch cart item count final cartItemCount = ref.watch(cartItemCountProvider); final colorScheme = context.colorScheme; return Scaffold( backgroundColor: colorScheme.surfaceContainerLowest, body: CustomScrollView( slivers: [ // Add top padding for status bar SliverPadding( padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top), ), // Member Card Section SliverToBoxAdapter( child: memberCardAsync.when( data: (memberCard) => MemberCardWidget(memberCard: memberCard), loading: () => Container( margin: const EdgeInsets.all(16), height: 200, decoration: BoxDecoration( color: colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(16), ), child: const CustomLoadingIndicator(), ), error: (error, stack) => Container( margin: const EdgeInsets.all(16), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: colorScheme.errorContainer, borderRadius: BorderRadius.circular(16), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ FaIcon( FontAwesomeIcons.circleExclamation, color: colorScheme.error, size: 48, ), const SizedBox(height: 8), Text( l10n.error, style: TextStyle( color: colorScheme.error, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 4), Text( error.toString(), style: TextStyle( color: colorScheme.onSurfaceVariant, fontSize: 12, ), textAlign: TextAlign.center, ), ], ), ), ), ), // Promotions Section SliverToBoxAdapter( child: promotionsAsync.when( data: (promotions) => promotions.isNotEmpty ? PromotionSlider( promotions: promotions, onPromotionTap: (promotion) { // Navigate to promotion details context.push('/promotions/${promotion.id}'); }, ) : const SizedBox.shrink(), loading: () => _buildPromotionsShimmer(colorScheme), error: (error, stack) => const SizedBox.shrink(), ), ), // Quick Action Sections SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( children: [ // Products & Cart Section QuickActionSection( title: 'Sản phẩm & Giỏ hàng', actions: [ QuickAction( icon: FontAwesomeIcons.grip, label: 'Sản phẩm', onTap: () => context.pushNamed(RouteNames.products), ), QuickAction( icon: FontAwesomeIcons.cartShopping, label: 'Giỏ hàng', badge: cartItemCount > 0 ? '$cartItemCount' : null, onTap: () => context.push(RouteNames.cart), ), QuickAction( icon: FontAwesomeIcons.heart, label: 'Yêu thích', onTap: () => context.push(RouteNames.favorites), ), ], ), // Orders & Payments Section QuickActionSection( title: 'Đơn hàng & thanh toán', actions: [ QuickAction( icon: FontAwesomeIcons.fileLines, label: 'Chính sách giá', onTap: () => context.push(RouteNames.pricePolicy), ), QuickAction( icon: FontAwesomeIcons.boxesStacked, label: 'Đơn hàng', onTap: () => context.push(RouteNames.orders), ), QuickAction( icon: FontAwesomeIcons.receipt, label: 'Thanh toán', onTap: () => context.push(RouteNames.payments), ), ], ), // Loyalty Section QuickActionSection( title: 'Khách hàng thân thiết', actions: [ QuickAction( icon: FontAwesomeIcons.circlePlus, label: 'Ghi nhận điểm', onTap: () => context.push(RouteNames.pointsRecords), ), QuickAction( icon: FontAwesomeIcons.gift, label: 'Đổi quà', onTap: () => context.push('/loyalty/rewards'), ), QuickAction( icon: FontAwesomeIcons.clockRotateLeft, label: 'Lịch sử điểm', onTap: () => context.push(RouteNames.pointsHistory), ), ], ), // Sample Houses & News Section QuickActionSection( title: 'Nhà mẫu, dự án & tin tức', actions: [ QuickAction( icon: FontAwesomeIcons.houseCircleCheck, label: 'Nhà mẫu', onTap: () => context.push(RouteNames.modelHouses), ), QuickAction( icon: FontAwesomeIcons.building, label: 'Đăng ký dự án', onTap: () => context.push(RouteNames.submissions), ), ], ), // Bottom Padding (for bottom nav clearance) const SizedBox(height: 40), ], ), ), ), ], ), ); } /// Build shimmer loading for promotions section Widget _buildPromotionsShimmer(ColorScheme colorScheme) { return Padding( padding: const EdgeInsets.only(bottom: 8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Title shimmer Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Text( 'Chương trình ưu đãi', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w700, color: colorScheme.onSurface, ), ), ), const SizedBox(height: 12), // Cards shimmer SizedBox( height: 210, child: ListView.builder( scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 16), itemCount: 3, itemBuilder: (context, index) { return Shimmer.fromColors( baseColor: colorScheme.surfaceContainerHighest, highlightColor: colorScheme.surface, child: Container( width: 280, margin: const EdgeInsets.only(right: 12), decoration: BoxDecoration( color: colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Image placeholder Container( height: 140, decoration: BoxDecoration( color: colorScheme.surfaceContainerHighest, borderRadius: const BorderRadius.vertical( top: Radius.circular(12), ), ), ), // Text placeholders Padding( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( width: 200, height: 16, decoration: BoxDecoration( color: colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(4), ), ), const SizedBox(height: 8), Container( width: 140, height: 12, decoration: BoxDecoration( color: colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(4), ), ), ], ), ), ], ), ), ); }, ), ), ], ), ); } }