feat: ship creator journey v2 and profile updates

This commit is contained in:
2026-04-12 21:42:07 +02:00
parent a2457f4e49
commit d5cff21ea2
335 changed files with 20147 additions and 1545 deletions

View File

@@ -34,14 +34,6 @@ function BookmarkIcon({ filled }) {
)
}
function CloudDownIcon() {
return (
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="h-5 w-5">
<path strokeLinecap="round" strokeLinejoin="round" d="M12 9.75v6.75m0 0-3-3m3 3 3-3m-8.25 6a4.5 4.5 0 0 1-1.41-8.775 5.25 5.25 0 0 1 10.233-2.33 3 3 0 0 1 3.758 3.848A3.752 3.752 0 0 1 18 19.5H6.75Z" />
</svg>
)
}
function DownloadArrowIcon() {
return (
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor" className="h-4 w-4">
@@ -216,17 +208,13 @@ export default function ArtworkActionBar({ artwork, stats, canonicalUrl, onStats
? document.querySelector('meta[name="csrf-token"]')?.getAttribute('content')
: null
// Track view
// Count a view on every page load.
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
@@ -310,7 +298,6 @@ export default function ArtworkActionBar({ artwork, stats, canonicalUrl, onStats
const favCount = formatCount(stats?.favorites ?? artwork?.stats?.favorites ?? 0)
const savedCount = formatCount(bookmarkCount)
const viewCount = formatCount(stats?.views ?? artwork?.stats?.views ?? 0)
return (
<>
@@ -347,12 +334,6 @@ export default function ArtworkActionBar({ artwork, stats, canonicalUrl, onStats
<span className="tabular-nums">{savedCount}</span>
</button>
{/* Views stat pill */}
<div className="inline-flex items-center gap-2 rounded-full border border-white/[0.08] bg-white/[0.04] px-5 py-2.5 text-sm font-medium text-white/70">
<CloudDownIcon />
<span className="tabular-nums">{viewCount}</span>
</div>
{/* Share pill */}
<ArtworkShareButton artwork={artwork} shareUrl={shareUrl} size="default" isLoggedIn={isLoggedIn} />