import 'package:flutter/material.dart'; import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; import '../../../components/spacer/spacer.dart'; import 'profit_sharing_allocation.dart'; /// Ambang kesehatan berdasarkan % HPP riil terhadap omzet. /// Ubah di sini kalau target margin bisnis berubah. class HppThreshold { static const double healthy = 70; static const double watch = 80; } String formatPercent(double value) => '${value.toStringAsFixed(1)}%'; /// Persen fee tanpa desimal kalau nilainya bulat (20% / 22.5%). String formatFeePercent(double value) => '${value.toStringAsFixed(value % 1 == 0 ? 0 : 1)}%'; Color statusColor(double realHppPercentage) { if (realHppPercentage <= HppThreshold.healthy) return AppColor.success; if (realHppPercentage <= HppThreshold.watch) return AppColor.warning; return AppColor.error; } String statusLabel(BuildContext context, double realHppPercentage) { if (realHppPercentage <= HppThreshold.healthy) { return context.lang.status_healthy; } if (realHppPercentage <= HppThreshold.watch) return context.lang.status_watch; return context.lang.status_critical; } /// Pill status margin (Sehat / Waspada / Tidak Sehat). class ProfitSharingStatusBadge extends StatelessWidget { final double realHppPercentage; final bool onDarkBackground; const ProfitSharingStatusBadge({ super.key, required this.realHppPercentage, this.onDarkBackground = false, }); @override Widget build(BuildContext context) { final color = statusColor(realHppPercentage); return Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), decoration: BoxDecoration( color: onDarkBackground ? AppColor.textWhite.withOpacity(0.18) : color.withOpacity(0.12), borderRadius: BorderRadius.circular(20), border: onDarkBackground ? Border.all(color: AppColor.textWhite.withOpacity(0.3)) : null, ), child: Text( statusLabel(context, realHppPercentage), style: AppStyle.xs.copyWith( color: onDarkBackground ? AppColor.textWhite : color, fontWeight: FontWeight.w700, ), ), ); } } /// Strip sorotan SDL: label + persen fee owner di kiri, nominal di kanan. class ProfitSharingSdlStrip extends StatelessWidget { final int amount; final double? feePercent; const ProfitSharingSdlStrip({ super.key, required this.amount, this.feePercent, }); @override Widget build(BuildContext context) { const color = ProfitSharingColor.owner; return Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), decoration: BoxDecoration( color: color.withOpacity(0.08), borderRadius: BorderRadius.circular(10), border: Border.all(color: color.withOpacity(0.2)), ), child: Row( children: [ const Icon( Icons.account_balance_wallet_rounded, color: color, size: 18, ), const SpaceWidth(8), Text( context.lang.sdl, style: AppStyle.sm.copyWith( color: AppColor.textPrimary, fontWeight: FontWeight.w600, ), ), if (feePercent != null) ...[ const SpaceWidth(6), Container( padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), decoration: BoxDecoration( color: color, borderRadius: BorderRadius.circular(6), ), child: Text( formatFeePercent(feePercent!), style: AppStyle.xs.copyWith( color: AppColor.textWhite, fontWeight: FontWeight.w700, ), ), ), ], const SpaceWidth(8), Expanded( child: Text( amount.currencyFormatRp, textAlign: TextAlign.right, style: AppStyle.md.copyWith( color: AppColor.secondaryDark, fontWeight: FontWeight.w800, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), ], ), ); } } /// Deretan angka ringkas di header (latar gelap), dipisah garis tipis. class ProfitSharingHeaderStats extends StatelessWidget { final List<(String label, String value)> stats; const ProfitSharingHeaderStats({super.key, required this.stats}); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.symmetric(vertical: 12), decoration: BoxDecoration( color: AppColor.textWhite.withOpacity(0.14), borderRadius: BorderRadius.circular(14), border: Border.all(color: AppColor.textWhite.withOpacity(0.22)), ), child: IntrinsicHeight( child: Row( children: [ for (var i = 0; i < stats.length; i++) ...[ if (i > 0) VerticalDivider( width: 1, thickness: 1, color: AppColor.textWhite.withOpacity(0.22), ), Expanded( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( stats[i].$1, style: AppStyle.xs.copyWith( color: AppColor.textWhite.withOpacity(0.75), ), maxLines: 1, overflow: TextOverflow.ellipsis, ), const SizedBox(height: 4), FittedBox( fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text( stats[i].$2, style: AppStyle.md.copyWith( color: AppColor.textWhite, fontWeight: FontWeight.w800, ), ), ), ], ), ), ), ], ], ), ), ); } } /// Kotak statistik kecil: ikon, nilai, lalu label. class ProfitSharingStatTile extends StatelessWidget { final IconData icon; final String label; final String value; final Color color; const ProfitSharingStatTile({ super.key, required this.icon, required this.label, required this.value, this.color = AppColor.primary, }); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: AppColor.background, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColor.borderLight), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( width: 30, height: 30, decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(8), ), child: Icon(icon, color: color, size: 16), ), const SpaceHeight(10), Text( value, style: AppStyle.lg.copyWith( color: AppColor.textPrimary, fontWeight: FontWeight.w800, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), const SizedBox(height: 2), Text( label, style: AppStyle.xs.copyWith(color: AppColor.textSecondary), maxLines: 1, overflow: TextOverflow.ellipsis, ), ], ), ); } } /// Label kecil dua baris: judul di atas, nilai di bawah. class ProfitSharingMetric extends StatelessWidget { final String label; final String value; final Color? valueColor; final bool isBold; const ProfitSharingMetric({ super.key, required this.label, required this.value, this.valueColor, this.isBold = false, }); @override Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: AppStyle.xs.copyWith(color: AppColor.textSecondary), maxLines: 1, overflow: TextOverflow.ellipsis, ), const SizedBox(height: 2), Text( value, style: AppStyle.sm.copyWith( color: valueColor ?? AppColor.textPrimary, fontWeight: isBold ? FontWeight.w800 : FontWeight.w600, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ], ); } }