feat: update profit shareing
Build & Deploy iOS to TestFlight / build-and-deploy (push) Canceled after 0s
Build & Deploy iOS to TestFlight / build-and-deploy (push) Canceled after 0s
This commit is contained in:
@@ -9,8 +9,10 @@ import '../../../common/theme/theme.dart';
|
||||
import '../../../domain/analytic/analytic.dart';
|
||||
import '../../../injection.dart';
|
||||
import '../../components/spacer/spacer.dart';
|
||||
import 'widgets/period_label.dart';
|
||||
import 'widgets/profit_sharing_allocation.dart';
|
||||
import 'widgets/profit_sharing_detail_header.dart';
|
||||
import 'widgets/profit_sharing_sdl.dart';
|
||||
import 'widgets/profit_sharing_status.dart';
|
||||
import 'widgets/profit_sharing_subcategories.dart';
|
||||
|
||||
@@ -48,75 +50,116 @@ class ProfitSharingDetailPage extends StatelessWidget
|
||||
return Scaffold(
|
||||
backgroundColor: AppColor.background,
|
||||
body:
|
||||
BlocBuilder<
|
||||
BlocListener<
|
||||
ProfitSharingDetailLoaderBloc,
|
||||
ProfitSharingDetailLoaderState
|
||||
>(
|
||||
builder: (context, state) {
|
||||
return RefreshIndicator(
|
||||
backgroundColor: AppColor.white,
|
||||
color: AppColor.primary,
|
||||
onRefresh: () async {
|
||||
context.read<ProfitSharingDetailLoaderBloc>().add(
|
||||
_fetchEvent(),
|
||||
);
|
||||
await context
|
||||
.read<ProfitSharingDetailLoaderBloc>()
|
||||
.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<ProfitSharingDetailLoaderBloc>().add(
|
||||
ProfitSharingDetailLoaderEvent.expandedCategoryChanged(
|
||||
categoryId,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
const SliverToBoxAdapter(child: SizedBox(height: 100)),
|
||||
],
|
||||
),
|
||||
listenWhen: (previous, current) =>
|
||||
previous.failureOption != current.failureOption,
|
||||
listener: (context, state) {
|
||||
final isNotTeam = state.failureOption.fold(
|
||||
() => false,
|
||||
(f) => f.maybeMap(notTeam: (_) => true, orElse: () => false),
|
||||
);
|
||||
// Kategori induk dimatikan dari team setelah list dimuat:
|
||||
// kembali ke list dengan hasil `true` supaya list memuat ulang.
|
||||
if (isNotTeam) context.router.maybePop(true);
|
||||
},
|
||||
child: _buildContent(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildContent() {
|
||||
return BlocBuilder<
|
||||
ProfitSharingDetailLoaderBloc,
|
||||
ProfitSharingDetailLoaderState
|
||||
>(
|
||||
builder: (context, state) {
|
||||
return RefreshIndicator(
|
||||
backgroundColor: AppColor.white,
|
||||
color: AppColor.primary,
|
||||
onRefresh: () async {
|
||||
context.read<ProfitSharingDetailLoaderBloc>().add(_fetchEvent());
|
||||
await context
|
||||
.read<ProfitSharingDetailLoaderBloc>()
|
||||
.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: _buildSdlSection(context, state.detail),
|
||||
),
|
||||
|
||||
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<ProfitSharingDetailLoaderBloc>().add(
|
||||
ProfitSharingDetailLoaderEvent.expandedCategoryChanged(
|
||||
categoryId,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
const SliverToBoxAdapter(child: SizedBox(height: 100)),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSdlSection(BuildContext context, ProfitSharingDetail detail) {
|
||||
final summary = detail.summary;
|
||||
|
||||
return ProfitSharingSdlSection(
|
||||
sdl: summary.sdl,
|
||||
revenue: summary.totalRevenue,
|
||||
percent: summary.ownerFeePercent,
|
||||
breakdownTitle: context.lang.sdl_per_week,
|
||||
items: [
|
||||
for (final period in detail.budget.weekly.where((e) => e.hasRevenue))
|
||||
ProfitSharingSdlItem(
|
||||
label: formatPeriodLabel(period.periodStart, period.periodEnd),
|
||||
sdl: period.sdl,
|
||||
revenue: period.revenue,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildShimmer() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
@@ -187,6 +230,7 @@ class _SummaryCard extends StatelessWidget {
|
||||
icon: Icons.category_rounded,
|
||||
label: context.lang.sub_category,
|
||||
value: '${summary.categoryCount}',
|
||||
color: ProfitSharingColor.subCategory,
|
||||
),
|
||||
),
|
||||
const SpaceWidth(10),
|
||||
@@ -195,7 +239,7 @@ class _SummaryCard extends StatelessWidget {
|
||||
icon: Icons.inventory_2_rounded,
|
||||
label: context.lang.products,
|
||||
value: '${summary.productCount}',
|
||||
color: AppColor.info,
|
||||
color: ProfitSharingColor.product,
|
||||
),
|
||||
),
|
||||
const SpaceWidth(10),
|
||||
@@ -204,20 +248,13 @@ class _SummaryCard extends StatelessWidget {
|
||||
icon: Icons.receipt_long_rounded,
|
||||
label: context.lang.orders,
|
||||
value: summary.orderCount.thousandFormat,
|
||||
color: AppColor.warning,
|
||||
color: ProfitSharingColor.order,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
const SpaceHeight(12),
|
||||
|
||||
ProfitSharingSdlStrip(
|
||||
amount: summary.sdl,
|
||||
feePercent: summary.ownerFeePercent,
|
||||
),
|
||||
|
||||
const SpaceHeight(12),
|
||||
const SpaceHeight(16),
|
||||
|
||||
Row(
|
||||
children: [
|
||||
|
||||
Reference in New Issue
Block a user