201 lines
5.7 KiB
Dart
201 lines
5.7 KiB
Dart
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.
|
|
/// Sengaja pakai warna jenuh, bukan default Material yang pucat.
|
|
class ProfitSharingColor {
|
|
static const Color owner = Color(0xFF00B341);
|
|
static const Color team = Color(0xFFFF6A00);
|
|
|
|
// Status margin (Sehat / Waspada / Tidak Sehat).
|
|
static const Color healthy = Color(0xFF00B341);
|
|
static const Color watch = Color(0xFFFF9500);
|
|
static const Color critical = Color(0xFFFF1E3C);
|
|
|
|
// Tile ringkasan.
|
|
static const Color subCategory = AppColor.primary;
|
|
static const Color product = Color(0xFF7B2FF7);
|
|
static const Color order = Color(0xFF00A3D9);
|
|
}
|
|
|
|
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;
|
|
// Fee owner berbeda tiap kategori induk, jadi porsi dihitung dari
|
|
// nominalnya; persentase bawaan hanya dipakai saat belum ada omzet.
|
|
final sdlPercentage = total.hasRevenue
|
|
? total.sdlPercentage
|
|
: percentages.owner;
|
|
final teamPercentage = total.hasRevenue
|
|
? total.teamPercentage
|
|
: percentages.team;
|
|
|
|
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(owner: sdlPercentage, team: teamPercentage),
|
|
|
|
const SpaceHeight(20),
|
|
|
|
_row(
|
|
context: context,
|
|
color: ProfitSharingColor.owner,
|
|
label: context.lang.sdl,
|
|
percentage: sdlPercentage,
|
|
amount: total.sdl,
|
|
),
|
|
const Divider(height: 24, color: AppColor.borderLight),
|
|
_row(
|
|
context: context,
|
|
color: ProfitSharingColor.team,
|
|
label: context.lang.share_team,
|
|
percentage: teamPercentage,
|
|
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,
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
child: Text(
|
|
'${percentage.toStringAsFixed(percentage % 1 == 0 ? 0 : 1)}%',
|
|
style: AppStyle.xs.copyWith(
|
|
color: AppColor.textWhite,
|
|
fontWeight: FontWeight.w800,
|
|
),
|
|
),
|
|
),
|
|
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 SDL (owner) / tim dalam persen omzet. Sisa yang belum terbagi
|
|
/// (backend lama masih menyisihkan porsi belanja) tampil sebagai track kosong.
|
|
class ProfitSharingBar extends StatelessWidget {
|
|
final double owner;
|
|
final double team;
|
|
final double height;
|
|
|
|
const ProfitSharingBar({
|
|
super.key,
|
|
required this.owner,
|
|
required this.team,
|
|
this.height = 12,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final total = 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(owner, ProfitSharingColor.owner),
|
|
_segment(team, ProfitSharingColor.team),
|
|
_segment(100 - total, AppColor.borderLight),
|
|
].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),
|
|
);
|
|
}
|
|
}
|