import { useCallback, useEffect, useState } from 'react'; import { addCateringTable, adminCatering, deleteCateringTable, reorderCateringTables, saveCateringNotes, saveCateringTable, type CateringTable, } from '@/lib/api'; import { ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, CHECK, Icon, PLUS, TRASH, X, danger, field, iconButton, primary, secondary, shift, } from '@/components/admin/ui'; /** * The goodie box and catering price tables, editable by the person who quotes them. * * A table is edited as a table and saved in one go, unlike the catalogue next door where every change * saves as you make it. That's not a different taste in interfaces: a column heading, its price and * the entries beneath it only mean anything together, so they have to be moved, added and removed * together. Adding a column here adds an empty entry to every line, and removing one takes its * entries with it — the server refuses any table whose lines and columns disagree, because the * alternative is the Large box quietly advertising the Medium box's contents at the Large price. */ // --- what's on screen ------------------------------------------------------- type TierDraft = { id: number | null; label: string; price: string }; type RowDraft = { id: number | null; label: string; values: string[] }; type Draft = { name: string; blurb: string; tiers: TierDraft[]; rows: RowDraft[]; notes: string[] }; const draftOf = (table: CateringTable): Draft => ({ name: table.name, blurb: table.blurb ?? '', // The price arrives written out ("$24"); it goes back as whatever the editor leaves in the box, and // the server decides what that's worth. tiers: table.tiers.map((tier) => ({ id: tier.id, label: tier.label, price: tier.price ?? '' })), rows: table.rows.map((row) => ({ id: row.id, label: row.label, values: [...row.values] })), notes: [...table.notes], }); /** Notes are edited as a list; deleting one is an omission, exactly as the server expects. */ const Notes = ({ notes, hint, disabled, onChange, }: { notes: string[]; hint: string; disabled?: boolean; onChange: (notes: string[]) => void; }) => (

{hint}