Implement creator studio and upload updates
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import React, { useState, useCallback, useEffect } from 'react'
|
||||
import React, { useState, useCallback, useEffect, useMemo } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import axios from 'axios'
|
||||
import ArtworkHero from '../components/artwork/ArtworkHero'
|
||||
import ArtworkMediaStrip from '../components/artwork/ArtworkMediaStrip'
|
||||
import ArtworkMeta from '../components/artwork/ArtworkMeta'
|
||||
import ArtworkAwards from '../components/artwork/ArtworkAwards'
|
||||
import ArtworkTags from '../components/artwork/ArtworkTags'
|
||||
@@ -40,6 +41,7 @@ function ArtworkPage({ artwork: initialArtwork, related: initialRelated, present
|
||||
const [related, setRelated] = useState(initialRelated)
|
||||
const [comments, setComments] = useState(initialComments)
|
||||
const [canonicalUrl, setCanonicalUrl] = useState(initialCanonical)
|
||||
const [selectedMediaId, setSelectedMediaId] = useState('cover')
|
||||
|
||||
// Nav arrow state — populated by ArtworkNavigator once neighbors resolve
|
||||
const [navState, setNavState] = useState({ hasPrev: false, hasNext: false, navigatePrev: null, navigateNext: null })
|
||||
@@ -68,11 +70,48 @@ function ArtworkPage({ artwork: initialArtwork, related: initialRelated, present
|
||||
setRelated([]) // cleared on navigation; user can scroll down for related
|
||||
setComments([]) // cleared; per-page server data
|
||||
setCanonicalUrl(data.canonical_url ?? window.location.href)
|
||||
setSelectedMediaId('cover')
|
||||
setViewerOpen(false) // close viewer when navigating away
|
||||
}, [])
|
||||
|
||||
if (!artwork) return null
|
||||
|
||||
const mediaItems = useMemo(() => {
|
||||
const coverItem = {
|
||||
id: 'cover',
|
||||
label: 'Cover art',
|
||||
thumbUrl: presentSq?.url || presentMd?.url || presentLg?.url || artwork?.thumbs?.sq?.url || artwork?.thumbs?.md?.url || null,
|
||||
mdUrl: presentMd?.url || artwork?.thumbs?.md?.url || null,
|
||||
lgUrl: presentLg?.url || artwork?.thumbs?.lg?.url || null,
|
||||
xlUrl: presentXl?.url || artwork?.thumbs?.xl?.url || null,
|
||||
width: Number(artwork?.dimensions?.width || artwork?.width || 0) || null,
|
||||
height: Number(artwork?.dimensions?.height || artwork?.height || 0) || null,
|
||||
}
|
||||
|
||||
const screenshotItems = Array.isArray(artwork?.screenshots)
|
||||
? artwork.screenshots.map((item, index) => ({
|
||||
id: item.id || `shot-${index + 1}`,
|
||||
label: item.label || `Screenshot ${index + 1}`,
|
||||
thumbUrl: item.thumb_url || item.url || null,
|
||||
mdUrl: item.url || item.thumb_url || null,
|
||||
lgUrl: item.url || item.thumb_url || null,
|
||||
xlUrl: item.url || item.thumb_url || null,
|
||||
width: null,
|
||||
height: null,
|
||||
}))
|
||||
: []
|
||||
|
||||
return [coverItem, ...screenshotItems].filter((item) => Boolean(item.thumbUrl || item.lgUrl || item.xlUrl))
|
||||
}, [artwork, presentMd, presentLg, presentXl, presentSq])
|
||||
|
||||
const selectedMedia = mediaItems.find((item) => item.id === selectedMediaId) || mediaItems[0] || null
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectedMedia && mediaItems.length > 0) {
|
||||
setSelectedMediaId(mediaItems[0].id)
|
||||
}
|
||||
}, [mediaItems, selectedMedia])
|
||||
|
||||
const initialAwards = artwork?.awards ?? null
|
||||
|
||||
return (
|
||||
@@ -82,15 +121,24 @@ function ArtworkPage({ artwork: initialArtwork, related: initialRelated, present
|
||||
<div id="artwork-hero-anchor" className="mx-auto w-full max-w-screen-2xl px-3 sm:px-6 lg:px-8">
|
||||
<ArtworkHero
|
||||
artwork={artwork}
|
||||
presentMd={presentMd}
|
||||
presentLg={presentLg}
|
||||
presentXl={presentXl}
|
||||
presentMd={selectedMedia?.mdUrl ? { url: selectedMedia.mdUrl } : presentMd}
|
||||
presentLg={selectedMedia?.lgUrl ? { url: selectedMedia.lgUrl } : presentLg}
|
||||
presentXl={selectedMedia?.xlUrl ? { url: selectedMedia.xlUrl } : presentXl}
|
||||
mediaWidth={selectedMedia?.width ?? null}
|
||||
mediaHeight={selectedMedia?.height ?? null}
|
||||
mediaKey={selectedMedia?.id || 'cover'}
|
||||
onOpenViewer={openViewer}
|
||||
hasPrev={navState.hasPrev}
|
||||
hasNext={navState.hasNext}
|
||||
onPrev={navState.navigatePrev}
|
||||
onNext={navState.navigateNext}
|
||||
/>
|
||||
|
||||
<ArtworkMediaStrip
|
||||
items={mediaItems}
|
||||
selectedId={selectedMedia?.id || 'cover'}
|
||||
onSelect={setSelectedMediaId}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* ── Centered action bar with stat counts ────────────────────── */}
|
||||
@@ -181,8 +229,8 @@ function ArtworkPage({ artwork: initialArtwork, related: initialRelated, present
|
||||
isOpen={viewerOpen}
|
||||
onClose={closeViewer}
|
||||
artwork={artwork}
|
||||
presentLg={presentLg}
|
||||
presentXl={presentXl}
|
||||
presentLg={selectedMedia?.lgUrl ? { url: selectedMedia.lgUrl } : presentLg}
|
||||
presentXl={selectedMedia?.xlUrl ? { url: selectedMedia.xlUrl } : presentXl}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user