import 'package:flutter/material.dart'; import 'package:line_icons/line_icons.dart'; import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; import '../../../../domain/analytic/analytic.dart'; class FinanceProfitLoss extends StatelessWidget { final ProfitLossSummary data; const FinanceProfitLoss({super.key, required this.data}); @override Widget build(BuildContext context) { return Container( margin: const EdgeInsets.all(16), padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: AppColor.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: AppColor.textLight.withOpacity(0.1), spreadRadius: 1, blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: AppColor.info.withOpacity(0.1), borderRadius: BorderRadius.circular(8), ), child: const Icon( LineIcons.calculator, color: AppColor.info, size: 20, ), ), const SizedBox(width: 12), Text( 'Detail Profit & Loss', style: AppStyle.lg.copyWith(fontWeight: FontWeight.bold), ), ], ), const SizedBox(height: 20), // Total Revenue (Penjualan Kotor) _buildPLItem( 'Penjualan Kotor', data.totalRevenue.currencyFormatRp, AppColor.success, true, ), // Discount (Diskon & Retur) _buildPLItem( 'Diskon & Retur', '- ${data.totalDiscount.currencyFormatRp}', AppColor.error, false, ), const Divider(height: 24), // Net Sales (Penjualan Bersih = Total Revenue - Discount) _buildPLItem( 'Penjualan Bersih', (data.totalRevenue - data.totalDiscount).currencyFormatRp, AppColor.textPrimary, true, isHeader: true, ), const SizedBox(height: 12), // Cost of Goods Sold (HPP) _buildPLItem( 'HPP (Harga Pokok Penjualan)', '- ${data.totalCost.currencyFormatRp}', AppColor.error, false, ), const Divider(height: 24), // Gross Profit (Laba Kotor) _buildPLItem( 'Laba Kotor', data.grossProfit.currencyFormatRp, AppColor.success, true, isHeader: true, showPercentage: true, percentage: '${data.grossProfitMargin.toStringAsFixed(1)}%', ), const SizedBox(height: 12), // Operational Cost (Biaya Operasional) - calculated as difference _buildPLItem( 'Biaya Operasional', '- ${_calculateOperationalCost().currencyFormatRp}', AppColor.error, false, ), const Divider(height: 24), // Net Profit (Laba Bersih) _buildPLItem( 'Laba Bersih', data.netProfit.currencyFormatRp, AppColor.primary, true, isHeader: true, showPercentage: true, percentage: '${data.netProfitMargin.round()}%', ), ], ), ); } Widget _buildPLItem( String title, String amount, Color color, bool isPositive, { bool isHeader = false, bool showPercentage = false, String? percentage, }) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Text( title, style: isHeader ? AppStyle.md.copyWith( fontWeight: FontWeight.bold, color: color, ) : AppStyle.md.copyWith(color: AppColor.textSecondary), ), ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( amount, style: isHeader ? AppStyle.lg.copyWith( fontWeight: FontWeight.bold, color: color, ) : AppStyle.md.copyWith( color: color, fontWeight: FontWeight.w600, ), ), if (showPercentage && percentage != null) Text( percentage, style: AppStyle.xs.copyWith( color: AppColor.textSecondary, fontStyle: FontStyle.italic, ), ), ], ), ], ), ); } // Calculate operational cost as the difference between gross profit and net profit int _calculateOperationalCost() { return data.grossProfit - data.netProfit - data.totalTax; } }