From 9f50189cd1286b3327c8a41bf1ef081020317603 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Tue, 8 Jul 2025 10:56:13 +0000 Subject: [PATCH] Fix: Close batch assign modal on outside click feat: Add break even price to job metrics, rename min price --- src/components/BatchTransactionForm.tsx | 10 ++- src/components/JobCardDetails.tsx | 82 +++++++++++++++++-------- 2 files changed, 66 insertions(+), 26 deletions(-) diff --git a/src/components/BatchTransactionForm.tsx b/src/components/BatchTransactionForm.tsx index ec704a8..f7a0c15 100644 --- a/src/components/BatchTransactionForm.tsx +++ b/src/components/BatchTransactionForm.tsx @@ -208,8 +208,14 @@ const BatchTransactionForm: React.FC = ({ onClose, on ); return ( -
- +
+ e.stopPropagation()} + > Batch Transaction Assignment
); }; -interface MinPriceDisplayProps { +interface PriceDisplayProps { job: IndJob; } -const MinPriceDisplay: React.FC = ({ job }) => { +const PriceDisplay: React.FC = ({ job }) => { const { copying, copyToClipboard } = useClipboard(); const [salesTax, setSalesTax] = useState(() => parseFloat(localStorage.getItem('salesTax') || '0') / 100); @@ -175,34 +175,68 @@ const MinPriceDisplay: React.FC = ({ job }) => { return () => window.removeEventListener('storage', handleStorageChange); }, []); - const minPricePerUnit = job.projectedRevenue / job.produced; - const minPriceWithTax = minPricePerUnit * (1 + salesTax); + // Calculate total costs + const totalCosts = job.expenditures?.reduce((sum, tx) => sum + tx.totalPrice, 0) || 0; - const handleCopyPrice = async (e: React.MouseEvent) => { + // Target price (based on projected revenue) + const targetPricePerUnit = job.projectedRevenue / job.produced; + const targetPriceWithTax = targetPricePerUnit * (1 + salesTax); + + // Break-even price (based on actual costs) + const breakEvenPricePerUnit = totalCosts / job.produced; + const breakEvenPriceWithTax = breakEvenPricePerUnit * (1 + salesTax); + + const handleCopyTargetPrice = async (e: React.MouseEvent) => { e.stopPropagation(); await copyToClipboard( - minPriceWithTax.toFixed(2), - 'minPrice', - 'Minimum price copied to clipboard' + targetPriceWithTax.toFixed(2), + 'targetPrice', + 'Target price copied to clipboard' + ); + }; + + const handleCopyBreakEvenPrice = async (e: React.MouseEvent) => { + e.stopPropagation(); + await copyToClipboard( + breakEvenPriceWithTax.toFixed(2), + 'breakEvenPrice', + 'Break-even price copied to clipboard' ); }; return ( -
- - Min Price: - - {formatISK(minPriceWithTax)} - {copying === 'minPrice' && } - - +
+
+ + Target Price: + + {formatISK(targetPriceWithTax)} + {copying === 'targetPrice' && } + +
+ +
+ + Break-even: + + {formatISK(breakEvenPriceWithTax)} + {copying === 'breakEvenPrice' && } + +
+ +
per unit {salesTax > 0 && `(+${(salesTax * 100).toFixed(1)}% tax)`} - +
); };