import React, { useEffect, useState } from 'react' function formatCount(value) { const n = Number(value || 0) if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1).replace(/\.0$/, '')}M` if (n >= 1_000) return `${(n / 1_000).toFixed(1).replace(/\.0$/, '')}k` return `${n}` } /* ── SVG Icons ─────────────────────────────────────────────────────────────── */ function HeartIcon({ filled }) { return filled ? ( ) : ( ) } function BookmarkIcon({ filled }) { return filled ? ( ) : ( ) } function CloudDownIcon() { return ( ) } function DownloadArrowIcon() { return ( ) } function ShareIcon() { return ( ) } function FlagIcon() { return ( ) } export default function ArtworkActionBar({ artwork, stats, canonicalUrl, onStatsChange }) { const [liked, setLiked] = useState(Boolean(artwork?.viewer?.is_liked)) const [favorited, setFavorited] = useState(Boolean(artwork?.viewer?.is_favorited)) const [downloading, setDownloading] = useState(false) const [reporting, setReporting] = useState(false) const [copied, setCopied] = useState(false) useEffect(() => { setLiked(Boolean(artwork?.viewer?.is_liked)) setFavorited(Boolean(artwork?.viewer?.is_favorited)) }, [artwork?.id, artwork?.viewer?.is_liked, artwork?.viewer?.is_favorited]) const fallbackUrl = artwork?.thumbs?.xl?.url || artwork?.thumbs?.lg?.url || artwork?.file?.url || '#' const shareUrl = canonicalUrl || artwork?.canonical_url || (typeof window !== 'undefined' ? window.location.href : '#') const csrfToken = typeof document !== 'undefined' ? document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') : null // Track view useEffect(() => { if (!artwork?.id) return const key = `sb_viewed_${artwork.id}` if (typeof sessionStorage !== 'undefined' && sessionStorage.getItem(key)) return fetch(`/api/art/${artwork.id}/view`, { method: 'POST', headers: { 'X-CSRF-TOKEN': csrfToken || '', 'Content-Type': 'application/json' }, credentials: 'same-origin', }).then(res => { if (res.ok && typeof sessionStorage !== 'undefined') sessionStorage.setItem(key, '1') }).catch(() => {}) }, [artwork?.id]) // eslint-disable-line react-hooks/exhaustive-deps const postInteraction = async (url, body) => { const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken || '' }, credentials: 'same-origin', body: JSON.stringify(body), }) if (!response.ok) throw new Error('Request failed') return response.json() } const handleDownload = async () => { if (downloading || !artwork?.id) return setDownloading(true) try { const res = await fetch(`/api/art/${artwork.id}/download`, { method: 'POST', headers: { 'X-CSRF-TOKEN': csrfToken || '', 'Content-Type': 'application/json' }, credentials: 'same-origin', }) const data = res.ok ? await res.json() : null const url = data?.url || fallbackUrl const a = document.createElement('a') a.href = url a.download = data?.filename || '' a.rel = 'noopener noreferrer' document.body.appendChild(a) a.click() document.body.removeChild(a) } catch { window.open(fallbackUrl, '_blank', 'noopener,noreferrer') } finally { setDownloading(false) } } const onToggleLike = async () => { const nextState = !liked setLiked(nextState) try { await postInteraction(`/api/artworks/${artwork.id}/like`, { state: nextState }) onStatsChange?.({ likes: nextState ? 1 : -1 }) } catch { setLiked(!nextState) } } const onToggleFavorite = async () => { const nextState = !favorited setFavorited(nextState) try { await postInteraction(`/api/artworks/${artwork.id}/favorite`, { state: nextState }) onStatsChange?.({ favorites: nextState ? 1 : -1 }) } catch { setFavorited(!nextState) } } const onShare = async () => { try { if (navigator.share) { await navigator.share({ title: artwork?.title || 'Artwork', url: shareUrl }) return } await navigator.clipboard.writeText(shareUrl) setCopied(true) setTimeout(() => setCopied(false), 2000) } catch { /* noop */ } } const onReport = async () => { if (reporting) return setReporting(true) try { await postInteraction(`/api/artworks/${artwork.id}/report`, { reason: 'Reported from artwork page' }) } catch { /* noop */ } finally { setReporting(false) } } const likeCount = formatCount(stats?.likes ?? artwork?.stats?.likes ?? 0) const favCount = formatCount(stats?.favorites ?? artwork?.stats?.favorites ?? 0) const viewCount = formatCount(stats?.views ?? artwork?.stats?.views ?? 0) return ( <> {/* ── Desktop centered bar ────────────────────────────────────── */}
{/* Like stat pill */} {/* Favorite/bookmark stat pill */} {/* Views stat pill */}
{viewCount}
{/* Share pill */} {/* Report pill */} {/* Download button */}
{/* ── Mobile fixed bottom bar ─────────────────────────────────── */}
{/* Share */} {/* Report */}
) }