Fastwhisper / frontend /src /router.tsx
Mbonea's picture
Close P1 arch-code gaps: loop summary, template-echo Rules, Move now, proof kinds.
57ed4c2
Raw
History Blame Contribute Delete
2.3 kB
/** Minimal hash router for Habit Journal pages. */
import { useEffect, useState } from "preact/hooks";
export type Route =
| { name: "login" }
| { name: "home" }
| { name: "log"; remedy?: string; happened?: string }
| { name: "history" }
| { name: "entry"; id: string }
| { name: "daily" }
| { name: "plan"; date?: string }
| { name: "stats" }
| { name: "coach" }
| { name: "remedies" }
| { name: "settings" }
| { name: "unknown"; path: string };
function parseHash(hash: string): Route {
const raw = hash.replace(/^#/, "") || "/";
const [path = "/", query = ""] = raw.split("?");
const params = new URLSearchParams(query);
if (path === "/login") return { name: "login" };
if (path === "/" || path === "") return { name: "home" };
if (path === "/log")
return {
name: "log",
remedy: params.get("remedy") || undefined,
happened: params.get("happened") || undefined,
};
if (path === "/history") return { name: "history" };
if (path.startsWith("/entry/")) return { name: "entry", id: decodeURIComponent(path.slice(7)) };
if (path === "/daily") return { name: "daily" };
if (path === "/plan") return { name: "plan" };
if (path.startsWith("/plan/")) return { name: "plan", date: decodeURIComponent(path.slice(6)) };
if (path === "/stats") return { name: "stats" };
if (path === "/coach") return { name: "coach" };
if (path === "/remedies") return { name: "remedies" };
if (path === "/settings") return { name: "settings" };
return { name: "unknown", path };
}
export function navigate(to: string): void {
const next = to.startsWith("#") ? to : `#${to.startsWith("/") ? to : `/${to}`}`;
if (window.location.hash === next) {
window.dispatchEvent(new HashChangeEvent("hashchange"));
return;
}
window.location.hash = next;
}
export function useRoute(): Route {
const [route, setRoute] = useState<Route>(() =>
parseHash(typeof window !== "undefined" ? window.location.hash : "#/"),
);
useEffect(() => {
const onChange = () => setRoute(parseHash(window.location.hash));
window.addEventListener("hashchange", onChange);
if (!window.location.hash) {
window.location.hash = "#/";
}
return () => window.removeEventListener("hashchange", onChange);
}, []);
return route;
}