import React, { useEffect, useState, useCallback } from "react"; import { api } from "../api/client"; import { useAuth } from "../context/AuthContext"; import { PageHeader } from "../components/PageHeader"; import { Table } from "../components/Table"; import { Modal } from "../components/Modal"; import { FormField, inputStyle, Btn } from "../components/FormField"; interface Vendor { id: string; name: string; businessNum: string | null; taxSettings: string | null; createdAt: string; updatedAt: string; } interface ApiList { data: T[]; pagination: { total: number } } const EMPTY_FORM = { name: "", businessNum: "" }; // ─── Admin view: list all vendors, create/edit/delete ──────────────────────── function AdminVendorPage() { const [vendors, setVendors] = useState([]); const [total, setTotal] = useState(0); const [loading, setLoading] = useState(true); const [modal, setModal] = useState<"create" | "edit" | null>(null); const [selected, setSelected] = useState(null); const [form, setForm] = useState(EMPTY_FORM); const [saving, setSaving] = useState(false); const [error, setError] = useState(""); const load = useCallback(async () => { setLoading(true); try { const res = await api.get>("/vendors?limit=100"); setVendors(res.data); setTotal(res.pagination.total); } catch (err) { console.error(err); } finally { setLoading(false); } }, []); useEffect(() => { load(); }, [load]); const openCreate = () => { setSelected(null); setForm(EMPTY_FORM); setError(""); setModal("create"); }; const openEdit = (v: Vendor) => { setSelected(v); setForm({ name: v.name, businessNum: v.businessNum ?? "" }); setError(""); setModal("edit"); }; const handleDelete = async (id: string) => { if (!confirm("Delete this vendor? All associated data will be removed.")) return; try { await api.delete(`/vendors/${id}`); load(); } catch (err) { alert(err instanceof Error ? err.message : "Delete failed"); } }; const handleSave = async () => { setSaving(true); setError(""); try { if (modal === "edit" && selected) { await api.put(`/vendors/${selected.id}`, form); } else { await api.post("/vendors", form); } setModal(null); load(); } catch (err) { setError(err instanceof Error ? err.message : "Save failed"); } finally { setSaving(false); } }; const columns = [ { key: "name", header: "Name", render: (v: Vendor) => v.name }, { key: "businessNum", header: "Business No.", render: (v: Vendor) => v.businessNum ?? "—" }, { key: "createdAt", header: "Created", render: (v: Vendor) => new Date(v.createdAt).toLocaleDateString() }, { key: "actions", header: "", render: (v: Vendor) => (
openEdit(v)}>Edit handleDelete(v.id)}>Delete
) }, ]; return (
+ New Vendor} /> {modal && ( setModal(null)}> setForm((f) => ({ ...f, name: e.target.value }))} required /> setForm((f) => ({ ...f, businessNum: e.target.value }))} /> {error &&
{error}
}
setModal(null)}>Cancel {saving ? "Saving…" : "Save"}
)} ); } // ─── Vendor/user view: own settings only ──────────────────────────────────── function OwnVendorPage() { const [vendor, setVendor] = useState(null); const [loading, setLoading] = useState(true); const [editing, setEditing] = useState(false); const [saving, setSaving] = useState(false); const [error, setError] = useState(""); const [form, setForm] = useState(EMPTY_FORM); useEffect(() => { api.get>("/vendors") .then((res) => { const v = res.data[0] ?? null; setVendor(v); if (v) setForm({ name: v.name, businessNum: v.businessNum ?? "" }); }) .catch(console.error) .finally(() => setLoading(false)); }, []); const handleSave = async (e: React.FormEvent) => { e.preventDefault(); if (!vendor) return; setSaving(true); setError(""); try { const updated = await api.put(`/vendors/${vendor.id}`, form); setVendor(updated); setEditing(false); } catch (err) { setError(err instanceof Error ? err.message : "Save failed"); } finally { setSaving(false); } }; if (loading) return
Loading…
; if (!vendor) return
No vendor found.
; return (
setEditing(true)}>Edit} /> {editing ? (
{error &&
{error}
} setForm((f) => ({ ...f, name: e.target.value }))} required /> setForm((f) => ({ ...f, businessNum: e.target.value }))} />
{saving ? "Saving…" : "Save changes"} setEditing(false)}>Cancel
) : (
)}
); } // ─── Root export — branches on role ───────────────────────────────────────── export default function VendorPage() { const { user } = useAuth(); return user?.role === "admin" ? : ; } // ─── Shared helpers ────────────────────────────────────────────────────────── function Row({ label, value }: { label: string; value: string }) { return (
{label}
{value}
); } const card: React.CSSProperties = { background: "var(--color-surface)", border: "1px solid var(--color-border)", borderRadius: "var(--radius)", padding: "20px", }; const errStyle: React.CSSProperties = { background: "#fef2f2", border: "1px solid #fecaca", color: "var(--color-danger)", borderRadius: "var(--radius)", padding: "10px 12px", fontSize: 13, marginBottom: 16, };