Initial project upload

This commit is contained in:
Mohamed Mathar Irfan
2026-07-28 17:57:02 +05:30
commit ed6610d5d8
23919 changed files with 3003316 additions and 0 deletions

View File

@@ -0,0 +1,110 @@
"use client";
import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { api } from "@/lib/api";
export default function NewProduct() {
const r = useRouter();
const [brands, setBrands] = useState<any[]>([]);
const [form, setForm] = useState<any>({
brand_id: "", name: "", sku: "", category: "", description: "",
manufacturer: { company: "", country: "India", plant: "" },
details: { net_weight: "", shelf_life: "", storage_condition: "" },
status: "active",
});
const [err, setErr] = useState("");
const [newBrand, setNewBrand] = useState("");
useEffect(() => { api("/brands").then(setBrands).catch(() => {}); }, []);
async function createBrand() {
if (!newBrand) return;
const b = await api("/brands", { method: "POST", body: JSON.stringify({ name: newBrand }) });
setBrands([...brands, b]);
setForm({ ...form, brand_id: b.id });
setNewBrand("");
}
async function submit(e: React.FormEvent) {
e.preventDefault();
setErr("");
try {
const p = await api("/products", { method: "POST", body: JSON.stringify(form) });
r.push(`/dashboard/products/${p.id}/batch`);
} catch (e: any) {
const d = e.detail;
setErr(typeof d === "object" ? d.message : d || "Failed to create product");
}
}
const set = (path: string) => (e: any) => {
const v = e.target.value;
if (path.includes(".")) {
const [g, k] = path.split(".");
setForm({ ...form, [g]: { ...form[g], [k]: v } });
} else setForm({ ...form, [path]: v });
};
return (
<div className="max-w-2xl space-y-5">
<h2 className="text-xl font-bold">Add Product</h2>
{err && <div className="card p-3 bg-rose-50 border-rose-200 text-rose-700 text-sm">{err}</div>}
<form onSubmit={submit} className="space-y-5">
<div className="card p-5 space-y-4">
<h3 className="font-semibold text-slate-800">Basic Info</h3>
<div className="flex gap-2 items-end">
<label className="flex-1">
<span className="text-sm font-medium">Brand</span>
<select value={form.brand_id} onChange={set("brand_id")} required
className="mt-1 w-full px-3 py-2 rounded-lg border border-slate-200 text-sm">
<option value="">Select brand</option>
{brands.map((b) => <option key={b.id} value={b.id}>{b.name}</option>)}
</select>
</label>
<input placeholder="+ New brand" value={newBrand} onChange={(e) => setNewBrand(e.target.value)}
className="px-3 py-2 rounded-lg border border-slate-200 text-sm w-32" />
<button type="button" onClick={createBrand}
className="px-3 py-2 rounded-lg bg-slate-100 text-sm font-medium">Add</button>
</div>
<Input label="Product name" value={form.name} onChange={set("name")} required />
<div className="grid grid-cols-2 gap-3">
<Input label="SKU" value={form.sku} onChange={set("sku")} />
<Input label="Category" value={form.category} onChange={set("category")} />
</div>
</div>
<div className="card p-5 space-y-4">
<h3 className="font-semibold text-slate-800">Manufacturing Info</h3>
<Input label="Manufacturer" value={form.manufacturer.company} onChange={set("manufacturer.company")} />
<div className="grid grid-cols-2 gap-3">
<Input label="Country" value={form.manufacturer.country} onChange={set("manufacturer.country")} />
<Input label="Plant" value={form.manufacturer.plant} onChange={set("manufacturer.plant")} />
</div>
</div>
<div className="card p-5 space-y-4">
<h3 className="font-semibold text-slate-800">Product Details</h3>
<div className="grid grid-cols-2 gap-3">
<Input label="Net weight" value={form.details.net_weight} onChange={set("details.net_weight")} />
<Input label="Shelf life" value={form.details.shelf_life} onChange={set("details.shelf_life")} />
</div>
<Input label="Storage condition" value={form.details.storage_condition} onChange={set("details.storage_condition")} />
</div>
<button className="bg-brand-600 text-white px-6 py-2.5 rounded-lg font-semibold">
Save & create batch
</button>
</form>
</div>
);
}
function Input({ label, ...props }: any) {
return (
<label className="block">
<span className="text-sm font-medium">{label}</span>
<input {...props} className="mt-1 w-full px-3 py-2 rounded-lg border border-slate-200 text-sm" />
</label>
);
}