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_detail_loader/profit_sharing_detail_loader_bloc.dart'; import '../../../common/extension/extension.dart'; import '../../../common/theme/theme.dart'; import '../../../domain/analytic/analytic.dart'; import '../../../injection.dart'; import '../../components/spacer/spacer.dart'; import 'widgets/profit_sharing_allocation.dart'; import 'widgets/profit_sharing_detail_header.dart'; import 'widgets/profit_sharing_status.dart'; import 'widgets/profit_sharing_subcategories.dart'; @RoutePage() class ProfitSharingDetailPage extends StatelessWidget implements AutoRouteWrapper { final String parentCategoryId; final String parentCategoryName; final DateTime dateFrom; final DateTime dateTo; const ProfitSharingDetailPage({ super.key, required this.parentCategoryId, required this.parentCategoryName, required this.dateFrom, required this.dateTo, }); @override Widget wrappedRoute(BuildContext context) => BlocProvider( create: (_) => getIt()..add(_fetchEvent()), child: this, ); ProfitSharingDetailLoaderEvent _fetchEvent() => ProfitSharingDetailLoaderEvent.fetched( parentCategoryId: parentCategoryId, dateFrom: dateFrom, dateTo: dateTo, ); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColor.background, body: BlocBuilder< ProfitSharingDetailLoaderBloc, ProfitSharingDetailLoaderState >( builder: (context, state) { return RefreshIndicator( backgroundColor: AppColor.white, color: AppColor.primary, onRefresh: () async { context.read().add( _fetchEvent(), ); await context .read() .stream .firstWhere((s) => !s.isFetching); }, child: CustomScrollView( physics: const AlwaysScrollableScrollPhysics(), slivers: [ SliverToBoxAdapter( child: ProfitSharingDetailHeader( state: state, fallbackTitle: parentCategoryName, ), ), const SliverToBoxAdapter(child: SpaceHeight(16)), if (state.isFetching) SliverToBoxAdapter(child: _buildShimmer()) else ...[ SliverToBoxAdapter( child: _SummaryCard(summary: state.detail.summary), ), const SliverToBoxAdapter(child: SpaceHeight(16)), SliverToBoxAdapter( child: ProfitSharingAllocation( budget: state.detail.budget, ), ), const SliverToBoxAdapter(child: SpaceHeight(16)), SliverToBoxAdapter( child: ProfitSharingSubCategories( categories: state.detail.categories, expandedCategoryId: state.expandedCategoryId, onToggle: (categoryId) => context.read().add( ProfitSharingDetailLoaderEvent.expandedCategoryChanged( categoryId, ), ), ), ), ], const SliverToBoxAdapter(child: SizedBox(height: 100)), ], ), ); }, ), ); } Widget _buildShimmer() { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( children: [ _shimmerBox(height: 160), const SpaceHeight(16), _shimmerBox(height: 240), ], ), ); } 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), ), ), ); } } class _SummaryCard extends StatelessWidget { final ProfitSharingCategory summary; const _SummaryCard({required this.summary}); @override Widget build(BuildContext context) { return Container( margin: const EdgeInsets.symmetric(horizontal: 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( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( context.lang.summary, style: AppStyle.lg.copyWith( fontWeight: FontWeight.w700, color: AppColor.textPrimary, ), ), const SpaceHeight(16), Row( children: [ Expanded( child: ProfitSharingMetric( label: context.lang.sub_category, value: '${summary.categoryCount}', ), ), Expanded( child: ProfitSharingMetric( label: context.lang.products, value: '${summary.productCount}', ), ), Expanded( child: ProfitSharingMetric( label: context.lang.orders, value: summary.orderCount.thousandFormat, ), ), ], ), const Padding( padding: EdgeInsets.symmetric(vertical: 12), child: Divider(height: 1, color: AppColor.borderLight), ), Row( children: [ Expanded( child: ProfitSharingMetric( label: context.lang.std_hpp, value: formatPercent(summary.standardHppPercentage), ), ), Expanded( child: ProfitSharingMetric( label: context.lang.real_hpp, value: formatPercent(summary.realHppPercentage), valueColor: statusColor(summary.realHppPercentage), ), ), Expanded( child: ProfitSharingMetric( label: context.lang.gross_profit, value: summary.grossProfit.currencyFormatRp, ), ), ], ), ], ), ); } }