feat(products): code is editable on edit, name is locked

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Hardik 2026-05-31 06:18:09 +05:30
parent 80fa1ea63c
commit 7b498a91f8
2 changed files with 11 additions and 8 deletions

View file

@ -45,14 +45,17 @@ export async function updateProduct(formData: FormData): Promise<ActionResult> {
if (!id) return { error: "Product ID required" }; if (!id) return { error: "Product ID required" };
const parsed = z.object({ const parsed = z.object({
name: z.string().min(1).max(200), code: z.string().min(1).max(50),
description: z.string().optional(), description: z.string().optional(),
}).safeParse({ }).safeParse({
name: formData.get("name"), code: formData.get("code"),
description: formData.get("description") || undefined, description: formData.get("description") || undefined,
}); });
if (!parsed.success) return { error: parsed.error.errors[0].message }; if (!parsed.success) return { error: parsed.error.errors[0].message };
const conflict = await db.product.findFirst({ where: { code: parsed.data.code, id: { not: id } } });
if (conflict) return { error: "Another product already uses that code." };
await db.product.update({ where: { id }, data: parsed.data }); await db.product.update({ where: { id }, data: parsed.data });
revalidatePath("/admin/products"); revalidatePath("/admin/products");
return { ok: true }; return { ok: true };

View file

@ -18,15 +18,15 @@ function ProductFormFields({ product }: { product?: ProductRow }) {
<div className="space-y-3"> <div className="space-y-3">
<div> <div>
<label className="block text-xs font-medium text-neutral-700 mb-1">Product Code *</label> <label className="block text-xs font-medium text-neutral-700 mb-1">Product Code *</label>
<input name="code" defaultValue={product?.code} required disabled={!!product} <input name="code" defaultValue={product?.code} required
className="w-full rounded-lg border border-neutral-300 px-3 py-2 text-sm focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20 disabled:bg-neutral-50 disabled:text-neutral-400" className="w-full rounded-lg border border-neutral-300 px-3 py-2 text-sm focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20"
placeholder="e.g. FUEL-OIL-001" /> placeholder="e.g. FUEL-OIL-001" />
{product && <p className="mt-1 text-xs text-neutral-400">Product code cannot be changed after creation.</p>}
</div> </div>
<div> <div>
<label className="block text-xs font-medium text-neutral-700 mb-1">Name *</label> <label className="block text-xs font-medium text-neutral-700 mb-1">Name</label>
<input name="name" defaultValue={product?.name} required <input name="name" defaultValue={product?.name} required disabled={!!product}
className="w-full rounded-lg border border-neutral-300 px-3 py-2 text-sm focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20" /> className="w-full rounded-lg border border-neutral-300 px-3 py-2 text-sm focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20 disabled:bg-neutral-50 disabled:text-neutral-400" />
{product && <p className="mt-1 text-xs text-neutral-400">Name is locked after creation.</p>}
</div> </div>
<div> <div>
<label className="block text-xs font-medium text-neutral-700 mb-1">Description</label> <label className="block text-xs font-medium text-neutral-700 mb-1">Description</label>