/* ============================================================= CoreIQ Office — Dashboard (LIVE · this pharmacy) Every figure here is a real aggregate pulled from Aurora via the Office API (/overview), scoped to the signed-in organisation (and the selected store). Nothing is fabricated: where a vertical has no data yet — e.g. no sales history, dispensing not migrated — the figure is honestly zero and labelled, rather than filled with a placeholder. ============================================================= */ const { useState: dashUseState, useEffect: dashUseEffect } = React; const dashMoney = (cents) => "$" + (Number(cents || 0) / 100).toLocaleString("en-AU", { minimumFractionDigits: 2, maximumFractionDigits: 2 }); const dashNum = (n) => Number(n || 0).toLocaleString("en-AU"); // date math on YYYY-MM-DD (UTC) const dMinusMonths = (d, n) => { const t = new Date(d + "T00:00:00Z"); t.setUTCMonth(t.getUTCMonth() - n); return t.toISOString().slice(0, 10); }; function Dashboard() { const { scope, stores, setScreen, setScope } = window.useOffice(); const [ov, setOv] = dashUseState(null); const [loading, setLoading] = dashUseState(true); const [err, setErr] = dashUseState(null); const [range, setRange] = dashUseState(null); // fetched takings for the window const [from, setFrom] = dashUseState(""); const [to, setTo] = dashUseState(""); const siteId = scope === "all" ? undefined : scope; dashUseEffect(() => { let alive = true; setLoading(true); setErr(null); window.OfficeAPI.getOverview(siteId) .then((o) => { if (alive) { setOv(o); setLoading(false); } }) .catch((e) => { if (alive) { setErr(String((e && e.message) || e)); setLoading(false); } }); return () => { alive = false; }; }, [scope]); // Sales for the chosen window — history + new sales as ONE timeline. First load // uses the API default (trailing 12 months of data) and seeds the date inputs. const loadRange = (f, t) => { const q = { ...(f ? { from: f } : {}), ...(t ? { to: t } : {}), ...(siteId ? { siteId } : {}) }; window.OfficeAPI.getSalesRange(Object.keys(q).length ? q : undefined) .then((r) => { setRange(r); setFrom(r.range.from || ""); setTo(r.range.to || ""); }) .catch(() => setRange(null)); }; dashUseEffect(() => { loadRange(); }, [scope]); const cur = stores.find((s) => s.id === scope); const scopeName = scope === "all" ? `All stores · ${stores.length}` : (cur?.name || "—"); const v = (fn) => (loading || !ov ? "…" : fn(ov)); const bounds = range?.bounds; const preset = (months) => { if (!bounds) return; const f = months == null ? bounds.from : dMinusMonths(bounds.to, months); setFrom(f); setTo(bounds.to); loadRange(f, bounds.to); }; const rv = (fn) => (range ? fn(range) : "…"); return (