Add URL hash routing for direct project links
All checks were successful
ci/woodpecker/push/build Pipeline was successful

Opening #/project/123 navigates directly to the project page.
Back button and project selection update the hash accordingly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mikhail Kilin
2026-03-18 14:28:15 +03:00
parent 570e0ca643
commit 3bddb0012d

View File

@@ -180,23 +180,43 @@ function ProjectPage({
);
}
function parseHash(): { view: "list" | "project"; projectId: number | null } {
const hash = window.location.hash;
const match = hash.match(/^#\/project\/(\d+)$/);
if (match) return { view: "project", projectId: Number(match[1]) };
return { view: "list", projectId: null };
}
function App() {
const [view, setView] = useState<"list" | "project">("list");
const [projectId, setProjectId] = useState<number | null>(null);
const [view, setView] = useState<"list" | "project">(parseHash().view);
const [projectId, setProjectId] = useState<number | null>(parseHash().projectId);
useEffect(() => {
const onHashChange = () => {
const state = parseHash();
setView(state.view);
setProjectId(state.projectId);
};
window.addEventListener("hashchange", onHashChange);
return () => window.removeEventListener("hashchange", onHashChange);
}, []);
const navigate = (id: number | null) => {
if (id !== null) {
window.location.hash = `#/project/${id}`;
} else {
window.location.hash = "";
}
};
return (
<div className="app">
{view === "list" ? (
<ProjectList
onSelect={(id) => {
setProjectId(id);
setView("project");
}}
/>
<ProjectList onSelect={(id) => navigate(id)} />
) : (
<ProjectPage
projectId={projectId!}
onBack={() => setView("list")}
onBack={() => navigate(null)}
/>
)}
</div>