// Parts Catalog: read-only stock view from the seeded inventory read-model. // Low-stock flags + counts are computed server-side; category filter is client-side. const money = (n) => (n == null ? "—" : `$${Number(n).toFixed(2)}`); const el = (html) => { const t = document.createElement("template"); t.innerHTML = html.trim(); return t.content.firstElementChild; }; let parts = []; let activeCat = "ALL"; function stockBar(p) { const pct = p.reorder_at > 0 ? Math.min(100, Math.round((p.stock / (p.reorder_at * 3)) * 100)) : 100; const status = p.reorder_at === 0 ? "Service" : p.low ? "LOW" : "OK"; return `
${p.stock} ${p.unit}${status}
`; } function render() { const host = document.getElementById("parts"); host.innerHTML = ""; const shown = activeCat === "ALL" ? parts : parts.filter((p) => p.category === activeCat); const rows = shown .map( (p) => ` ${p.description} ${p.category} ${stockBar(p)} ${money(p.rate)} ${p.low ? 'Reorder' : 'In stock'} `, ) .join(""); host.append( el(`${rows}
PartCategoryStockUnit priceStatus
`), ); } async function load() { const data = await (await fetch("/api/inventory")).json(); parts = data.parts; document.getElementById("kpis").append( el(`

Total SKUs

${data.total_skus}

in the catalog

`), el(`

Low stock

${data.low_stock_count}

at or below reorder point

`), ); const cats = ["ALL", ...new Set(parts.map((p) => p.category))]; const filters = document.getElementById("filters"); cats.forEach((c) => { const b = el(``); b.addEventListener("click", () => { activeCat = c; filters.querySelectorAll(".filter").forEach((f) => f.classList.toggle("active", f === b)); render(); }); filters.append(b); }); render(); } load();