Make profile formatting hydration-safe
This commit is contained in:
@@ -1,14 +1,11 @@
|
||||
import React from 'react'
|
||||
import { formatProfileDate, formatProfileNumber } from '../../lib/profileFormatters'
|
||||
|
||||
function formatDate(value) {
|
||||
if (!value) return null
|
||||
|
||||
try {
|
||||
return new Intl.DateTimeFormat('en', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
}).format(new Date(value))
|
||||
return formatProfileDate(value, { month: 'short', day: 'numeric', year: 'numeric' })
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
@@ -17,7 +14,7 @@ function formatDate(value) {
|
||||
function formatYear(value) {
|
||||
if (!value) return null
|
||||
try {
|
||||
return new Intl.DateTimeFormat('en', { year: 'numeric' }).format(new Date(value))
|
||||
return formatProfileDate(value, { year: 'numeric' })
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
@@ -268,8 +265,8 @@ function YearlyProductivityChart({ recaps }) {
|
||||
<div className="absolute inset-y-0 left-0 flex w-full items-center px-3 opacity-0 transition-opacity group-hover:opacity-100">
|
||||
<span className="text-[11px] font-semibold text-white drop-shadow-sm">
|
||||
{uploads} upload{uploads !== 1 ? 's' : ''}
|
||||
{(item.metrics?.views ?? 0) > 0 ? ` · ${Number(item.metrics.views).toLocaleString()} views` : ''}
|
||||
{(item.metrics?.downloads ?? 0) > 0 ? ` · ${Number(item.metrics.downloads).toLocaleString()} dl` : ''}
|
||||
{(item.metrics?.views ?? 0) > 0 ? ` · ${formatProfileNumber(item.metrics.views)} views` : ''}
|
||||
{(item.metrics?.downloads ?? 0) > 0 ? ` · ${formatProfileNumber(item.metrics.downloads)} dl` : ''}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -292,8 +289,8 @@ function YearlyProductivityChart({ recaps }) {
|
||||
{/* Summary footer */}
|
||||
<div className="mt-5 flex flex-wrap gap-4 border-t border-white/5 pt-4 text-[12px] text-slate-400">
|
||||
<span><span className="font-semibold text-white">{sorted.length}</span> active years</span>
|
||||
<span><span className="font-semibold text-white">{sorted.reduce((s, r) => s + r.metrics.uploads_count, 0).toLocaleString()}</span> total uploads</span>
|
||||
<span><span className="font-semibold text-white">{Number(sorted.reduce((s, r) => s + (r.metrics.views ?? 0), 0)).toLocaleString()}</span> total views</span>
|
||||
<span><span className="font-semibold text-white">{formatProfileNumber(sorted.reduce((s, r) => s + r.metrics.uploads_count, 0))}</span> total uploads</span>
|
||||
<span><span className="font-semibold text-white">{formatProfileNumber(sorted.reduce((s, r) => s + (r.metrics.views ?? 0), 0))}</span> total views</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@@ -550,8 +547,8 @@ export default function CreatorJourneySection({ journey, username }) {
|
||||
<p className="mt-3 text-sm leading-relaxed text-slate-300">{item.summary}</p>
|
||||
|
||||
<div className="mt-4 grid gap-2 sm:grid-cols-2">
|
||||
<StatPill label="Views" value={(item.metrics?.views ?? 0).toLocaleString()} />
|
||||
<StatPill label="Downloads" value={(item.metrics?.downloads ?? 0).toLocaleString()} />
|
||||
<StatPill label="Views" value={formatProfileNumber(item.metrics?.views ?? 0)} />
|
||||
<StatPill label="Downloads" value={formatProfileNumber(item.metrics?.downloads ?? 0)} />
|
||||
{(item.metrics?.featured_count ?? 0) > 0 && (
|
||||
<StatPill label="Featured" value={item.metrics.featured_count} />
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user