Spaces:
Sleeping
Sleeping
| /** 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; | |
| } | |