feat: add reusable gallery carousel and ranking feed infrastructure
This commit is contained in:
@@ -21,6 +21,17 @@ function ArtworkPage({ artwork: initialArtwork, related: initialRelated, present
|
||||
|
||||
// Navigable state — updated on client-side navigation
|
||||
const [artwork, setArtwork] = useState(initialArtwork)
|
||||
const [liveStats, setLiveStats] = useState(initialArtwork?.stats || {})
|
||||
|
||||
const handleStatsChange = useCallback((delta) => {
|
||||
setLiveStats(prev => {
|
||||
const next = { ...prev }
|
||||
Object.entries(delta).forEach(([key, val]) => {
|
||||
next[key] = Math.max(0, (Number(next[key]) || 0) + val)
|
||||
})
|
||||
return next
|
||||
})
|
||||
}, [])
|
||||
const [presentMd, setPresentMd] = useState(initialMd)
|
||||
const [presentLg, setPresentLg] = useState(initialLg)
|
||||
const [presentXl, setPresentXl] = useState(initialXl)
|
||||
@@ -38,6 +49,7 @@ function ArtworkPage({ artwork: initialArtwork, related: initialRelated, present
|
||||
*/
|
||||
const handleNavigate = useCallback((data) => {
|
||||
setArtwork(data)
|
||||
setLiveStats(data.stats || {})
|
||||
setPresentMd(data.thumbs?.md ?? null)
|
||||
setPresentLg(data.thumbs?.lg ?? null)
|
||||
setPresentXl(data.thumbs?.xl ?? null)
|
||||
@@ -69,14 +81,14 @@ function ArtworkPage({ artwork: initialArtwork, related: initialRelated, present
|
||||
|
||||
<div className="mt-6 space-y-4 lg:hidden">
|
||||
<ArtworkAuthor artwork={artwork} presentSq={presentSq} />
|
||||
<ArtworkActions artwork={artwork} canonicalUrl={canonicalUrl} mobilePriority />
|
||||
<ArtworkActions artwork={artwork} canonicalUrl={canonicalUrl} mobilePriority onStatsChange={handleStatsChange} />
|
||||
<ArtworkAwards artwork={artwork} initialAwards={initialAwards} isAuthenticated={isAuthenticated} />
|
||||
</div>
|
||||
|
||||
<div className="mt-8 grid grid-cols-1 gap-8 lg:grid-cols-3">
|
||||
<div className="space-y-6 lg:col-span-2">
|
||||
<ArtworkMeta artwork={artwork} />
|
||||
<ArtworkStats artwork={artwork} />
|
||||
<ArtworkStats artwork={artwork} stats={liveStats} />
|
||||
<ArtworkTags artwork={artwork} />
|
||||
<ArtworkDescription artwork={artwork} />
|
||||
<ArtworkReactions artworkId={artwork.id} isLoggedIn={isAuthenticated} />
|
||||
@@ -91,7 +103,7 @@ function ArtworkPage({ artwork: initialArtwork, related: initialRelated, present
|
||||
<aside className="hidden space-y-6 lg:block">
|
||||
<div className="sticky top-24 space-y-4">
|
||||
<ArtworkAuthor artwork={artwork} presentSq={presentSq} />
|
||||
<ArtworkActions artwork={artwork} canonicalUrl={canonicalUrl} />
|
||||
<ArtworkActions artwork={artwork} canonicalUrl={canonicalUrl} onStatsChange={handleStatsChange} />
|
||||
<ArtworkAwards artwork={artwork} initialAwards={initialAwards} isAuthenticated={isAuthenticated} />
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
Reference in New Issue
Block a user