/* ============================================================
screens-home.jsx — HOME / TODAY: the tiered glance.
Surfaces acute → sub-acute first; falls back to the wellness
layer. Two layouts (stack / board) for the variation study.
============================================================ */
(function () {
const fmtDur = (m) => m == null ? "—" : `${Math.floor(m / 60)}h ${String(m % 60).padStart(2, "0")}m`;
// recovery uncertainty viz, switchable (variation study)
function RecoveryViz({ rec, kind = "dist", status }) {
if (kind === "band") return ;
if (kind === "arc") return
;
return ;
}
window.RecoveryViz = RecoveryViz;
const recStatus = (v) => v >= 67 ? "good" : v >= 45 ? "within" : "attn";
// ---- ACUTE alert ----------------------------------------
function AcuteAlert({ a, onOpen }) {
return (
{a.time ? a.time.split("·")[1]?.trim() || "Now" : "Now"}
{a.title}
{a.summary}
{a.metric && (
{a.metric.value}
{a.metric.threshold}
)}
{a.caveat}
);
}
// ---- SUB-ACUTE card -------------------------------------
function SubacuteCard({ s, onOpen }) {
return (
multi-night
{s.title}
{s.summary}
{s.signals.map((sig) => {
const bad = (sig.dir === "up") !== sig.higherBetter;
return (
{sig.value}
);
})}
{s.caveat}
);
}
// ---- ALL CLEAR (reassuring, not blank) ------------------
function AllClear({ data }) {
return (
{data.greeting}
No acute or sub-acute signals overnight. Your wellness layer is below.
{[["Acute", "AF · desaturation"], ["Sub-acute", "apnea · illness · RHR"]].map(([t, sub]) => (
))}
);
}
// ---- night confidence strip -----------------------------
function NightStrip({ data }) {
const c = data.confidence;
return (
{c.gapHrs > 0 && (
)}
{c.note && {c.note}
}
);
}
// ---- wellness cards -------------------------------------
function RecoveryCard({ data, viz, onOpen }) {
const rec = data.recovery, st = recStatus(rec.value);
return (
{st === "good" ? "recovered" : st === "attn" ? "low" : "moderate"}
{rec.headline}
);
}
function StrainSleepRow({ data, onSleep }) {
const st = data.strain, sl = data.sleep;
return (
{st.value != null ? (
<>
>
) : (
unavailable
wear gap
)}
{fmtDur(sl.duration)}
{sl.gapHrs ? (
) : (
)}
);
}
// ---- HOME: STACK layout (default / variation A) ---------
function HomeStack({ data, go, viz }) {
const hasAcute = data.acute.length, hasSub = data.subacute.length;
return (
{hasAcute > 0 && (
{data.acute.map((a) =>
go("clinical", "af")} />)})}
{hasSub > 0 && (
{data.subacute.map((s) => go("clinical", "illness")} />)}
)}
{!hasAcute && !hasSub &&
}
go("recovery")} />
go("sleep")} />
);
}
// ---- HOME: BOARD layout (variation B) -------------------
function StatusRow({ mark, status, label, value, onClick }) {
return (
);
}
function HomeBoard({ data, go, viz }) {
const hasAcute = data.acute.length, hasSub = data.subacute.length;
const rec = data.recovery, st = recStatus(rec.value);
return (
hasAcute && go("clinical", "af")} />
hasSub && go("clinical", "illness")} />
go("trends")} />
go("recovery")} />
{hasAcute > 0 && data.acute.map((a) =>
go("clinical", "af")} />)}
{hasSub > 0 && data.subacute.map((s) => go("clinical", "illness")} />)}
go("recovery")} />
go("sleep")} />
);
}
function Home({ data, go, viz = "dist", layout = "stack" }) {
return layout === "board" ? : ;
}
Object.assign(window, { Home, HomeStack, HomeBoard, RecoveryCard, AcuteAlert, SubacuteCard, AllClear, recStatus, fmtDur: fmtDur });
})();