import React, { useEffect, useState, useCallback } from "react"; import { api } from "../api/client"; import { useAuth } from "../context/AuthContext"; import { Table } from "../components/Table"; import { Modal } from "../components/Modal"; import { PageHeader } from "../components/PageHeader"; import { FormField, inputStyle, Btn } from "../components/FormField"; import { VendorFilter } from "../components/VendorFilter"; interface Category { id: string; name: string; } interface Tax { id: string; name: string; rate: number; } interface Product { id: string; name: string; sku: string | null; price: number; category: Category | null; tax: Tax | null; description: string | null; } interface ApiList { data: T[]; } type Tab = "products" | "categories" | "taxes"; export default function CatalogPage() { const { user } = useAuth(); const [tab, setTab] = useState("products"); const [vendorId, setVendorId] = useState(user?.vendorId ?? ""); return (
{(["products", "categories", "taxes"] as Tab[]).map((t) => ( ))}
{tab === "products" && } {tab === "categories" && } {tab === "taxes" && }
); } function qs(vendorId: string) { return vendorId ? `?vendorId=${encodeURIComponent(vendorId)}` : ""; } // ─── Products ────────────────────────────────────────────────────────────── function ProductsTab({ vendorId }: { vendorId: string }) { const [products, setProducts] = useState([]); const [categories, setCategories] = useState([]); const [taxes, setTaxes] = useState([]); const [loading, setLoading] = useState(true); const [modal, setModal] = useState<"create" | "edit" | null>(null); const [selected, setSelected] = useState(null); const [form, setForm] = useState(emptyProduct()); const [saving, setSaving] = useState(false); const [error, setError] = useState(""); const load = useCallback(async () => { setLoading(true); const q = qs(vendorId); const [p, c, t] = await Promise.all([ api.get>(`/products${q}`), api.get>(`/categories${q}`), api.get>(`/taxes${q}`), ]); setProducts(p.data); setCategories(c.data); setTaxes(t.data); setLoading(false); }, [vendorId]); useEffect(() => { load(); }, [load]); const openCreate = () => { setSelected(null); setForm(emptyProduct()); setError(""); setModal("create"); }; const openEdit = (p: Product) => { setSelected(p); setForm({ name: p.name, sku: p.sku ?? "", price: String(p.price), categoryId: p.category?.id ?? "", taxId: p.tax?.id ?? "", description: p.description ?? "" }); setError(""); setModal("edit"); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setSaving(true); setError(""); try { const payload = { ...form, price: parseFloat(form.price), categoryId: form.categoryId || null, taxId: form.taxId || null }; const q = qs(vendorId); if (modal === "create") await api.post(`/products${q}`, payload); else if (selected) await api.put(`/products/${selected.id}${q}`, payload); setModal(null); load(); } catch (err) { setError(err instanceof Error ? err.message : "Save failed"); } finally { setSaving(false); } }; const handleDelete = async (p: Product) => { if (!confirm(`Delete "${p.name}"?`)) return; await api.delete(`/products/${p.id}`).catch((e) => alert(e.message)); load(); }; const columns = [ { key: "name", header: "Name" }, { key: "sku", header: "SKU", render: (p: Product) => p.sku ?? "—" }, { key: "price", header: "Price", render: (p: Product) => `$${p.price.toFixed(2)}` }, { key: "category", header: "Category", render: (p: Product) => p.category?.name ?? "—" }, { key: "tax", header: "Tax", render: (p: Product) => p.tax ? `${p.tax.name} (${p.tax.rate}%)` : "—" }, { key: "actions", header: "", render: (p: Product) => (
openEdit(p)} style={{ padding: "4px 10px" }}>Edit handleDelete(p)} style={{ padding: "4px 10px" }}>Delete
)}, ]; return ( <>
+ Add Product
{modal && ( setModal(null)}>
{error &&
{error}
}