'use client';
/**
* The two drag-sortable tiles of the page builder (#608): a hero photo, and
* a subpage in the page list. Album cards are in ./AlbumCard.tsx.
*/
import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { IconFolder, IconGripVertical, IconLock, IconPencil, IconX } from '../Icons';
import type { Subpage } from './types';
// ── Sortable Hero Tile ─────────────────────────────────────────
export function SortableHeroTile({
id,
index,
onRemove,
}: {
id: string;
index: number;
onRemove: () => void;
}) {
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
id: `hero-${index}`,
});
const style = {
transform: CSS.Transform.toString(transform),
transition,
opacity: isDragging ? 0.5 : 1,
zIndex: isDragging ? 10 : undefined,
};
return (
{index + 1}
);
}
// ── Sortable Subpage Tile ──────────────────────────────────────
export function SortableSubpageTile({
sp,
spIndex,
isActive,
onClick,
getFirstThumb,
}: {
sp: Subpage;
spIndex: number;
isActive: boolean;
onClick: () => void;
getFirstThumb: (sp: Subpage) => string | null;
}) {
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
id: `subpage-${spIndex}`,
});
const style = {
transform: CSS.Transform.toString(transform),
transition,
opacity: isDragging ? 0.5 : 1,
zIndex: isDragging ? 10 : undefined,
};
const totalAlbums =
sp.albums.length + (sp.sections?.reduce((sum, sec) => sum + sec.albums.length, 0) || 0);
const firstThumb = getFirstThumb(sp);
const slug = sp.name
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-|-$/g, '');
return (
{sp.enabled === false && (
Disabled
)}
{sp.hidden === true && sp.enabled !== false && (
Unlisted
)}
{sp.password && (
Password
)}
{firstThumb ? (

) : (
)}
Edit Page
{sp.title || sp.name}
/{slug}
{totalAlbums} album{totalAlbums !== 1 ? 's' : ''}
);
}
// ── Component ──────────────────────────────────────────────────
// ── Sortable Subpage Row (stage 4 structure list) ──────────────
/**
* One subpage in the page builder's structure list (UX stage 4): drag handle,
* cover, name, state and album count, in one line. Same sortable id as the
* tile it replaces, so the builder's drag handler is unchanged.
*/
export function SortableSubpageRow({
sp,
spIndex,
isActive,
onClick,
getFirstThumb,
}: {
sp: Subpage;
spIndex: number;
isActive: boolean;
onClick: () => void;
getFirstThumb: (sp: Subpage) => string | null;
}) {
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
id: `subpage-${spIndex}`,
});
const totalAlbums =
sp.albums.length + (sp.sections?.reduce((sum, sec) => sum + sec.albums.length, 0) || 0);
const thumb = getFirstThumb(sp);
return (
);
}