import { useCallback, useEffect, useRef, useState } from 'react'; import { useSearchParams } from 'react-router'; import { useClient } from 'hooks/useClient'; import { DEFAULT_SECTION, isSectionKey, type SectionKey } from './sections'; import { HostsPanel } from './HostsPanel'; import { CertificatesPanel } from './CertificatesPanel'; import { ConnectionPanel } from './ConnectionPanel'; import { ListSection, REDIRECTIONS, STREAMS, DEAD_HOSTS, ACCESS_LISTS } from './ListSection'; import { useConnectionChanged } from './channel'; /** * The right column: whichever section the nav has selected. * * It reads `?section=` from the URL rather than being handed it — the two panels are siblings in a * workspace and neither owns the other, and `docs/navigation-audit.md` puts addressable state in the URL * for exactly this reason. A bogus or missing value falls back rather than rendering nothing. * * ── The unconfigured check lives HERE, once ── * * Every section needs a connection, so every section would otherwise have to handle its absence, and each * one would say something slightly different. Asking `/status` once and rendering the connection form * instead of any section is the same answer for all seven, and it means "no connection yet" reads as a * setup step rather than as six broken lists. */ type Status = { configured: boolean }; export const DetailPanel = () => { const [params] = useSearchParams(); const raw = params.get('section'); const section: SectionKey = isSectionKey(raw) ? raw : DEFAULT_SECTION; const client = useClient(); const clientRef = useRef(client); clientRef.current = client; const [configured, setConfigured] = useState(null); const [connectionSignal] = useConnectionChanged(); const check = useCallback(async () => { try { const status = await clientRef.current.get('/proxy-manager/status'); setConfigured(status.configured); } catch { // Cannot tell. Render the section rather than the setup form — a transient failure must not look // like "you have not set this up", which is a much more alarming thing to be told. setConfigured(true); } }, []); useEffect(() => { void check(); }, [check, connectionSignal]); if (configured === null) { return
Loading…
; } if (!configured || section === 'connection') return ; switch (section) { case 'proxy-hosts': return ; case 'certificates': return ; case 'redirections': return ; case 'streams': return ; case 'dead-hosts': return ; case 'access-lists': return ; } };