Files
SkinbaseNova/resources/js/components/profile/worlds/ProfileWorldHistorySection.jsx

114 lines
5.4 KiB
JavaScript

import React from 'react'
import ProfileWorldHistorySummary from './ProfileWorldHistorySummary'
import ProfileWorldTimelineList from './ProfileWorldTimelineList'
function EmptyState({ isOwner, hasPrivateContext }) {
return (
<div className="rounded-[30px] border border-dashed border-white/12 bg-white/[0.03] px-6 py-16 text-center">
<div className="mx-auto flex h-16 w-16 items-center justify-center rounded-3xl border border-white/10 bg-white/[0.05] text-slate-500">
<i className="fa-solid fa-globe text-2xl" />
</div>
<h3 className="mt-5 text-xl font-semibold text-white">No public worlds timeline yet</h3>
<p className="mx-auto mt-3 max-w-xl text-sm leading-relaxed text-slate-400">
{isOwner
? (hasPrivateContext
? 'Public world history appears here once a live, publicly visible submission or recognized placement is available. Until then, private-only world activity is still tracked for you above.'
: 'Public world history appears here once a live, publicly visible submission or recognized placement is available.')
: 'This creator does not have any public world participation or recognition to show yet.'}
</p>
</div>
)
}
function OwnerNote({ ownerContext }) {
if (!ownerContext) {
return null
}
const details = [
ownerContext.pending_submissions ? `${ownerContext.pending_submissions} pending submission${ownerContext.pending_submissions === 1 ? '' : 's'}` : null,
ownerContext.removed_or_blocked_submissions ? `${ownerContext.removed_or_blocked_submissions} removed or blocked item${ownerContext.removed_or_blocked_submissions === 1 ? '' : 's'}` : null,
ownerContext.hidden_public_entries ? `${ownerContext.hidden_public_entries} recognition${ownerContext.hidden_public_entries === 1 ? '' : 's'} hidden from public view` : null,
].filter(Boolean)
if (details.length === 0) {
return null
}
return (
<div className="rounded-[24px] border border-sky-300/15 bg-sky-400/10 px-5 py-4 text-sm text-sky-100">
<div className="flex items-start gap-3">
<div className="mt-0.5 inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-2xl border border-sky-300/20 bg-sky-300/10 text-sky-100">
<i className="fa-solid fa-eye text-sm" />
</div>
<div>
<div className="text-[11px] font-semibold uppercase tracking-[0.18em] text-sky-100/80">Private View</div>
<p className="mt-1 leading-relaxed text-sky-50/90">
Your public worlds timeline stays strict about visibility, but this profile still tracks {details.join(', ')}.
</p>
</div>
</div>
</div>
)
}
export default function ProfileWorldHistorySection({ history, isOwner }) {
const entries = Array.isArray(history?.entries) ? history.entries : []
const highlights = Array.isArray(history?.highlights) ? history.highlights : []
const highlightIds = new Set(highlights.map((entry) => entry?.id).filter(Boolean))
const timelineEntries = entries.filter((entry) => !highlightIds.has(entry?.id))
const hasPrivateContext = Boolean(
history?.owner_context?.pending_submissions
|| history?.owner_context?.removed_or_blocked_submissions
|| history?.owner_context?.hidden_public_entries
)
const hasEntries = Boolean(history?.summary?.available) && entries.length > 0
return (
<section className="space-y-6">
<div className="flex flex-wrap items-end justify-between gap-4">
<div>
<div className="text-[11px] font-semibold uppercase tracking-[0.22em] text-slate-500">Worlds History</div>
<h2 className="mt-2 text-2xl font-semibold tracking-[-0.02em] text-white md:text-3xl">Recurring worlds, challenge outcomes, and standout editions</h2>
<p className="mt-3 max-w-3xl text-sm leading-relaxed text-slate-400">
This timeline pulls together edition-aware world participation, featured placements, finalists, winners, and linked challenge results into one creator-facing history layer.
</p>
</div>
</div>
<OwnerNote ownerContext={isOwner ? history?.owner_context : null} />
{hasEntries ? (
<>
<ProfileWorldHistorySummary history={history} />
{highlights.length > 0 ? (
<div className="space-y-3">
<div>
<div className="text-[11px] font-semibold uppercase tracking-[0.18em] text-slate-500">Highlights</div>
<p className="mt-2 text-sm text-slate-400">
The most recent and highest-signal world appearances surface first so recurring recognition reads like a creator recap, not just a raw list.
</p>
</div>
<ProfileWorldTimelineList entries={highlights} />
</div>
) : null}
{timelineEntries.length > 0 ? (
<div className="space-y-3">
<div>
<div className="text-[11px] font-semibold uppercase tracking-[0.18em] text-slate-500">Full Timeline</div>
<p className="mt-2 text-sm text-slate-400">
Every public world appearance, challenge-linked outcome, and edition-aware placement remains visible here in chronological order.
</p>
</div>
<ProfileWorldTimelineList entries={timelineEntries} />
</div>
) : null}
</>
) : (
<EmptyState isOwner={isOwner} hasPrivateContext={hasPrivateContext} />
)}
</section>
)
}