sections are paths, not a query string

The admin declares its routes in the manifest, so /fofos-admin/layout/header and
/fofos-admin/pages/home are real URLs. One reader takes the two segments after
the mount; links carry no query string at all, so nothing leaks between
sections.

What stays in the query is how you are looking — device, tab, view — rather than
at what.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-01 04:57:29 +01:00
co-authored by Claude Opus 5
parent 4d7162363b
commit a7fc07c52f
7 changed files with 141 additions and 68 deletions
+16 -7
View File
@@ -1,7 +1,9 @@
import { useSearchParams } from 'react-router';
import { Navigate } from 'react-router';
import { href, useNav } from './routes';
import { DEFAULT_SECTION } from './sections';
import { Check, Eye, Loader2, Monitor, Pencil, Smartphone, Tablet } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { DEFAULT_SECTION, isSectionKey, sectionFor, sectionOpen, type SectionKey } from './sections';
import { sectionFor, sectionOpen, type SectionKey } from './sections';
import { AdministrationPanel } from './AdministrationPanel';
import { MediaPanel } from './MediaPanel';
import { GalleriesPanel } from './sections/GalleriesPanel';
@@ -98,20 +100,27 @@ const BarDeviceToggle = () => {
export const DetailPanel = () => {
const [params] = useSearchParams();
const raw = params.get('section');
/*
A page selected inside Pages opens the BUILDER, not the list with a row lit up. By SLUG, so the URL
says which page rather than which row — see pageParam in usePages.
The nav says the same thing — Pages is a section and the pages are rows under it — so the detail
panel follows it. `?page=` is what distinguishes the two, which keeps both addressable.
panel follows it. The second path segment is what distinguishes the two, which keeps both
addressable: `/fofos-admin/pages` is the list, `/fofos-admin/pages/home` is that page.
*/
const selectedPage = params.get('page');
const selected: SectionKey = isSectionKey(raw) ? raw : DEFAULT_SECTION;
const { section: selected, item: selectedPage, atIndex } = useNav();
const { ready, rootSet, loading } = useReady();
/*
The bare `/fofos-admin` redirected to its first section, once, replacing.
The screen has to render SOMETHING there, and rendering Layout while the address bar says nothing
means the URL stops describing what is on screen — which is the whole reason the sections moved out
of the query string. `replace`, so Back leaves the admin rather than bouncing off the redirect.
*/
if (atIndex) return <Navigate to={href(DEFAULT_SECTION)} replace />;
if (loading) {
return <div className="flex size-full items-center justify-center p-6 text-sm text-muted-foreground">Loading…</div>;
}