This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../common/extension/extension.dart';
|
||||
import '../../../../common/theme/theme.dart';
|
||||
import '../../../../domain/analytic/analytic.dart';
|
||||
import '../../../components/spacer/spacer.dart';
|
||||
|
||||
/// Warna tetap untuk tiap pos bagi hasil supaya konsisten di semua bagian.
|
||||
class ProfitSharingColor {
|
||||
static const Color purchase = Color(0xFF2196F3);
|
||||
static const Color owner = Color(0xFF4CAF50);
|
||||
static const Color team = Color(0xFFFF9800);
|
||||
}
|
||||
|
||||
class ProfitSharingAllocation extends StatelessWidget {
|
||||
final ProfitSharingBudget budget;
|
||||
|
||||
const ProfitSharingAllocation({super.key, required this.budget});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final total = budget.total;
|
||||
final percentages = budget.percentages;
|
||||
|
||||
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.profit_sharing_allocation,
|
||||
style: AppStyle.lg.copyWith(
|
||||
fontWeight: FontWeight.w700,
|
||||
color: AppColor.textPrimary,
|
||||
),
|
||||
),
|
||||
|
||||
const SpaceHeight(16),
|
||||
|
||||
ProfitSharingBar(
|
||||
purchase: percentages.purchase,
|
||||
owner: percentages.owner,
|
||||
team: percentages.team,
|
||||
),
|
||||
|
||||
const SpaceHeight(20),
|
||||
|
||||
_row(
|
||||
context: context,
|
||||
color: ProfitSharingColor.purchase,
|
||||
label: context.lang.share_purchase,
|
||||
percentage: percentages.purchase,
|
||||
amount: total.limitPurchase,
|
||||
),
|
||||
const Divider(height: 24, color: AppColor.borderLight),
|
||||
_row(
|
||||
context: context,
|
||||
color: ProfitSharingColor.owner,
|
||||
label: context.lang.share_owner,
|
||||
percentage: percentages.owner,
|
||||
amount: total.limitOwner,
|
||||
),
|
||||
const Divider(height: 24, color: AppColor.borderLight),
|
||||
_row(
|
||||
context: context,
|
||||
color: ProfitSharingColor.team,
|
||||
label: context.lang.share_team,
|
||||
percentage: percentages.team,
|
||||
amount: total.limitTeam,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _row({
|
||||
required BuildContext context,
|
||||
required Color color,
|
||||
required String label,
|
||||
required double percentage,
|
||||
required int amount,
|
||||
}) {
|
||||
return Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 10,
|
||||
height: 10,
|
||||
decoration: BoxDecoration(color: color, shape: BoxShape.circle),
|
||||
),
|
||||
const SpaceWidth(10),
|
||||
Text(
|
||||
label,
|
||||
style: AppStyle.md.copyWith(
|
||||
color: AppColor.textPrimary,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
const SpaceWidth(8),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
|
||||
decoration: BoxDecoration(
|
||||
color: color.withOpacity(0.12),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
child: Text(
|
||||
'${percentage.toStringAsFixed(percentage % 1 == 0 ? 0 : 1)}%',
|
||||
style: AppStyle.xs.copyWith(
|
||||
color: color,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Flexible(
|
||||
child: Text(
|
||||
amount.currencyFormatRp,
|
||||
textAlign: TextAlign.right,
|
||||
style: AppStyle.md.copyWith(
|
||||
color: AppColor.textPrimary,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Bar proporsi belanja / owner / tim.
|
||||
class ProfitSharingBar extends StatelessWidget {
|
||||
final double purchase;
|
||||
final double owner;
|
||||
final double team;
|
||||
final double height;
|
||||
|
||||
const ProfitSharingBar({
|
||||
super.key,
|
||||
required this.purchase,
|
||||
required this.owner,
|
||||
required this.team,
|
||||
this.height = 12,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final total = purchase + owner + team;
|
||||
if (total <= 0) {
|
||||
return Container(
|
||||
height: height,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.borderLight,
|
||||
borderRadius: BorderRadius.circular(height),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(height),
|
||||
child: SizedBox(
|
||||
height: height,
|
||||
child: Row(
|
||||
children: [
|
||||
_segment(purchase, ProfitSharingColor.purchase),
|
||||
_segment(owner, ProfitSharingColor.owner),
|
||||
_segment(team, ProfitSharingColor.team),
|
||||
].whereType<Widget>().toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Segmen dilewati saat porsinya 0 supaya Expanded tidak dipakai dengan flex 0.
|
||||
Widget? _segment(double value, Color color) {
|
||||
final flex = (value * 100).round();
|
||||
if (flex <= 0) return null;
|
||||
return Expanded(
|
||||
flex: flex,
|
||||
child: Container(color: color),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user