Layout is one row; Pages always shows the pages
Top Menu, Content and Footer were a hierarchy the screen does not have — all three are edited by the same controls at the same time, so clicking one changed the URL and nothing else. The pages were announced by PagesPanel and only by PagesPanel, which mounts when Pages is open. So they were invisible in the nav until you had already been to the page that lists them. The nav fetches them itself when nobody has said yet; the channel stays, and is still why a rename shows here the moment it is typed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+29
-41
@@ -1,9 +1,11 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import { useClient } from 'hooks/useClient';
|
||||
import { Lock } from 'lucide-react';
|
||||
import { LAYOUT_BANDS, SECTIONS, sectionOpen } from './sections';
|
||||
import { SECTIONS, sectionOpen } from './sections';
|
||||
import { href, useNav } from './routes';
|
||||
import { useReady } from './useReady';
|
||||
import { pageParam, usePages } from './usePages';
|
||||
import { pageParam, usePages, type Page } from './usePages';
|
||||
|
||||
/**
|
||||
* The left column: which part of the fofos site the detail panel is showing.
|
||||
@@ -50,12 +52,34 @@ const rowClass = (active: boolean) =>
|
||||
}`;
|
||||
|
||||
export const NavPanel = () => {
|
||||
// Announced by PagesPanel rather than fetched here — see usePages. Null until it has spoken, which
|
||||
// is why nothing is drawn instead of an empty list.
|
||||
const { pages } = usePages();
|
||||
const { pages, announce } = usePages();
|
||||
const { section: active, item } = useNav();
|
||||
const { ready, rootSet } = useReady();
|
||||
|
||||
/*
|
||||
The pages, fetched HERE when nobody has said yet.
|
||||
|
||||
They were announced by PagesPanel and only by PagesPanel — which mounts when Pages is the open
|
||||
section, so the site's pages were invisible in the nav until you had already been to the page that
|
||||
lists them. The one place they most need to be is the one place they were not.
|
||||
|
||||
The channel stays and is still the reason the nav renames a page the moment the editor does: two
|
||||
fetchers would agree until somebody typed. This only fills a silence.
|
||||
*/
|
||||
const client = useClient();
|
||||
const clientRef = useRef(client);
|
||||
clientRef.current = client;
|
||||
|
||||
useEffect(() => {
|
||||
if (pages !== null || !ready) return;
|
||||
void clientRef.current
|
||||
.get<{ data: Page[] }>('/fofos-admin/pages')
|
||||
.then((body) => announce(body.data))
|
||||
// Left null: the nav then draws no children, which is what it did before and is not a failure
|
||||
// worth a message in a list of links.
|
||||
.catch(() => {});
|
||||
}, [pages, ready, announce]);
|
||||
|
||||
const renderRow = (section: (typeof SECTIONS)[number]) => {
|
||||
const Icon = section.icon;
|
||||
// Each section asks its own question now — Media wants a root location, the site's pages want a
|
||||
@@ -118,42 +142,6 @@ export const NavPanel = () => {
|
||||
Drawn whether or not Pages is the open section. The list of pages IS the site, and hiding it
|
||||
until you click makes the nav a menu of menus.
|
||||
*/
|
||||
/*
|
||||
Layout's three bands, as rows under Layout.
|
||||
|
||||
The layout IS a page — a header, the slot a page goes in, and a footer — and those three are the
|
||||
only things on this screen. They were reachable by scrolling and by knowing which tab held what;
|
||||
as rows they are the same shape as the pages under Pages, which is the shape the nav already
|
||||
teaches.
|
||||
|
||||
Fixed rather than fetched: unlike pages, these three are structural. A band cannot be added or
|
||||
removed from the admin, only the code that draws it can, so a list read from the database would
|
||||
be a query that can only ever return the same three rows.
|
||||
*/
|
||||
if (section.key === 'layout') {
|
||||
return (
|
||||
<div key={section.key} className="flex flex-col">
|
||||
{row}
|
||||
{LAYOUT_BANDS.map((band) => {
|
||||
const current = active === 'layout' && item === band.key;
|
||||
|
||||
return (
|
||||
<Link
|
||||
key={band.key}
|
||||
to={href('layout', band.key)}
|
||||
replace
|
||||
className={`flex items-baseline gap-2 border-b border-border py-1.5 pr-3 pl-9 text-left transition-colors ${
|
||||
current ? 'bg-muted' : 'hover:bg-muted/50'
|
||||
}`}
|
||||
>
|
||||
<span className="min-w-0 flex-1 truncate text-xs">{band.label}</span>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (section.key !== 'pages' || !pages?.length) return row;
|
||||
|
||||
return (
|
||||
|
||||
+6
-20
@@ -70,27 +70,13 @@ export type Section = {
|
||||
pinned?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* The three bands the layout is made of, in the order they appear on the page.
|
||||
*
|
||||
* The layout IS a page: a header, the slot a page goes in, and a footer. These are the nav rows under
|
||||
* Layout, and the `band` in the query string.
|
||||
*
|
||||
* FIXED, unlike the pages under Pages. A band cannot be added or removed from the admin — only the
|
||||
* code that draws it can — so reading them from the database would be a query that can only ever
|
||||
* return the same three rows in the same order.
|
||||
*/
|
||||
export const LAYOUT_BANDS = [
|
||||
{ key: 'header', label: 'Top Menu' },
|
||||
{ key: 'content', label: 'Content' },
|
||||
{ key: 'footer', label: 'Footer' },
|
||||
] as const;
|
||||
|
||||
export type LayoutBand = (typeof LAYOUT_BANDS)[number]['key'];
|
||||
|
||||
export const isLayoutBand = (value: string | null): value is LayoutBand =>
|
||||
value !== null && LAYOUT_BANDS.some((band) => band.key === value);
|
||||
/*
|
||||
Layout had three rows under it — Top Menu, Content, Footer — and they are gone.
|
||||
|
||||
They were a hierarchy the screen did not have: all three are edited in the same panel, by the same
|
||||
controls, at the same time. Clicking one changed the URL and nothing else, which teaches that the
|
||||
nav does not mean anything. Pages keeps its children because a page IS a destination.
|
||||
*/
|
||||
export const SECTIONS: Section[] = [
|
||||
{
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user