import { useEffect, useState } from 'react'; import { Columns2, Loader2, Square } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; export type SectionLayout = 'one' | 'two'; /** * The layouts, drawn rather than named. * * "One column" and "Two columns" are words for a shape, and a shape is faster to recognise than to * read. The words stay underneath for anybody the picture does not reach. * * This list and the site's own are two copies of the same fact — the database has it as a check * constraint and PageSection.tsx has it as a branch. A layout offered here that the site cannot draw * would render as nothing, so adding one means all three. */ const LAYOUTS: { value: SectionLayout; label: string; Icon: typeof Square; columns: number }[] = [ { value: 'one', label: 'One column', Icon: Square, columns: 1 }, { value: 'two', label: 'Two columns', Icon: Columns2, columns: 2 }, ]; /** * Naming a section and choosing its shape, before it exists. * * ── Why a name is asked for and not generated ── * * The name is never rendered on the site. It exists so a page of eight bands is navigable, and * "Section 4" tells nobody anything — which is precisely the state a generated name would leave every * page in. Asked once, at the only moment somebody knows what they are about to build. */ export const AddSectionDialog = ({ open, busy, onCancel, onCreate, }: { open: boolean; busy: boolean; onCancel: () => void; onCreate: (values: { name: string; layout: SectionLayout }) => void; }) => { const [name, setName] = useState(''); const [layout, setLayout] = useState('one'); // Fresh every time it opens. A dialog that remembers the last thing somebody typed and abandoned is // a dialog that quietly suggests they meant it. useEffect(() => { if (open) { setName(''); setLayout('one'); } }, [open]); const create = () => { const trimmed = name.trim(); if (!trimmed || busy) return; onCreate({ name: trimmed, layout }); }; return ( !next && onCancel()}> Add a section
setName(event.currentTarget.value)} // Enter creates, because a two-field form is one somebody expects to finish from the // keyboard. Guarded by the same check the button uses. onKeyDown={(event) => event.key === 'Enter' && create()} /> For you, not for the site. It never appears on the page.
{LAYOUTS.map(({ value, label, Icon, columns }) => ( ))}
{/* Dead without a name. The server refuses an empty one, and a button that fires a request only to show an error is a slower way of saying what the button could have said. */}
); };