import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:shimmer/shimmer.dart'; import '../../../application/analytic/profit_sharing_loader/profit_sharing_loader_bloc.dart'; import '../../../common/theme/theme.dart'; import '../../../injection.dart'; import '../../components/field/date_range_picker_field.dart'; import '../../components/spacer/spacer.dart'; import '../../router/app_router.gr.dart'; import 'widgets/profit_sharing_allocation.dart'; import 'widgets/profit_sharing_categories.dart'; import 'widgets/profit_sharing_header.dart'; import 'widgets/profit_sharing_periods.dart'; @RoutePage() class ProfitSharingPage extends StatefulWidget implements AutoRouteWrapper { const ProfitSharingPage({super.key}); @override State createState() => _ProfitSharingPageState(); @override Widget wrappedRoute(BuildContext context) => BlocProvider( create: (_) => getIt() ..add(ProfitSharingLoaderEvent.fetched()), child: this, ); } class _ProfitSharingPageState extends State with SingleTickerProviderStateMixin { late AnimationController _fadeController; late Animation _fadeAnimation; @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( listenWhen: (previous, current) => previous.dateFrom != current.dateFrom || previous.dateTo != current.dateTo, listener: (context, state) { context.read().add( const ProfitSharingLoaderEvent.fetched(), ); }, child: BlocBuilder( builder: (context, state) { return RefreshIndicator( backgroundColor: AppColor.white, color: AppColor.primary, onRefresh: () async { context.read().add( const ProfitSharingLoaderEvent.fetched(), ); await context.read().stream.firstWhere( (s) => !s.isFetching, ); }, child: CustomScrollView( physics: const AlwaysScrollableScrollPhysics(), slivers: [ SliverToBoxAdapter( child: FadeTransition( opacity: _fadeAnimation, child: ProfitSharingHeader(state: state), ), ), SliverToBoxAdapter( child: FadeTransition( opacity: _fadeAnimation, child: Padding( padding: const EdgeInsets.all(16), child: DateRangePickerField( startDate: state.dateFrom, endDate: state.dateTo, onChanged: (startDate, endDate) { if (startDate == null || endDate == null) return; context.read().add( ProfitSharingLoaderEvent.rangeDateChanged( startDate, endDate, ), ); }, ), ), ), ), if (state.isFetching) SliverToBoxAdapter(child: _buildShimmer()) else ...[ SliverToBoxAdapter( child: FadeTransition( opacity: _fadeAnimation, child: ProfitSharingCategories( categories: state.profitSharing.categories, onCategoryTap: (category) => context.router.push( ProfitSharingDetailRoute( parentCategoryId: category.parentCategoryId, parentCategoryName: category.parentCategoryName, dateFrom: state.dateFrom, dateTo: state.dateTo, ), ), ), ), ), const SliverToBoxAdapter(child: SpaceHeight(16)), SliverToBoxAdapter( child: FadeTransition( opacity: _fadeAnimation, child: ProfitSharingAllocation( budget: state.profitSharing.budget, ), ), ), const SliverToBoxAdapter(child: SpaceHeight(16)), SliverToBoxAdapter( child: FadeTransition( opacity: _fadeAnimation, child: ProfitSharingPeriods( state: state, onPeriodTypeChanged: (type) { context.read().add( ProfitSharingLoaderEvent.periodTypeChanged(type), ); }, ), ), ), ], const SliverToBoxAdapter(child: SizedBox(height: 100)), ], ), ); }, ), ), ); } Widget _buildShimmer() { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( children: [ _shimmerBox(height: 240), const SpaceHeight(16), _shimmerBox(height: 300), ], ), ); } Widget _shimmerBox({required double height}) { return Shimmer.fromColors( baseColor: Colors.grey[300]!, highlightColor: Colors.grey[100]!, child: Container( height: height, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), ), ), ); } }