diff --git a/app/dashboard/products/page.tsx b/app/dashboard/products/page.tsx index 7ef0d69..2823be1 100644 --- a/app/dashboard/products/page.tsx +++ b/app/dashboard/products/page.tsx @@ -105,7 +105,6 @@ export default function ProductsPage() { }; - // Save product data after modal form submission const handleSaveProduct = async (data: Product, file?: File | null) => { console.log("handleSaveProduct:", data, file); diff --git a/components/forms/pricing-tiers.tsx b/components/forms/pricing-tiers.tsx index b7d4d83..eb01ce4 100644 --- a/components/forms/pricing-tiers.tsx +++ b/components/forms/pricing-tiers.tsx @@ -19,52 +19,106 @@ export const PricingTiers = ({ handleTierChange, handleRemoveTier, handleAddTier, -}: PricingTiersProps) => ( -
-

Tiered Pricing

+}: PricingTiersProps) => { + const formatNumber = (num: number) => { + // For price per unit, show up to 6 decimal places if needed + return Number(num.toFixed(6)).toString(); + }; - {pricing?.length > 0 ? ( - pricing.map((tier, index) => ( -
- handleTierChange(e, index)} - className="h-8 text-sm px-2 flex-1" - /> + const formatTotal = (num: number) => { + // For total price, always show 2 decimal places + return num.toFixed(2); + }; - handleTierChange(e, index)} - className="h-8 text-sm px-2 flex-1" - /> - -
- )) - ) : ( -

No pricing tiers added.

- )} + const calculateTotal = (quantity: number, pricePerUnit: number) => { + return formatTotal(quantity * pricePerUnit); + }; - -
-); + const handleTotalChange = ( + e: React.ChangeEvent, + index: number, + minQuantity: number + ) => { + const totalPrice = Number(e.target.value); + const pricePerUnit = minQuantity > 0 ? totalPrice / minQuantity : 0; + + const syntheticEvent = { + target: { + name: 'pricePerUnit', + value: formatNumber(pricePerUnit) + } + } as React.ChangeEvent; + + handleTierChange(syntheticEvent, index); + }; + + return ( +
+

Tiered Pricing

+ + {pricing?.length > 0 ? ( + <> +
+
Quantity
+
Price Per Unit
+
Total Price
+
+
+ + {pricing.map((tier, index) => ( +
+ handleTierChange(e, index)} + className="h-8 text-sm px-2" + /> + + handleTierChange(e, index)} + className="h-8 text-sm px-2" + /> + + handleTotalChange(e, index, tier.minQuantity)} + className="h-8 text-sm px-2" + /> + + +
+ ))} + + ) : ( +

No pricing tiers added.

+ )} + + +
+ ); +}; diff --git a/components/modals/product-modal.tsx b/components/modals/product-modal.tsx index 7fceb55..e6c500e 100644 --- a/components/modals/product-modal.tsx +++ b/components/modals/product-modal.tsx @@ -87,10 +87,10 @@ export const ProductModal: React.FC = ({ const handleAddTier = () => { setProductData((prev) => ({ ...prev, - pricing: [...prev.pricing, { minQuantity: 0, pricePerUnit: 0 }], + pricing: [...prev.pricing, { minQuantity: 0, pricePerUnit: 0 }], })); }; - + const handleSave = async () => { if (!productData.category) { toast.error("Please select or add a category"); @@ -114,7 +114,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 : Number(value) } : tier ), })); @@ -122,7 +122,7 @@ export const ProductModal: React.FC = ({ return ( - + {editing ? "Edit Product" : "Add Product"} @@ -221,9 +221,9 @@ const CategorySelect: React.FC = ({ // Get root categories (those without parentId) const rootCategories = categories.filter(cat => !cat.parentId); - + // Get subcategories for a given parent - const getSubcategories = (parentId: string) => + const getSubcategories = (parentId: string) => categories.filter(cat => cat.parentId === parentId); return ( diff --git a/components/tables/product-table.tsx b/components/tables/product-table.tsx index 47ffcbd..1fea8dd 100644 --- a/components/tables/product-table.tsx +++ b/components/tables/product-table.tsx @@ -18,6 +18,12 @@ const ProductTable = ({ onDelete, getCategoryNameById }: ProductTableProps) => { + + const sortedProducts = [...products].sort((a, b) => { + const categoryNameA = getCategoryNameById(a.category); + const categoryNameB = getCategoryNameById(b.category); + return categoryNameA.localeCompare(categoryNameB); + }); return (
@@ -39,8 +45,8 @@ const ProductTable = ({ Loading... )) - ) : products.length > 0 ? ( - products.map((product) => ( + ) : sortedProducts.length > 0 ? ( + sortedProducts.map((product) => ( {product.name} diff --git a/components/ui/dialog.tsx b/components/ui/dialog.tsx index 478c72b..4233e40 100644 --- a/components/ui/dialog.tsx +++ b/components/ui/dialog.tsx @@ -21,7 +21,7 @@ const DialogOverlay = React.forwardRef<