Quillwright / quillwright /web /js /inventory.js
Aarya2004
Deploy: sync hosted Space to local app (chat, document capture, Modal backends, pages, mobile/QR)
47b2a99
Raw
History Blame Contribute Delete
2.58 kB
// 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 `<div class="stock ${p.low ? "is-low" : ""}">
<div class="nums"><span>${p.stock} ${p.unit}</span><span>${status}</span></div>
<div class="meter"><span style="width:${pct}%"></span></div>
</div>`;
}
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) => `<tr>
<td class="desc">${p.description}</td>
<td><span class="chip chip--cat">${p.category}</span></td>
<td>${stockBar(p)}</td>
<td class="num">${money(p.rate)}</td>
<td>${p.low ? '<span class="chip chip--low">Reorder</span>' : '<span class="chip chip--ok">In stock</span>'}</td>
</tr>`,
)
.join("");
host.append(
el(`<table>
<thead><tr><th>Part</th><th>Category</th><th>Stock</th><th class="num">Unit price</th><th>Status</th></tr></thead>
<tbody>${rows}</tbody></table>`),
);
}
async function load() {
const data = await (await fetch("/api/inventory")).json();
parts = data.parts;
document.getElementById("kpis").append(
el(`<div class="kpi"><p class="label">Total SKUs</p><p class="value">${data.total_skus}</p>
<p class="sub">in the catalog</p></div>`),
el(`<div class="kpi kpi--alert"><p class="label">Low stock</p>
<p class="value">${data.low_stock_count}</p><p class="sub">at or below reorder point</p></div>`),
);
const cats = ["ALL", ...new Set(parts.map((p) => p.category))];
const filters = document.getElementById("filters");
cats.forEach((c) => {
const b = el(`<button class="filter ${c === "ALL" ? "active" : ""}">${c}</button>`);
b.addEventListener("click", () => {
activeCat = c;
filters.querySelectorAll(".filter").forEach((f) => f.classList.toggle("active", f === b));
render();
});
filters.append(b);
});
render();
}
load();