import 'package:carousel_slider/carousel_slider.dart'; import 'package:cb_prestige_qr/core/presentation/widgets/global_loading_overlay.dart'; import 'package:cb_prestige_qr/features/history/presentation/widgets/history_item_tile.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import '../viewmodels/home_ui_state.dart'; import '../viewmodels/home_view_model.dart'; import '../widgets/home_today_summary_section.dart'; class HomeView extends ConsumerWidget { const HomeView({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final theme = Theme.of(context); final viewModel = ref.read(homeViewModelProvider.notifier); final stateAsync = ref.watch(homeViewModelProvider); return Scaffold( backgroundColor: theme.scaffoldBackgroundColor, appBar: AppBar( elevation: 0, scrolledUnderElevation: 0, titleSpacing: 16, title: Row( children: [ Image.asset( 'assets/images/logo_white.png', height: 60, fit: BoxFit.contain, ), const Spacer(), Image.asset( 'assets/images/cb_logo_white.png', height: 50, fit: BoxFit.contain, ), ], ), ), body: stateAsync.when( data: (state) => _HomeBody( state: state, onSeeAll: viewModel.onSeeAllTapped, onRecentScanTap: viewModel.onRecentScanTapped, ), loading: () => const GlobalLoadingOverlay(isLoading: true), error: (error, stackTrace) => Center( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( mainAxisSize: MainAxisSize.min, children: [ const Text('Failed to load Home'), const SizedBox(height: 10), TextButton( onPressed: () => ref.invalidate(homeViewModelProvider), child: const Text('Retry'), ), ], ), ), ), ), ); } } class _HomeBody extends StatelessWidget { const _HomeBody({ required this.state, required this.onSeeAll, required this.onRecentScanTap, }); final HomeUiState state; final VoidCallback onSeeAll; final void Function(int index) onRecentScanTap; @override Widget build(BuildContext context) { final shellBottomInset = 70 + MediaQuery.of(context).padding.bottom; final contentBottomPadding = shellBottomInset + 8; return CustomScrollView( slivers: [ SliverPadding( padding: const EdgeInsets.fromLTRB(16, 10, 16, 0), sliver: SliverToBoxAdapter( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ ClipRRect( borderRadius: BorderRadius.circular(16), child: CarouselSlider( options: CarouselOptions( height: MediaQuery.of(context).size.height * 0.3, viewportFraction: 1.0, autoPlay: true, autoPlayInterval: const Duration(seconds: 3), autoPlayAnimationDuration: const Duration( milliseconds: 800, ), autoPlayCurve: Curves.fastOutSlowIn, ), items: state.carouselAssets.map((assetPath) { return Builder( builder: (BuildContext context) { return SizedBox( width: double.infinity, child: Image.asset(assetPath, fit: BoxFit.cover), ); }, ); }).toList(), ), ), const SizedBox(height: 20), HomeTodaySummarySection( customersLabel: '18', earnedCoinsLabel: '+3,240', redeemedCoinsLabel: '-1,120', onViewDetailsTap: onSeeAll, ), const SizedBox(height: 16), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( 'Recent History', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), TextButton( onPressed: onSeeAll, style: TextButton.styleFrom( padding: EdgeInsets.zero, minimumSize: Size.zero, tapTargetSize: MaterialTapTargetSize.shrinkWrap, foregroundColor: Colors.blue, ), child: const Text('See All'), ), ], ), const SizedBox(height: 10), ], ), ), ), SliverPadding( padding: EdgeInsets.fromLTRB(16, 0, 16, contentBottomPadding), sliver: state.recentScans.isEmpty ? const SliverToBoxAdapter( child: Padding( padding: EdgeInsets.only(top: 40), child: Center(child: Text('No recent scans')), ), ) : SliverList( delegate: SliverChildBuilderDelegate( (context, index) { if (index.isOdd) return const SizedBox(height: 10); final itemIndex = index ~/ 2; final item = state.recentScans[itemIndex]; final colorScheme = Theme.of(context).colorScheme; return Container( decoration: BoxDecoration( color: colorScheme.surface, borderRadius: BorderRadius.circular(16), border: Border.all( color: colorScheme.outlineVariant.withOpacity(0.5), ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.06), blurRadius: 14, offset: const Offset(0, 6), ), ], ), child: ClipRRect( borderRadius: BorderRadius.circular(16), child: HistoryItemTile( title: item.title, subtitle: item.subtitle, timeLabel: 'Just now', amountLabel: null, isRedeem: null, onTap: () => onRecentScanTap(itemIndex), ), ), ); }, childCount: state.recentScans.isEmpty ? 0 : state.recentScans.length * 2 - 1, ), ), ), ], ); } }