import { useCallback, useEffect, useRef, useState } from 'react';
import { useSearchParams } from 'react-router';
import { useClient } from 'hooks/useClient';
import { DEFAULT_SECTION, isSectionKey, sectionFor, type SectionKey } from './sections';
import { ConnectionPanel } from './ConnectionPanel';
import { MessagesPanel } from './MessagesPanel';
import { PlannedSection } from './PlannedSection';
import { useFofosChanged } 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.
*
* ── There used to be a `?config=1` ──
*
* The connection form was an overlay reached from a link in this header, because it was not one of the
* sections. Now it IS one — Administration — so the overlay is gone and so is the link. A second route
* to the same screen is a second thing to keep correct, and the two disagreed the moment a section was
* selected underneath a form that covered it.
*
* ── The unconfigured check lives HERE, once ──
*
* Every OTHER section needs a connection, so each would otherwise have to handle its absence and each
* would word it slightly differently. Asking `/status` once and sending an unconfigured plugin to
* Administration is one answer for all of them, and it makes "not connected yet" read as a setup step
* rather than as nine broken lists.
*/
type Status = { configured: boolean; lastProbeOk: boolean | null };
/**
* Which component renders which section.
*
* A map rather than a conditional on `built`. The version of this that read
* `built ? : ` was correct only while exactly one section existed — the
* second one to be finished would have rendered Messages under its own name, which is the kind of bug
* that looks like a data problem for an hour. A key with no entry here falls through to Planned, so
* marking a section `built` in sections.ts without writing its panel fails visibly rather than
* silently showing somebody else's.
*/
const PANELS: Partial React.JSX.Element>> = {
messages: MessagesPanel,
administration: ConnectionPanel,
};
export const DetailPanel = () => {
const [params] = useSearchParams();
const raw = params.get('section');
const selected: SectionKey = isSectionKey(raw) ? raw : DEFAULT_SECTION;
const client = useClient();
const clientRef = useRef(client);
clientRef.current = client;
const [configured, setConfigured] = useState(null);
const [signal] = useFofosChanged();
const check = useCallback(async () => {
try {
const status = await clientRef.current.get('/fofos-admin/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, and would
// invite somebody to re-enter a connection that was never the problem.
setConfigured(true);
}
}, []);
useEffect(() => {
void check();
}, [check, signal]);
if (configured === null) {
return
Loading…
;
}
/*
Unconfigured, so Administration regardless of what the nav says. The header then NAMES it, which is
the part the overlay could not do: the form used to appear under whichever row happened to be
highlighted, so it read as that section being broken rather than as one step not done yet.
*/
const current = sectionFor(configured ? selected : 'administration');
const Panel = current.built ? PANELS[current.key] : undefined;
return (