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)}%'; /// Versi lebih gelap dari [color], dipakai sebagai ujung gradien. Color darken(Color color, [double amount = 0.2]) => Color.lerp(color, AppColor.black, amount)!; Color statusColor(double realHppPercentage) { if (realHppPercentage <= HppThreshold.healthy) { return ProfitSharingColor.healthy; } if (realHppPercentage <= HppThreshold.watch) return ProfitSharingColor.watch; return ProfitSharingColor.critical; } 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); // Di atas header merah, pill putih supaya status merah tidak tenggelam. return Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), decoration: BoxDecoration( color: onDarkBackground ? AppColor.white : color, borderRadius: BorderRadius.circular(20), ), child: Text( statusLabel(context, realHppPercentage), style: AppStyle.xs.copyWith( color: onDarkBackground ? color : AppColor.textWhite, fontWeight: FontWeight.w800, ), ), ); } } /// Kartu item di dalam section: latar putih, garis aksen berwarna di kiri. /// Child boleh berisi InkWell; ripple-nya ikut terpotong sudut kartu. class ProfitSharingItemCard extends StatelessWidget { final Widget child; final Color accentColor; const ProfitSharingItemCard({ super.key, required this.child, this.accentColor = AppColor.primary, }); @override Widget build(BuildContext context) { return Container( clipBehavior: Clip.antiAlias, decoration: BoxDecoration( color: AppColor.white, borderRadius: BorderRadius.circular(14), border: Border.all(color: AppColor.border), boxShadow: [ BoxShadow( color: AppColor.black.withOpacity(0.05), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Stack( children: [ Material(type: MaterialType.transparency, child: child), Positioned( left: 0, top: 0, bottom: 0, child: Container(width: 4, color: accentColor), ), ], ), ); } } /// Pill persen fee owner. Di atas latar berwarna jadi putih supaya terbaca. class ProfitSharingFeeBadge extends StatelessWidget { final double feePercent; final Color color; final bool onDarkBackground; const ProfitSharingFeeBadge({ super.key, required this.feePercent, this.color = ProfitSharingColor.owner, this.onDarkBackground = false, }); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), decoration: BoxDecoration( color: onDarkBackground ? AppColor.white : color, borderRadius: BorderRadius.circular(6), ), child: Text( formatFeePercent(feePercent), style: AppStyle.xs.copyWith( color: onDarkBackground ? color : AppColor.textWhite, fontWeight: FontWeight.w800, ), ), ); } } /// 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, ), ), ), ], ), ), ), ], ], ), ), ); } } /// Kartu statistik kecil berwarna solid: 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( gradient: LinearGradient( colors: [color, darken(color)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: color.withOpacity(0.3), blurRadius: 8, offset: const Offset(0, 3), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( width: 30, height: 30, decoration: BoxDecoration( color: AppColor.textWhite.withOpacity(0.2), borderRadius: BorderRadius.circular(8), ), child: Icon(icon, color: AppColor.textWhite, size: 16), ), const SpaceHeight(10), FittedBox( fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text( value, style: AppStyle.lg.copyWith( color: AppColor.textWhite, fontWeight: FontWeight.w800, ), ), ), const SizedBox(height: 2), Text( label, style: AppStyle.xs.copyWith( color: AppColor.textWhite.withOpacity(0.85), fontWeight: FontWeight.w600, ), 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, ), ], ); } }