unzip frontend
This commit is contained in:
@@ -0,0 +1,230 @@
|
||||
"use client"
|
||||
|
||||
import type React from "react"
|
||||
|
||||
import { useState } from "react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import { Textarea } from "@/components/ui/textarea"
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog"
|
||||
import type { Product } from "@/types/business"
|
||||
|
||||
interface ProductFormProps {
|
||||
product?: Product
|
||||
open: boolean
|
||||
onOpenChange: (open: boolean) => void
|
||||
onSubmit: (product: Omit<Product, "id">) => void
|
||||
}
|
||||
|
||||
const categories = [
|
||||
"Electronics",
|
||||
"Audio",
|
||||
"Accessories",
|
||||
"Mobile",
|
||||
"Computing",
|
||||
"Gaming",
|
||||
"Home & Garden",
|
||||
"Sports",
|
||||
"Other",
|
||||
]
|
||||
|
||||
export function ProductForm({ product, open, onOpenChange, onSubmit }: ProductFormProps) {
|
||||
const [formData, setFormData] = useState({
|
||||
name: product?.name || "",
|
||||
category: product?.category || "",
|
||||
description: product?.description || "",
|
||||
buyPrice: product?.buyPrice || 0,
|
||||
sellPrice: product?.sellPrice || 0,
|
||||
stock: product?.stock || 0,
|
||||
minStock: product?.minStock || 5,
|
||||
supplier: product?.supplier || "",
|
||||
sku: product?.sku || "",
|
||||
})
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
onSubmit(formData)
|
||||
onOpenChange(false)
|
||||
// Reset form if it's a new product
|
||||
if (!product) {
|
||||
setFormData({
|
||||
name: "",
|
||||
category: "",
|
||||
description: "",
|
||||
buyPrice: 0,
|
||||
sellPrice: 0,
|
||||
stock: 0,
|
||||
minStock: 5,
|
||||
supplier: "",
|
||||
sku: "",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const profitMargin =
|
||||
formData.sellPrice > 0 && formData.buyPrice > 0
|
||||
? (((formData.sellPrice - formData.buyPrice) / formData.sellPrice) * 100).toFixed(1)
|
||||
: "0"
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="sm:max-w-[600px] max-h-[90vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{product ? "Edit Product" : "Add New Product"}</DialogTitle>
|
||||
<DialogDescription>
|
||||
{product ? "Update product information" : "Enter the details for the new product"}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="name">Product Name *</Label>
|
||||
<Input
|
||||
id="name"
|
||||
value={formData.name}
|
||||
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
||||
placeholder="Enter product name"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="sku">SKU</Label>
|
||||
<Input
|
||||
id="sku"
|
||||
value={formData.sku}
|
||||
onChange={(e) => setFormData({ ...formData, sku: e.target.value })}
|
||||
placeholder="Product SKU"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="category">Category *</Label>
|
||||
<Select
|
||||
value={formData.category}
|
||||
onValueChange={(value) => setFormData({ ...formData, category: value })}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select category" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{categories.map((category) => (
|
||||
<SelectItem key={category} value={category}>
|
||||
{category}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="supplier">Supplier</Label>
|
||||
<Input
|
||||
id="supplier"
|
||||
value={formData.supplier}
|
||||
onChange={(e) => setFormData({ ...formData, supplier: e.target.value })}
|
||||
placeholder="Supplier name"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="description">Description</Label>
|
||||
<Textarea
|
||||
id="description"
|
||||
value={formData.description}
|
||||
onChange={(e) => setFormData({ ...formData, description: e.target.value })}
|
||||
placeholder="Product description"
|
||||
rows={3}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="buyPrice">Buy Price ($) *</Label>
|
||||
<Input
|
||||
id="buyPrice"
|
||||
type="number"
|
||||
step="0.01"
|
||||
min="0"
|
||||
value={formData.buyPrice}
|
||||
onChange={(e) => setFormData({ ...formData, buyPrice: Number.parseFloat(e.target.value) || 0 })}
|
||||
placeholder="0.00"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="sellPrice">Sell Price ($) *</Label>
|
||||
<Input
|
||||
id="sellPrice"
|
||||
type="number"
|
||||
step="0.01"
|
||||
min="0"
|
||||
value={formData.sellPrice}
|
||||
onChange={(e) => setFormData({ ...formData, sellPrice: Number.parseFloat(e.target.value) || 0 })}
|
||||
placeholder="0.00"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{formData.buyPrice > 0 && formData.sellPrice > 0 && (
|
||||
<div className="p-3 bg-muted rounded-lg">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Profit Margin: <span className="font-medium text-foreground">{profitMargin}%</span> ($
|
||||
{(formData.sellPrice - formData.buyPrice).toFixed(2)} profit per unit)
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="stock">Current Stock *</Label>
|
||||
<Input
|
||||
id="stock"
|
||||
type="number"
|
||||
min="0"
|
||||
value={formData.stock}
|
||||
onChange={(e) => setFormData({ ...formData, stock: Number.parseInt(e.target.value) || 0 })}
|
||||
placeholder="0"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="minStock">Minimum Stock Alert</Label>
|
||||
<Input
|
||||
id="minStock"
|
||||
type="number"
|
||||
min="0"
|
||||
value={formData.minStock}
|
||||
onChange={(e) => setFormData({ ...formData, minStock: Number.parseInt(e.target.value) || 0 })}
|
||||
placeholder="5"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
<Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button type="submit">{product ? "Update Product" : "Add Product"}</Button>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user