a gallery is a carousel

It always rendered as one — data-carousel, a snap track, two arrows, driven by
carousel.client.js. The entity was the last thing still calling it something
else, and that collided with the site's own Gallery section: two nav rows
reading Gallery and Galleries, meaning a list of objects and a list of
photograph sets.

GalleriesPanel, GalleryPicker and GalleryItems become Carousels*, the endpoint
becomes /fofos-admin/carousels, the block kind becomes carousel and
subject-gallery becomes subject-carousel. The publish allowlist follows the
renamed tables.

What did NOT move: GALLERY_CONFIG at /fofos-admin/gallery, subjects.ts's
base '/gallery', and home_gallery_media. Those are the Gallery section and the
legacy rows, and both are correct.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-04 18:01:15 +01:00
co-authored by Claude Opus 5
parent 5e5c06e76e
commit 15042ccc76
19 changed files with 148 additions and 148 deletions
+12 -12
View File
@@ -48,7 +48,7 @@ type Home = {
/** The OLD per-page list. Still returned by the API, and only rendered while no gallery is chosen. */
gallery: GalleryItem[];
/** Which gallery the carousel shows. Null means the old list above still applies. */
gallery_id: number | null;
carousel_id: number | null;
};
type Gallery = { id: number; name: string; slug: string; items: unknown[] };
@@ -65,7 +65,7 @@ export const HomePanel = () => {
const [error, setError] = useState<string | null>(null);
const [saved, flashSaved] = useFlash();
const [picking, setPicking] = useState(false);
const [galleries, setGalleries] = useState<Gallery[]>([]);
const [carousels, setCarousels] = useState<Gallery[]>([]);
/** Every write answers with the whole payload, so this is the only place state is set. */
const apply = useCallback((data: Home) => {
@@ -87,13 +87,13 @@ export const HomePanel = () => {
void load();
}, [load]);
// The galleries to choose between, read from the section that owns them rather than embedded in the
// The carousels to choose between, read from the section that owns them rather than embedded in the
// home payload — a copy there would go stale the moment somebody edited one.
useEffect(() => {
void clientRef.current
.get<{ data: Gallery[] }>('/fofos-admin/galleries')
.then((response) => setGalleries(response.data))
.catch(() => setGalleries([]));
.get<{ data: Gallery[] }>('/fofos-admin/carousels')
.then((response) => setCarousels(response.data))
.catch(() => setCarousels([]));
}, []);
const send = async (label: string, call: () => Promise<{ data: Home }>) => {
@@ -217,15 +217,15 @@ export const HomePanel = () => {
A picker, not a list.
Managing items here would be a second editor for something that already has one, and the two
would drift: a caption fixed in one place and not the other. The page chooses; the Galleries
would drift: a caption fixed in one place and not the other. The page chooses; the Carousels
section arranges.
*/}
<select
value={home.gallery_id ?? ''}
value={home.carousel_id ?? ''}
onChange={(event) =>
void send('gallery', () =>
void send('carousel', () =>
clientRef.current.patch<{ data: Home }>('/fofos-admin/home', {
gallery_id: event.target.value ? Number(event.target.value) : null,
carousel_id: event.target.value ? Number(event.target.value) : null,
}),
)
}
@@ -233,7 +233,7 @@ export const HomePanel = () => {
className="w-full rounded-md border border-border bg-background px-3 py-2 text-xs"
>
<option value="">None</option>
{galleries.map((gallery) => (
{carousels.map((gallery) => (
<option key={gallery.id} value={gallery.id}>
{gallery.name} · {gallery.items.length} item{gallery.items.length === 1 ? '' : 's'}
</option>
@@ -242,7 +242,7 @@ export const HomePanel = () => {
{/* Only while it is true: the old rows are what renders until a gallery is chosen, and saying so
beats a carousel that appears to come from nowhere. */}
{home.gallery_id === null && home.gallery.length > 0 && (
{home.carousel_id === null && home.gallery.length > 0 && (
<p className="text-xs text-muted-foreground/70">
Showing {home.gallery.length} item{home.gallery.length === 1 ? '' : 's'} from the old
per-page list. Choosing a gallery replaces it.