import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../application/analytic/category_analytic_loader/category_analytic_loader_bloc.dart'; import '../../../application/analytic/payment_method_analytic_loader/payment_method_analytic_loader_bloc.dart'; import '../../../application/analytic/product_analytic_loader/product_analytic_loader_bloc.dart'; import '../../../application/analytic/sales_loader/sales_loader_bloc.dart'; import '../../../common/theme/theme.dart'; import '../../../injection.dart'; import '../../components/spacer/spacer.dart'; import 'widgets/sales_category_card.dart'; import 'widgets/sales_header.dart'; import 'widgets/sales_payment_method_card.dart'; import 'widgets/sales_rincian_card.dart'; import 'widgets/sales_top_products_card.dart'; @RoutePage() class SalesPage extends StatefulWidget implements AutoRouteWrapper { const SalesPage({super.key}); @override State createState() => _SalesPageState(); @override Widget wrappedRoute(BuildContext context) => MultiBlocProvider( providers: [ BlocProvider( create: (context) => getIt()..add(SalesLoaderEvent.fectched()), ), BlocProvider( create: (context) => getIt() ..add(const PaymentMethodAnalyticLoaderEvent.fetched()), ), BlocProvider( create: (context) => getIt() ..add(const CategoryAnalyticLoaderEvent.fetched()), ), BlocProvider( create: (context) => getIt() ..add(const ProductAnalyticLoaderEvent.fetched()), ), ], child: this, ); } class _SalesPageState extends State with SingleTickerProviderStateMixin { late AnimationController _fadeController; late Animation _fadeAnimation; @override void initState() { super.initState(); _fadeController = AnimationController( duration: const Duration(milliseconds: 600), vsync: this, ); _fadeAnimation = CurvedAnimation( parent: _fadeController, curve: Curves.easeOut, ); Future.delayed(const Duration(milliseconds: 300), () { _fadeController.forward(); }); } @override void dispose() { _fadeController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColor.background, body: BlocBuilder( builder: (context, salesState) { return CustomScrollView( slivers: [ // Header SliverToBoxAdapter( child: SalesHeader( state: salesState, onDateRangeChanged: (startDate, endDate) { _onDateRangeChanged(context, startDate, endDate); }, ), ), // Rincian Penjualan SliverToBoxAdapter( child: FadeTransition( opacity: _fadeAnimation, child: Padding( padding: const EdgeInsets.all(16), child: SalesRincianCard(state: salesState), ), ), ), // Metode Pembayaran SliverToBoxAdapter( child: FadeTransition( opacity: _fadeAnimation, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: BlocBuilder< PaymentMethodAnalyticLoaderBloc, PaymentMethodAnalyticLoaderState >( builder: (context, paymentState) { return SalesPaymentMethodCard( paymentMethodAnalytic: paymentState.paymentMethodAnalytic, isFetching: paymentState.isFetching, ); }, ), ), ), ), // Penjualan per Kategori SliverToBoxAdapter( child: FadeTransition( opacity: _fadeAnimation, child: Padding( padding: const EdgeInsets.all(16), child: BlocBuilder< CategoryAnalyticLoaderBloc, CategoryAnalyticLoaderState >( builder: (context, categoryState) { return SalesCategoryCard( categoryAnalytic: categoryState.categoryAnalytic, isFetching: categoryState.isFetching, ); }, ), ), ), ), // Produk Terlaris SliverToBoxAdapter( child: FadeTransition( opacity: _fadeAnimation, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: BlocBuilder< ProductAnalyticLoaderBloc, ProductAnalyticLoaderState >( builder: (context, productState) { return SalesTopProductsCard( productAnalytic: productState.productAnalytic, isFetching: productState.isFetching, ); }, ), ), ), ), // Bottom Padding const SliverToBoxAdapter(child: SpaceHeight(32)), ], ); }, ), ); } void _onDateRangeChanged( BuildContext context, DateTime startDate, DateTime endDate, ) { // Update sales context.read() ..add(SalesLoaderEvent.rangeDateChanged(startDate, endDate)) ..add(SalesLoaderEvent.fectched()); // Update payment method context.read() ..add( PaymentMethodAnalyticLoaderEvent.rangeDateChanged(startDate, endDate), ) ..add(const PaymentMethodAnalyticLoaderEvent.fetched()); // Update category context.read() ..add(CategoryAnalyticLoaderEvent.rangeDateChanged(startDate, endDate)) ..add(const CategoryAnalyticLoaderEvent.fetched()); // Update product context.read() ..add(ProductAnalyticLoaderEvent.rangeDateChanged(startDate, endDate)) ..add(const ProductAnalyticLoaderEvent.fetched()); } }