From 864e1e98048ef6f0c275423ea1d76d296a88ac33 Mon Sep 17 00:00:00 2001 From: NotII <46204250+NotII@users.noreply.github.com> Date: Thu, 9 Oct 2025 21:05:13 +0100 Subject: [PATCH] Improve pricing tier input handling and precision Refactored PricingTiers component to better handle empty, null, and undefined values, prevent formatting issues, and add error handling for tier changes. Updated ProductModal to use parseFloat for price values to improve precision. Minor robustness improvements to event handling and sorting. --- components/forms/pricing-tiers.tsx | 41 ++++++++++++++++++----------- components/modals/product-modal.tsx | 2 +- package-lock.json | 4 +-- public/git-info.json | 4 +-- 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/components/forms/pricing-tiers.tsx b/components/forms/pricing-tiers.tsx index 578a3ef..4789397 100644 --- a/components/forms/pricing-tiers.tsx +++ b/components/forms/pricing-tiers.tsx @@ -15,15 +15,15 @@ interface PricingTiersProps { } export const PricingTiers = ({ - pricing, + pricing = [], handleTierChange, handleRemoveTier, handleAddTier, }: PricingTiersProps) => { const formatNumber = (num: number) => { - // Only format to 2 decimal places if the number has decimal places - // This prevents cursor jumping when user types whole numbers - return num % 1 === 0 ? num.toString() : num.toFixed(2); + if (isNaN(num) || num === null || num === undefined) return ""; + // Return the number as-is without any formatting to prevent precision issues + return num.toString(); }; const formatTotal = (num: number) => { @@ -39,17 +39,24 @@ export const PricingTiers = ({ index: number, minQuantity: number ) => { + if (!handleTierChange || !e || !e.target) return; + const totalPrice = Number(e.target.value); const pricePerUnit = minQuantity > 0 ? totalPrice / minQuantity : 0; + // Create a simple synthetic event with the raw number const syntheticEvent = { target: { name: 'pricePerUnit', - value: formatNumber(pricePerUnit) + value: pricePerUnit.toString() } } as React.ChangeEvent; - handleTierChange(syntheticEvent, index); + try { + handleTierChange(syntheticEvent, index); + } catch (error) { + console.error('Error in handleTotalChange:', error); + } }; return ( @@ -66,11 +73,13 @@ export const PricingTiers = ({ {[...pricing] - .sort((a, b) => a.minQuantity - b.minQuantity) + .sort((a, b) => (a?.minQuantity || 0) - (b?.minQuantity || 0)) .map((tier, sortedIndex) => { + if (!tier) return null; + // Find the original index for proper event handling const originalIndex = pricing.findIndex(p => - p === tier || (p.minQuantity === tier.minQuantity && p.pricePerUnit === tier.pricePerUnit) + p === tier || (p?.minQuantity === tier?.minQuantity && p?.pricePerUnit === tier?.pricePerUnit) ); return (
handleTierChange(e, originalIndex)} + value={tier?.minQuantity === 0 ? "" : (tier?.minQuantity || "")} + onChange={(e) => handleTierChange?.(e, originalIndex)} className="h-8 text-sm px-2" /> @@ -90,8 +99,8 @@ export const PricingTiers = ({ name="pricePerUnit" type="number" placeholder="Price per unit" - value={tier.pricePerUnit === 0 ? "" : formatNumber(tier.pricePerUnit)} - onChange={(e) => handleTierChange(e, originalIndex)} + value={tier?.pricePerUnit === 0 ? "" : formatNumber(tier?.pricePerUnit || 0)} + onChange={(e) => handleTierChange?.(e, originalIndex)} className="h-8 text-sm px-2" /> @@ -99,11 +108,11 @@ export const PricingTiers = ({ type="number" placeholder="Total price" value={ - tier.minQuantity && tier.pricePerUnit + tier?.minQuantity && tier?.pricePerUnit ? calculateTotal(tier.minQuantity, tier.pricePerUnit) : "" } - onChange={(e) => handleTotalChange(e, originalIndex, tier.minQuantity)} + onChange={(e) => handleTotalChange(e, originalIndex, tier?.minQuantity || 0)} className="h-8 text-sm px-2" /> @@ -111,7 +120,7 @@ export const PricingTiers = ({ variant="ghost" size="icon" className="text-red-500 hover:bg-red-100" - onClick={() => handleRemoveTier(originalIndex)} + onClick={() => handleRemoveTier?.(originalIndex)} > @@ -123,7 +132,7 @@ export const PricingTiers = ({

No pricing tiers added.

)} - diff --git a/components/modals/product-modal.tsx b/components/modals/product-modal.tsx index 19b2ed5..ab928d0 100644 --- a/components/modals/product-modal.tsx +++ b/components/modals/product-modal.tsx @@ -142,7 +142,7 @@ export const ProductModal: React.FC = ({ ...prev, pricing: prev.pricing.map((tier, i) => i === index - ? { ...tier, [name]: value === "" ? 0 : Number(value) } + ? { ...tier, [name]: value === "" ? 0 : parseFloat(value) || 0 } : tier ), })); diff --git a/package-lock.json b/package-lock.json index 113c643..52bf5a3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "my-v0-project", - "version": "2.1.0", + "version": "2.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "my-v0-project", - "version": "2.1.0", + "version": "2.2.0", "dependencies": { "@hookform/resolvers": "^3.9.1", "@radix-ui/react-accordion": "^1.2.2", diff --git a/public/git-info.json b/public/git-info.json index d8bfb67..943169f 100644 --- a/public/git-info.json +++ b/public/git-info.json @@ -1,4 +1,4 @@ { - "commitHash": "74b7aa4", - "buildTime": "2025-09-23T12:09:08.230Z" + "commitHash": "32bf9d7", + "buildTime": "2025-10-09T19:56:57.229Z" } \ No newline at end of file