24 lines
1.6 KiB
TypeScript
24 lines
1.6 KiB
TypeScript
import { useCallback, useEffect, useState } from "react";
|
|
import type { ResourceKind } from "./contracts";
|
|
|
|
const resourceRoutes: Record<string, ResourceKind> = { "/projects": "projects", "/servers": "servers", "/tools": "tools", "/connectors": "connectors", "/clients": "clients", "/policies": "policies", "/audit": "audit" };
|
|
|
|
export function usePath() {
|
|
const [path, setPath] = useState(window.location.pathname + window.location.search);
|
|
useEffect(() => { const onPopState = () => setPath(window.location.pathname + window.location.search); window.addEventListener("popstate", onPopState); return () => window.removeEventListener("popstate", onPopState); }, []);
|
|
const navigate = useCallback((next: string) => {
|
|
window.history.pushState({}, "", next);
|
|
setPath(next);
|
|
}, []);
|
|
return [path, navigate] as const;
|
|
}
|
|
export function basePath(path: string) { return (path.split("?")[0] ?? "").replace(/\/$/, "") || "/"; }
|
|
export function projectDetailId(path: string): string | null { return decodeDetailId(path, "projects"); }
|
|
export function connectorDetailId(path: string): string | null { return decodeDetailId(path, "connectors"); }
|
|
function decodeDetailId(path: string, collection: "projects" | "connectors"): string | null {
|
|
const match = new RegExp(`^/${collection}/([^/]+)$`).exec(basePath(path));
|
|
if (!match?.[1]) return null;
|
|
try { return decodeURIComponent(match[1]); } catch { return null; }
|
|
}
|
|
export function resourceKind(path: string): ResourceKind | null { const base = basePath(path); if (projectDetailId(base)) return "projects"; if (connectorDetailId(base)) return null; return resourceRoutes[base] ?? null; }
|