milestone 30: overview as a dashboard, explicit health contract, period aggregations
Gates / frontend (push) Successful in 1m32s
Gates / test (push) Successful in 1m54s
Gates / package (push) Successful in 5m28s
Gates / container (push) Successful in 14s
Gates / test-aarch64 (push) Failing after 3h10m0s
CI / gates (push) Failing after 3h11m55s

This commit is contained in:
2026-08-22 16:45:15 +02:00
parent 17422fac21
commit 648d9b4496
89 changed files with 7222 additions and 4239 deletions
+23
View File
@@ -0,0 +1,23 @@
/**
* The period Overview is scoped to, as URL state.
*
* One home for the four values and for the rule that turns whatever the URL
* carried into one of them: the route validates with it and the picker offers
* exactly the same list, so a hand-typed `?period=90d` becomes the default
* instead of reaching the API as a parameter it answers 400 to.
*/
import type { Period } from "@/lib/types";
export const PERIODS = ["1h", "24h", "7d", "30d"] as const satisfies readonly Period[];
export const DEFAULT_PERIOD: Period = "24h";
/**
* Undefined rather than the default for anything that is not one of the four,
* so an absent parameter and a nonsense one both leave a clean URL. The default
* is applied where the period is read, not written back into the address bar.
*/
export function parsePeriod(value: unknown): Period | undefined {
return PERIODS.find((period) => period === value);
}