import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.dart'; import '../../../common/theme/theme.dart'; import '../../../injection.dart'; import '../../components/spacer/spacer.dart'; import 'widgets/inventory_header.dart'; import 'widgets/inventory_stock_report.dart'; @RoutePage() class InventoryPage extends StatefulWidget implements AutoRouteWrapper { const InventoryPage({super.key}); @override State createState() => _InventoryPageState(); @override Widget wrappedRoute(BuildContext context) => BlocProvider( create: (_) => getIt() ..add(InventoryAnalyticLoaderEvent.fetched()), child: this, ); } class _InventoryPageState extends State with SingleTickerProviderStateMixin { late AnimationController _fadeController; late Animation _fadeAnimation; int _selectedTabIndex = 0; @override void initState() { super.initState(); _fadeController = AnimationController( duration: const Duration(milliseconds: 1000), vsync: this, ); _fadeAnimation = Tween( begin: 0.0, end: 1.0, ).animate(CurvedAnimation(parent: _fadeController, curve: Curves.easeIn)); _fadeController.forward(); } @override void dispose() { _fadeController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColor.background, body: BlocListener< InventoryAnalyticLoaderBloc, InventoryAnalyticLoaderState >( listenWhen: (previous, current) => previous.dateFrom != current.dateFrom || previous.dateTo != current.dateTo, listener: (context, state) { context.read().add( InventoryAnalyticLoaderEvent.fetched(), ); }, child: BlocBuilder< InventoryAnalyticLoaderBloc, InventoryAnalyticLoaderState >( builder: (context, state) { return CustomScrollView( slivers: [ // Header with gradient background, tabs, and summary SliverToBoxAdapter( child: FadeTransition( opacity: _fadeAnimation, child: InventoryHeader( state: state, selectedTabIndex: _selectedTabIndex, onTabChanged: (index) { setState(() { _selectedTabIndex = index; }); }, onDateRangeChanged: (startDate, endDate) { _onDateRangeChanged( context, startDate, endDate, ); }, ), ), ), // Stock Report Table SliverToBoxAdapter( child: FadeTransition( opacity: _fadeAnimation, child: state.isFetching ? _buildLoadingReport() : InventoryStockReport( inventoryAnalytic: state.inventoryAnalytic, selectedTabIndex: _selectedTabIndex, ), ), ), // Bottom spacing const SliverToBoxAdapter(child: SpaceHeight(100)), ], ); }, ), ), ); } Widget _buildLoadingReport() { return Container( margin: const EdgeInsets.all(16), padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: AppColor.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: AppColor.textLight.withOpacity(0.08), spreadRadius: 1, blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( children: List.generate( 5, (index) => Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: Row( children: [ Expanded( flex: 4, child: Container( height: 14, decoration: BoxDecoration( color: AppColor.borderLight, borderRadius: BorderRadius.circular(4), ), ), ), const SpaceWidth(12), Expanded( flex: 2, child: Container( height: 14, decoration: BoxDecoration( color: AppColor.borderLight, borderRadius: BorderRadius.circular(4), ), ), ), const SpaceWidth(12), Expanded( flex: 2, child: Container( height: 14, decoration: BoxDecoration( color: AppColor.borderLight, borderRadius: BorderRadius.circular(4), ), ), ), const SpaceWidth(12), Expanded( flex: 2, child: Container( height: 14, decoration: BoxDecoration( color: AppColor.borderLight, borderRadius: BorderRadius.circular(4), ), ), ), ], ), ), ), ), ); } void _onDateRangeChanged( BuildContext context, DateTime startDate, DateTime endDate, ) { context.read().add( InventoryAnalyticLoaderEvent.rangeDateChanged(startDate, endDate), ); } }