diff --git a/frontend/src/pages/products/components/product-dialog.tsx b/frontend/src/pages/products/components/product-dialog.tsx index 48ed144..7f9e3b0 100644 --- a/frontend/src/pages/products/components/product-dialog.tsx +++ b/frontend/src/pages/products/components/product-dialog.tsx @@ -28,7 +28,7 @@ interface ProductDialogProps { showDeleteButton?: boolean; } -export default function ProductDialog({ +export function ProductDialog({ open, onOpenChange, form, @@ -53,30 +53,38 @@ export default function ProductDialog({
{/* Name field */}
- - - {form.formState.errors.name && ( -

- {form.formState.errors.name.message} -

- )} - +
+ + + {form.formState.errors.name && ( +

+ {form.formState.errors.name.message} +

+ )} +
parseFloat(v).toFixed(2) + })} placeholder="0.00" /> + {form.formState.errors.price && ( +

+ {form.formState.errors.price.message} +

+ )}
@@ -93,27 +101,31 @@ export default function ProductDialog({
{/* Image upload & preview */} -
- +
+ + {imagePreview ? ( Preview ) : ( - - + )} -

+ +

JPG or PNG only. Max size: 2MB.

+
diff --git a/frontend/src/pages/products/components/product-list.tsx b/frontend/src/pages/products/components/product-list.tsx index 1206b89..2cfc19a 100644 --- a/frontend/src/pages/products/components/product-list.tsx +++ b/frontend/src/pages/products/components/product-list.tsx @@ -8,10 +8,12 @@ import { } from "@/components/ui/card"; export function ProductList({ + currency, products, isLoading, onClick }: { + currency: string, products: ProductWithDetails[]; isLoading: boolean; onClick: (id: number) => void; @@ -37,12 +39,15 @@ export function ProductList({ className="h-full w-full object-cover" /> ) : ( - + )} -
+
{product.stock_quantity} in stock + + {product.price.toFixed(2)} {currency} +
diff --git a/frontend/src/pages/products/hooks/use-product-form.tsx b/frontend/src/pages/products/hooks/use-product-form.tsx index c16621a..8d5d6b2 100644 --- a/frontend/src/pages/products/hooks/use-product-form.tsx +++ b/frontend/src/pages/products/hooks/use-product-form.tsx @@ -8,7 +8,7 @@ import { z } from "zod"; export const schema = z.object({ name: z.string().min(1, "Name is required"), description: z.string().min(1, "Description is required"), - price: z.coerce.number().min(0), + price: z.coerce.number().min(0.01, "Price must be greater than 0.01").step(0.01), stock_quantity: z.coerce.number().int().min(0), image_data: z.string().optional() }); diff --git a/frontend/src/pages/products/index.tsx b/frontend/src/pages/products/index.tsx index 9aa95fb..ba5bb2e 100644 --- a/frontend/src/pages/products/index.tsx +++ b/frontend/src/pages/products/index.tsx @@ -28,6 +28,7 @@ import { useProductForm } from "./hooks/use-product-form"; import { ProductList } from "./components/product-list"; import { ProductDialog } from "./components/product-dialog"; import { toast } from "@/hooks/useToast"; +import { useShop } from "@/hooks/useShop"; export default function Products() { const [sort, setSort] = useState<"ascending" | "descending">("ascending"); @@ -38,6 +39,7 @@ export default function Products() { number | undefined >(undefined); + const { shop } = useShop(); const { data: products = [], isLoading } = useProducts(); const { product, createProduct, updateProduct, deleteProduct } = useProduct(selectedProductId); @@ -52,7 +54,7 @@ export default function Products() { reader.readAsDataURL(file); }; - const handleCreateSubmit = form.handleSubmit((data) => { + const handleCreateClicked = () => { form.reset({ name: "", description: "", @@ -60,6 +62,11 @@ export default function Products() { stock_quantity: 0, image_data: "" }); + setSelectedProductId(undefined); + setDialogOpen(true); + }; + + const handleCreateSubmit = form.handleSubmit((data) => { createProduct.mutate(data); setDialogOpen(false); toast({ title: `${data.name} created`, variant: "default" }); @@ -144,6 +151,7 @@ export default function Products() { { @@ -153,7 +161,7 @@ export default function Products() { />