"use client"; /* Catalogue & suppliers: default reorder level, barcode lookup, and the supplier directory. */ import { useState } from "react"; import { useSnap } from "@/lib/client"; import { Field } from "@/components/ui"; import { Panel } from "@/components/portal"; import { csvOf, type SupplierRec } from "@/lib/compute"; import { downloadCsv } from "@/lib/print"; import { Msg, SectionHead, TextField, useSaver, useSettingsFields } from "./common"; type SupKey = "contact" | "phone" | "account" | "email" | "lead"; const SUP_FIELDS: readonly [SupKey, string, string][] = [["contact", "Contact", "e.g. Dana R."], ["phone", "Phone", "e.g. 07 3xxx xxxx"], ["account", "Account no.", "e.g. ACC-2201"], ["email", "Order email", "e.g. orders@example.com"], ["lead", "Lead time (days)", "e.g. 14"]]; export default function CatalogueSection() { const { s, isAdmin, mutate } = useSnap(); const saver = useSaver(); const { msg, say, draft, debounced } = saver; const { val, setField } = useSettingsFields(saver); const [lookupOn, setLookupOn] = useState(null); const [ns, setNs] = useState(""); const supField = (sup: SupplierRec, k: SupKey) => draft[`sup:${sup.id}:${k}`] ?? (sup[k] === null ? "" : String(sup[k])); function exportSuppliers() { const rows = s.supplierDir.map((sup) => [sup.name, supField(sup, "contact"), supField(sup, "phone"), supField(sup, "account"), supField(sup, "email"), supField(sup, "lead"), s.catalog.filter((it) => it.supplier === sup.name).length, s.orders.filter((o) => o.supplier === sup.name).length]); downloadCsv(`threadcount-suppliers-${s.today}.csv`, csvOf(["Supplier", "Contact", "Phone", "Account no.", "Order email", "Lead time (days)", "Products", "Orders"], rows)); } return ( <> Catalogue
setField("defaultReorder", v.replace(/[^0-9]/g, ""))} />
{isAdmin && ( )} Export CSV}> Suppliers {s.supplierDir.map((sp) => { const nItems = s.catalog.filter((it) => it.supplier === sp.name).length, nOrds = s.orders.filter((o) => o.supplier === sp.name).length; return ( {sp.name}} aside={ {nItems} product{nItems === 1 ? "" : "s"} · {nOrds} order{nOrds === 1 ? "" : "s"} {isAdmin && nItems + nOrds === 0 && } }>
{SUP_FIELDS.map(([k, lbl, ph]) => ( {lbl} for {sp.name}}>{(c) => { const v = k === "lead" ? e.target.value.replace(/[^0-9]/g, "") : e.target.value; debounced(`sup:${sp.id}:${k}`, v, "supplier.update", { id: sp.id, [k]: v }, "sup"); }} />} ))}
); })} {!s.supplierDir.length &&
No suppliers yet.
} {isAdmin && (
{(c) => setNs(e.target.value)} placeholder="e.g. Northline Workwear" onKeyDown={async (e) => { if (e.key === "Enter" && ns.trim()) { const r = await mutate("supplier.add", { name: ns }); say("sup", r.ok ? "Added." : r.error); if (r.ok) setNs(""); } }} />}
)} ); }