/* ============================================================= CoreIQ Office — Supplier profile (detail page with tabs) Registers window.OFFICE_SCREENS.supplierDetail ============================================================= */ const { useState: sdUseState, useMemo: sdUseMemo, useEffect: sdUseEffect } = React; const MONTHS = ["Jun","Jul","Aug","Sep","Oct","Nov","Dec","Jan","Feb","Mar","Apr","May"]; function poStatusBadge(st) { const m = { received: { c: "badge--paid", l: "Received" }, "in-transit":{ c: "badge--hold", l: "In transit" }, ordered: { c: "badge--brand", l: "Ordered" }, part: { c: "badge--hold", l: "Part-filled" }, }[st] || { c: "badge--neutral", l: st }; return {m.l}; } function invStatusBadge(st) { const m = { paid: { c: "badge--paid", l: "Paid" }, due: { c: "badge--hold", l: "Due" }, overdue: { c: "badge--void", l: "Overdue" }, credit: { c: "badge--brand", l: "Credit" }, }[st] || { c: "badge--neutral", l: st }; return {m.l}; } function ago(d) { return d === 0 ? "Today" : d === 1 ? "Yesterday" : d + " days ago"; } // ---- Overview tab ------------------------------------------------ function TabOverview({ id, period, setTab }) { const ext = window.supExt(id); const sp = window.supSpend(id, period); const share = window.supSpendShare(id, period); const delta = window.supSpendDelta(id); const trend = window.supSpend12(id); const tmax = Math.max(...trend, 1); const bo = window.supBackorders(id); const openBal = window.supOpenBalance(id); const t = window.supType(id); const KpiCard = window.KpiCard; return (
{bo.length > 0 && (
= 6 ? " sup-alert--bad" : "")}> {bo.length} line{bo.length > 1 ? "s" : ""} on backorder with this supplier — {bo.reduce((s, b) => s + b.qty, 0)} units across affected stores.
)}
p.key === period).label} value={window.supMoneyK(sp)} delta={isFinite(delta) && sp > 0 ? { dir: delta >= 0 ? "up" : "down", text: (delta >= 0 ? "+" : "") + (delta * 100).toFixed(1) + "% MoM" } : { text: "New account" }}/> = 95 ? "up" : "down", text: ext.leadTime + "-day lead" }}/> 0 ? window.supMoneyK(openBal) : "$0"} delta={{ text: ext.terms.payment }}/>
Spend · trailing 12 monthsTotal {window.supMoneyK(trend.reduce((a, b) => a + b, 0))}
{trend.map((v, i) => (
= 6 ? t.color : undefined }} title={window.supMoneyK(v)}/>
{MONTHS[i]}
))}
Account rep
{ext.rep.name.split(" ").map(w => w[0]).slice(0, 2).join("")}
{ext.rep.name}
{ext.rep.title}
{ext.rep.mobile}
{ext.channel}
); } // ---- Catalogue tab ---------------------------------------------- function TabCatalogue({ id }) { const cat = window.supCatalogue(id); return (
SKUs supplied {cat.length}
ProductPDEBuy exSellMOQOn hand
{cat.map(p => (
{p.name} {p.strength !== "—" ? p.strength : ""}
{p.pack}{p.schedule !== "—" ? " · " + p.schedule : ""}{p.pbs ? " · PBS" : ""}
{p.pde} {window.officeMoney(p.cost)} {window.officeMoney(p.price)} {p.moq} {p.onHand}
))} {cat.length === 0 &&
No SKUs linked to this supplier.
}
); } // ---- Purchase orders tab ---------------------------------------- function TabPOs({ id }) { const pos = window.supPurchaseOrders(id); const { pushToast } = window.useOffice(); return (
Purchase orders {pos.length}
PO numberStoreLinesDateStatusValue
{pos.map(po => (
{po.id} {po.store} {po.lines} {ago(po.daysAgo)}{po.eta ? " · ETA " + po.eta : ""} {poStatusBadge(po.status)} {window.officeMoney(po.value)}
))}
); } // ---- Invoices tab ----------------------------------------------- function TabInvoices({ id }) { const inv = window.supInvoices(id); const open = window.supOpenBalance(id); return ( <>
Open balance
{window.supMoneyK(open)}
{window.supExt(id).terms.payment}
Settlement
{window.supExt(id).terms.settlement || "—"}
early-payment discount
Credits · 12mo
{window.supExt(id).credits}%
of purchases returned
Invoices & credits{inv.length}
DocumentDateTermsStatusAmount
{inv.map(v => (
{v.id} {ago(v.daysAgo)} {v.terms} {invStatusBadge(v.status)} {window.officeMoney(v.amount)}
))}
); } // ---- Performance tab -------------------------------------------- function TabPerformance({ id }) { const ext = window.supExt(id); const bars = [ { l: "On-time delivery", v: ext.onTime, sub: "Orders delivered by the promised date" }, { l: "Fill rate", v: ext.fillRate, sub: "Lines supplied in full, first attempt" }, { l: "DIFOT", v: ext.difot, sub: "Delivered in full, on time" }, ]; function barColor(v) { return v == null ? "var(--border-strong)" : v >= 95 ? "var(--paid)" : v >= 90 ? "var(--hold)" : "var(--void)"; } return (
Service performance · 12 months
{ext.isNew &&
No delivery history yet — performance builds once orders start flowing.
} {bars.map(b => (
{b.l}{b.v == null ? "—" : b.v + "%"}
{b.sub}
))}
At a glance
Avg lead time{ext.leadTime} day{ext.leadTime > 1 ? "s" : ""}
Order cut-off{ext.cutoff}
Credits / returns{ext.credits}%
Open backorders{window.SUP_DATA.BACKORDERS[id] || 0}
Channel{ext.channel}
); } // ---- Terms & accounts tab --------------------------------------- function TabTerms({ id }) { const ext = window.supExt(id); const accts = window.supAccounts(id); const s = window.OFFICE_DATA.SUPPLIERS.find(x => x.id === id); return (
Trading terms
Order priority {window.supLineLabel(id)} {window.supIsRanked(id) && ( )}
Payment terms{ext.terms.payment}
Settlement discount{ext.terms.settlement || "—"}
Volume rebate{ext.terms.rebate || "—"}
Min order / freight{ext.terms.moq}
Returns policy{ext.terms.returns}
Company
ABN{ext.abn}
Address{ext.address}
Website{ext.web}
Phone{s.phone}
Per-store accounts{accts.length}
{accts.map(a => (
{a.code}
{a.store}
{a.account} · since {a.since}
{a.status === "active" ? "Active" : "On hold"}
))}
); } // ---- Documents tab ---------------------------------------------- function TabDocs({ id }) { const ext = window.supExt(id); const docs = ext.docs || []; function docBadge(st) { const m = { current: { c: "badge--paid", l: "Current" }, review: { c: "badge--hold", l: "Review due" }, stale: { c: "badge--void", l: "Out of date" } }[st] || { c: "badge--neutral", l: st }; return {m.l}; } return (
Documents & compliance{docs.length}
{docs.map((d, i) => (
{d.name}
{d.type} · updated {d.updated}{d.expires ? " · expires " + d.expires : ""}
{docBadge(d.status)}
))}
); } // ================================================================= // PROFILE SHELL // ================================================================= // ----------------------------------------------------------------- // SUPPLIER DETAIL — LIVE · this pharmacy // Real supplier profile (passed from the list) + the products that name it as // primary supplier, fetched from /products?supplierId. Trading history is shown // as an honest empty state — no spend/PO/invoice data was migrated. // ----------------------------------------------------------------- function SupplierDetail() { const { screenState, setScreen, setScreenState } = window.useOffice(); const s = screenState.supplier; const openProduct = (pid) => { setScreenState((st) => ({ ...st, activeProductId: pid, productFrom: "supplierDetail" })); setScreen("productDetail"); }; const [products, setProducts] = React.useState([]); const [loadingP, setLoadingP] = React.useState(true); React.useEffect(() => { if (!s) return undefined; let alive = true; setLoadingP(true); window.OfficeAPI.listProducts({ supplierId: s.id, limit: 200 }) .then((ps) => { if (alive) { setProducts(ps || []); setLoadingP(false); } }) .catch(() => { if (alive) setLoadingP(false); }); return () => { alive = false; }; }, [s && s.id]); if (!s) { return (
No supplier selected.
); } const money2 = (c) => "$" + (Number(c || 0) / 100).toFixed(2); const loc = [s.locality, s.region].filter(Boolean).join(", ") || null; return (
· live from Aurora

{s.name}

Contact & ordering

Trading history

No purchase history yet
Spend, orders, invoices and on-time metrics populate as you raise purchase orders — none were migrated from Z.
Products from this supplier
{loadingP ? "loading…" : (products.length >= 200 ? "first 200 of " + s.productCount.toLocaleString("en-AU") : products.length.toLocaleString("en-AU") + " of " + s.productCount.toLocaleString("en-AU"))}
Product
SKU
Sched
Cost
Sell
{products.map((p) => (
openProduct(p.id)}>
{p.name && p.name !== "-" ? p.name : p.sku}
{p.sku}
{p.schedule ? : ""}
{p.costPriceCents == null ? "—" : money2(p.costPriceCents)}
{money2(p.sellPriceCents)}
))}
{!loadingP && products.length === 0 &&
No products link to this supplier.
}
); } function SupKV({ k, v, mail }) { return (
{k}
{v ? (mail ? {v} : v) : "—"}
); } function TabBackorders({ id }) { const bo = window.supBackorders(id); if (bo.length === 0) { return (

No backorders

Every line from this supplier is currently available.

); } return (
Lines on backorder{bo.length}
ProductQtyWaitingETA
{bo.map((b, i) => (
{b.product} {b.strength !== "—" ? b.strength : ""} {b.qty} {b.waiting}d {b.eta === "No ETA" ? No ETA : {b.eta}}
))}
); } window.OFFICE_SCREENS = Object.assign(window.OFFICE_SCREENS || {}, { supplierDetail: SupplierDetail });