From 1dc07159c195e8ecf51b2e0565c3ed13a42e5684 Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Tue, 8 Jul 2025 13:17:16 +0200 Subject: [PATCH] Enhance PriceDisplay component with adjusted pricing calculations - Added calculations for adjusted target and break-even prices based on remaining revenue and uncovered costs. - Implemented clipboard copy functionality for adjusted prices. - Updated layout to display adjusted prices alongside original calculations for better clarity. --- src/components/JobCardDetails.tsx | 68 +++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/src/components/JobCardDetails.tsx b/src/components/JobCardDetails.tsx index 2e35a16..b659c77 100644 --- a/src/components/JobCardDetails.tsx +++ b/src/components/JobCardDetails.tsx @@ -219,17 +219,29 @@ const PriceDisplay: React.FC = ({ job }) => { return Math.round(num * factor) / factor; }; - // Calculate total costs + // Calculate total costs and income const totalCosts = job.expenditures?.reduce((sum, tx) => sum + tx.totalPrice, 0) || 0; + const totalIncome = job.income?.reduce((sum, tx) => sum + tx.totalPrice, 0) || 0; + const itemsSold = job.income?.reduce((sum, tx) => sum + tx.quantity, 0) || 0; + const itemsRemaining = (job.produced || 0) - itemsSold; - // Target price (based on projected revenue) + // Original calculations (based on full revenue and costs) const targetPricePerUnit = job.projectedRevenue / job.produced; const targetPriceWithTax = roundToSignificantDigits(targetPricePerUnit * (1 + salesTax)); - // Break-even price (based on actual costs) const breakEvenPricePerUnit = totalCosts / job.produced; const breakEvenPriceWithTax = roundToSignificantDigits(breakEvenPricePerUnit * (1 + salesTax)); + // Adjusted calculations (based on remaining revenue and uncovered costs) + const remainingRevenue = job.projectedRevenue - totalIncome; + const uncoveredCosts = totalCosts - totalIncome; + + const adjustedTargetPricePerUnit = itemsRemaining > 0 ? remainingRevenue / itemsRemaining : 0; + const adjustedTargetPriceWithTax = roundToSignificantDigits(adjustedTargetPricePerUnit * (1 + salesTax)); + + const adjustedBreakEvenPricePerUnit = itemsRemaining > 0 ? Math.max(0, uncoveredCosts / itemsRemaining) : 0; + const adjustedBreakEvenPriceWithTax = roundToSignificantDigits(adjustedBreakEvenPricePerUnit * (1 + salesTax)); + const handleCopyTargetPrice = async (e: React.MouseEvent) => { e.stopPropagation(); await copyToClipboard( @@ -248,6 +260,24 @@ const PriceDisplay: React.FC = ({ job }) => { ); }; + const handleCopyAdjustedTargetPrice = async (e: React.MouseEvent) => { + e.stopPropagation(); + await copyToClipboard( + adjustedTargetPriceWithTax.toString(), + 'adjustedTargetPrice', + 'Adjusted target price copied to clipboard' + ); + }; + + const handleCopyAdjustedBreakEvenPrice = async (e: React.MouseEvent) => { + e.stopPropagation(); + await copyToClipboard( + adjustedBreakEvenPriceWithTax.toString(), + 'adjustedBreakEvenPrice', + 'Adjusted break-even price copied to clipboard' + ); + }; + const taxSuffix = salesTax > 0 ? ` (+${(salesTax * 100).toFixed(1)}% tax)` : ''; return ( @@ -283,6 +313,38 @@ const PriceDisplay: React.FC = ({ job }) => { {copying === 'breakEvenPrice' && } + +
+ + Adjusted Target{taxSuffix}: +
+
+ + Adjusted Break-even{taxSuffix}: +
+ +
+ + {formatISK(adjustedTargetPriceWithTax)} + {copying === 'adjustedTargetPrice' && } + +
+
+ + {formatISK(adjustedBreakEvenPriceWithTax)} + {copying === 'adjustedBreakEvenPrice' && } + +
); };