import React from 'react' import CollectionVisibilityBadge from './CollectionVisibilityBadge' async function requestJson(url, { method = 'GET', body } = {}) { const response = await fetch(url, { method, credentials: 'same-origin', headers: { Accept: 'application/json', 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '', 'X-Requested-With': 'XMLHttpRequest', }, body: body ? JSON.stringify(body) : undefined, }) const payload = await response.json().catch(() => ({})) if (!response.ok) { const message = payload?.message || 'Request failed.' throw new Error(message) } return payload } function formatUpdated(value) { if (!value) return 'Updated recently' const date = new Date(value) if (Number.isNaN(date.getTime())) return 'Updated recently' return new Intl.DateTimeFormat(undefined, { month: 'short', day: 'numeric', year: 'numeric', }).format(date) } function StatPill({ icon, label, value }) { return ( {value} {label} ) } export default function CollectionCard({ collection, isOwner, onDelete, onToggleFeature, onMoveUp, onMoveDown, canMoveUp, canMoveDown, busy = false, saveContext = null, saveContextMeta = null }) { const coverImage = collection?.cover_image const [saved, setSaved] = React.useState(Boolean(collection?.saved)) const [saveBusy, setSaveBusy] = React.useState(false) React.useEffect(() => { setSaved(Boolean(collection?.saved)) setSaveBusy(false) }, [collection?.id, collection?.saved]) function handleDelete(event) { event.preventDefault() event.stopPropagation() onDelete?.(collection) } function stop(event) { event.stopPropagation() } function handleToggleFeature(event) { event.preventDefault() event.stopPropagation() onToggleFeature?.(collection) } async function handleSaveToggle(event) { event.preventDefault() event.stopPropagation() if (saveBusy) return const targetUrl = saved ? collection?.unsave_url : collection?.save_url if (!targetUrl) { if (collection?.login_url) { window.location.assign(collection.login_url) } return } setSaveBusy(true) try { const payload = await requestJson(targetUrl, { method: saved ? 'DELETE' : 'POST', body: saved ? undefined : { context: saveContext, context_meta: saveContextMeta || undefined, }, }) setSaved(Boolean(payload?.saved)) } catch (error) { window.console?.error?.(error) } finally { setSaveBusy(false) } } return (
{coverImage ? (
{collection?.title
) : (
)}
{collection?.is_featured ? ( Featured ) : null} {collection?.mode === 'smart' ? ( Smart ) : null} {!isOwner && collection?.program_key ? ( Program · {collection.program_key} ) : null} {!isOwner && collection?.partner_label ? ( Partner · {collection.partner_label} ) : null} {!isOwner && collection?.sponsorship_label ? ( Sponsor · {collection.sponsorship_label} ) : null} {isOwner ? : null}

{collection?.title}

{collection?.subtitle ?

{collection.subtitle}

: null} {collection?.owner?.name ?

Curated by {collection.owner.name}{collection?.owner?.username ? ` • @${collection.owner.username}` : ''}

: null}

{(collection?.artworks_count ?? 0).toLocaleString()} artworks

{collection?.description_excerpt ? (

{collection.description_excerpt}

) : collection?.smart_summary ? (

{collection.smart_summary}

) : null}
{collection?.collaborators_count > 1 ? : null}
{collection?.is_featured ? 'Featured' : 'Updated'} {formatUpdated(collection?.featured_at || collection?.updated_at)}
{!isOwner && (collection?.save_url || collection?.unsave_url || collection?.login_url) ? ( ) : null} Open
{isOwner ? (
{collection?.visibility === 'public' ? ( ) : null} Edit Manage Artworks {onMoveUp ? ( ) : null} {onMoveDown ? ( ) : null} {collection?.delete_url ? ( ) : null}
) : null}
) }