milestone 30: overview as a dashboard, explicit health contract, period aggregations

This commit is contained in:
2026-08-22 16:45:15 +02:00
parent 0e83477d80
commit 623667e475
89 changed files with 7222 additions and 4239 deletions
+37
View File
@@ -0,0 +1,37 @@
/**
* The count beside the Diagnostics nav item.
*
* Three things have to be visible and only one of them is a number. Open
* episodes are the count. A `degraded` rollup with no open episode still has to
* show something, or a degraded box looks exactly like a healthy one. And a
* health poll that failed is not evidence of health: it shows the same neutral
* mark, because the alternative is an unbadged item claiming all is well on no
* evidence at all.
*
* "Fresh" here means the latest poll succeeded, never TanStack's `isStale`:
* healthQuery's `staleTime` is 0, so staleness is true in every gap between
* polls and would badge the item permanently.
*/
import type { Health } from "@/lib/types";
export interface NavBadge {
/** What the badge shows. Shape and text, never colour alone. */
text: string;
/** What a screen reader hears in its place. */
label: string;
}
export function diagnosticsBadge(health: Health | undefined, pollFailed: boolean): NavBadge | null {
// The one hidden unknown, and only because it is momentary: the first poll has
// not answered yet, and there is nothing to be right or wrong about.
if (health === undefined && !pollFailed) return null;
if (pollFailed) return { text: "!", label: "Health unavailable" };
if (health === undefined) return null;
const open = health.diagnostics.active_warnings + health.diagnostics.active_errors;
if (open > 0) {
return { text: String(open), label: `${open} active diagnostic ${open === 1 ? "event" : "events"}` };
}
if (health.status === "degraded") return { text: "!", label: "Health degraded" };
return null;
}