Commit workspace changes

This commit is contained in:
2026-04-05 19:42:33 +02:00
parent 148a3bbe43
commit 08ad757bcb
312 changed files with 35149 additions and 399 deletions

View File

@@ -69,6 +69,19 @@ function truncateText(value, maxLength = 140) {
return `${text.slice(0, maxLength).trimEnd()}...`
}
function formatContributionDate(value) {
if (!value) return null
try {
const date = new Date(value)
if (Number.isNaN(date.getTime())) return null
return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })
} catch {
return null
}
}
function buildInterestGroups(artworks = []) {
const categoryMap = new Map()
const contentTypeMap = new Map()
@@ -156,7 +169,7 @@ function SectionCard({ icon, eyebrow, title, children, className = '' }) {
* TabAbout
* Bio, social links, metadata - replaces old sidebar profile card.
*/
export default function TabAbout({ user, profile, stats, achievements, artworks, creatorStories, profileComments, socialLinks, countryName, followerCount, recentFollowers, leaderboardRank }) {
export default function TabAbout({ user, profile, stats, achievements, artworks, creatorStories, profileComments, socialLinks, countryName, followerCount, recentFollowers, leaderboardRank, groupContributionHistory }) {
const uname = user.username || user.name
const displayName = user.name || uname
const about = profile?.about
@@ -193,6 +206,7 @@ export default function TabAbout({ user, profile, stats, achievements, artworks,
const recentAchievements = Array.isArray(achievements?.recent) ? achievements.recent : []
const stories = Array.isArray(creatorStories) ? creatorStories : []
const comments = Array.isArray(profileComments) ? profileComments : []
const contributionHistory = Array.isArray(groupContributionHistory) ? groupContributionHistory : []
const interestGroups = buildInterestGroups(Array.isArray(artworks) ? artworks : [])
const summaryCards = [
{ icon: 'fa-user-group', label: 'Followers', value: formatNumber(followerCount), tone: 'sky' },
@@ -271,6 +285,59 @@ export default function TabAbout({ user, profile, stats, achievements, artworks,
</div>
</SectionCard>
{contributionHistory.length > 0 ? (
<SectionCard icon="fa-solid fa-people-group" eyebrow="Collaborative work" title="Group contribution history">
<div className="grid gap-4">
{contributionHistory.map((entry) => (
<a
key={entry.group?.slug}
href={entry.group?.profile_url || '#'}
className="rounded-[24px] border border-white/8 bg-white/[0.03] p-4 transition-colors hover:border-white/14 hover:bg-white/[0.06]"
>
<div className="flex items-start gap-3">
{entry.group?.avatar_url ? (
<img src={entry.group.avatar_url} alt={entry.group?.name} className="h-12 w-12 rounded-2xl object-cover ring-1 ring-white/10" />
) : (
<div className="flex h-12 w-12 items-center justify-center rounded-2xl border border-white/10 bg-white/[0.04] text-slate-400">
<i className="fa-solid fa-people-group" />
</div>
)}
<div className="min-w-0 flex-1">
<div className="flex flex-wrap items-center gap-2">
<div className="truncate text-sm font-semibold text-white">{entry.group?.name}</div>
{entry.role ? <span className="rounded-full border border-white/10 bg-black/20 px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.16em] text-slate-300">{String(entry.role).replaceAll('_', ' ')}</span> : null}
{entry.trusted_indicator ? <span className="rounded-full border border-emerald-300/20 bg-emerald-300/10 px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.16em] text-emerald-100">Trusted</span> : null}
</div>
{entry.group?.headline ? <p className="mt-1 text-sm text-slate-400">{truncateText(entry.group.headline, 100)}</p> : null}
{entry.summary ? <p className="mt-3 text-sm text-slate-300">{entry.summary}</p> : null}
<div className="mt-3 flex flex-wrap gap-3 text-xs text-slate-500">
<span>{Number(entry.counts?.credited_artworks || 0).toLocaleString()} credited artworks</span>
<span>{Number(entry.counts?.releases || 0).toLocaleString()} releases</span>
<span>{Number(entry.counts?.projects || 0).toLocaleString()} projects</span>
{entry.joined_at ? <span>Joined {formatContributionDate(entry.joined_at)}</span> : null}
</div>
{Array.isArray(entry.role_labels) && entry.role_labels.length > 0 ? (
<div className="mt-3 flex flex-wrap gap-2">
{entry.role_labels.map((label) => (
<span key={`${entry.group?.slug}-${label}`} className="rounded-full border border-sky-300/15 bg-sky-400/10 px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.16em] text-sky-100">
{label}
</span>
))}
</div>
) : null}
{Array.isArray(entry.recent_release_titles) && entry.recent_release_titles.length > 0 ? (
<div className="mt-3 text-xs text-slate-400">
Recent releases: {entry.recent_release_titles.join(' • ')}
</div>
) : null}
</div>
</div>
</a>
))}
</div>
</SectionCard>
) : null}
{followers.length > 0 ? (
<SectionCard icon="fa-solid fa-user-group" eyebrow="Community" title="Recent followers">
<div className="grid gap-3 sm:grid-cols-2">