import React from 'react' import CreatorJourneySection from '../CreatorJourneySection' const SOCIAL_ICONS = { twitter: { icon: 'fa-brands fa-x-twitter', label: 'X / Twitter', hoverClass: 'hover:border-slate-300/30 hover:text-slate-100 hover:bg-white/[0.08]' }, deviantart: { icon: 'fa-brands fa-deviantart', label: 'DeviantArt', hoverClass: 'hover:border-green-400/35 hover:text-green-300 hover:bg-green-900/20' }, instagram: { icon: 'fa-brands fa-instagram', label: 'Instagram', hoverClass: 'hover:border-pink-400/35 hover:text-pink-300 hover:bg-pink-900/20' }, behance: { icon: 'fa-brands fa-behance', label: 'Behance', hoverClass: 'hover:border-blue-400/35 hover:text-blue-300 hover:bg-blue-900/20' }, artstation: { icon: 'fa-solid fa-palette', label: 'ArtStation', hoverClass: 'hover:border-orange-400/35 hover:text-orange-300 hover:bg-orange-900/20' }, youtube: { icon: 'fa-brands fa-youtube', label: 'YouTube', hoverClass: 'hover:border-red-400/35 hover:text-red-300 hover:bg-red-900/20' }, website: { icon: 'fa-solid fa-link', label: 'Website', hoverClass: 'hover:border-sky-400/35 hover:text-sky-200 hover:bg-sky-900/20' }, } const CATEGORY_ICONS = { animals: 'fa-solid fa-paw', birds: 'fa-solid fa-dove', flowers: 'fa-solid fa-seedling', fruit: 'fa-solid fa-apple-whole', 'sci-fi': 'fa-solid fa-rocket', scifi: 'fa-solid fa-rocket', fantasy: 'fa-solid fa-dragon', nature: 'fa-solid fa-leaf', landscape: 'fa-solid fa-mountain', abstract: 'fa-solid fa-shapes', architecture: 'fa-solid fa-building', people: 'fa-solid fa-person', portrait: 'fa-solid fa-face-smile', cars: 'fa-solid fa-car', space: 'fa-solid fa-star', games: 'fa-solid fa-gamepad', food: 'fa-solid fa-utensils', travel: 'fa-solid fa-plane', sports: 'fa-solid fa-football', ocean: 'fa-solid fa-water', underwater: 'fa-solid fa-fish', insects: 'fa-solid fa-bug', reptiles: 'fa-solid fa-dragon', cats: 'fa-solid fa-cat', dogs: 'fa-solid fa-dog', } const CONTENT_TYPE_ICONS = { photography: 'fa-solid fa-camera', wallpapers: 'fa-solid fa-desktop', 'digital art': 'fa-solid fa-wand-magic-sparkles', illustration: 'fa-solid fa-pen-nib', '3d': 'fa-solid fa-cube', vector: 'fa-solid fa-bezier-curve', fractal: 'fa-solid fa-infinity', gif: 'fa-solid fa-film', drawing: 'fa-solid fa-pencil', painting: 'fa-solid fa-paintbrush', photo: 'fa-solid fa-camera', } function getCategoryIcon(label) { const key = String(label || '').toLowerCase().trim() return CATEGORY_ICONS[key] ?? null } function getContentTypeIcon(label) { const key = String(label || '').toLowerCase().trim() return CONTENT_TYPE_ICONS[key] ?? null } function formatNumber(value) { return Number(value ?? 0).toLocaleString() } function formatRelativeDate(value) { if (!value) return null try { const date = new Date(value) if (Number.isNaN(date.getTime())) return null const now = new Date() const diffSeconds = Math.round((date.getTime() - now.getTime()) / 1000) const absSeconds = Math.abs(diffSeconds) const formatter = new Intl.RelativeTimeFormat('en', { numeric: 'auto' }) if (absSeconds < 3600) { return formatter.format(Math.round(diffSeconds / 60), 'minute') } if (absSeconds < 86400) { return formatter.format(Math.round(diffSeconds / 3600), 'hour') } if (absSeconds < 604800) { return formatter.format(Math.round(diffSeconds / 86400), 'day') } if (absSeconds < 2629800) { return formatter.format(Math.round(diffSeconds / 604800), 'week') } return formatter.format(Math.round(diffSeconds / 2629800), 'month') } catch { return null } } function formatShortDate(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 truncateText(value, maxLength = 140) { const text = String(value ?? '').trim() if (!text) return '' if (text.length <= maxLength) return text 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() artworks.forEach((artwork) => { const categoryKey = String(artwork?.category_slug || artwork?.category || '').trim().toLowerCase() const categoryLabel = String(artwork?.category || '').trim() const contentTypeKey = String(artwork?.content_type_slug || artwork?.content_type || '').trim().toLowerCase() const contentTypeLabel = String(artwork?.content_type || '').trim() if (categoryKey && categoryLabel) { categoryMap.set(categoryKey, { label: categoryLabel, count: (categoryMap.get(categoryKey)?.count ?? 0) + 1, }) } if (contentTypeKey && contentTypeLabel) { contentTypeMap.set(contentTypeKey, { label: contentTypeLabel, count: (contentTypeMap.get(contentTypeKey)?.count ?? 0) + 1, }) } }) const toSortedList = (source) => Array.from(source.values()) .sort((left, right) => right.count - left.count || left.label.localeCompare(right.label)) .slice(0, 5) return { categories: toSortedList(categoryMap), contentTypes: toSortedList(contentTypeMap), } } function InfoRow({ icon, label, children }) { return (
{label}
{children}
) } function StatCard({ icon, label, value, tone = 'sky' }) { const tones = { sky: { icon: 'text-sky-300 bg-sky-400/10 border-sky-300/20', bar: 'from-sky-400/60 via-sky-400/20 to-transparent', glow: 'shadow-[0_0_28px_rgba(56,189,248,0.10)]' }, amber: { icon: 'text-amber-200 bg-amber-300/10 border-amber-300/20', bar: 'from-amber-400/60 via-amber-400/20 to-transparent', glow: 'shadow-[0_0_28px_rgba(251,191,36,0.10)]' }, emerald: { icon: 'text-emerald-200 bg-emerald-400/10 border-emerald-300/20', bar: 'from-emerald-400/60 via-emerald-400/20 to-transparent', glow: 'shadow-[0_0_28px_rgba(52,211,153,0.10)]' }, violet: { icon: 'text-violet-200 bg-violet-400/10 border-violet-300/20', bar: 'from-violet-400/60 via-violet-400/20 to-transparent', glow: 'shadow-[0_0_28px_rgba(167,139,250,0.10)]' }, } const t = tones[tone] || tones.sky return (
{label}
{value}
) } function SectionCard({ icon, eyebrow, title, children, className = '' }) { return (

{eyebrow}

{title}

{children}
) } /** * 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, groupContributionHistory, journey }) { const uname = user.username || user.name const displayName = user.name || uname const about = profile?.about const website = profile?.website const joinDate = user.created_at ? new Date(user.created_at).toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' }) : null const lastVisit = user.last_visit_at ? (() => { try { const d = new Date(user.last_visit_at) return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) } catch { return null } })() : null const genderMap = { M: 'Male', F: 'Female', X: 'Non-binary / N/A' } const genderLabel = genderMap[profile?.gender?.toUpperCase()] ?? null const birthDate = profile?.birthdate ? (() => { try { return new Date(profile.birthdate).toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' }) } catch { return null } })() : null const lastSeenRelative = formatRelativeDate(user.last_visit_at) const socialEntries = socialLinks ? Object.entries(socialLinks).filter(([, link]) => link?.url) : [] const followers = recentFollowers ?? [] 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' }, { icon: 'fa-images', label: 'Uploads', value: formatNumber(stats?.uploads_count ?? 0), tone: 'violet' }, { icon: 'fa-eye', label: 'Profile views', value: formatNumber(stats?.profile_views_count ?? 0), tone: 'emerald' }, { icon: 'fa-trophy', label: 'Weekly rank', value: leaderboardRank?.rank ? `#${formatNumber(leaderboardRank.rank)}` : 'Unranked', tone: 'amber' }, ] return (
{summaryCards.map((card) => ( ))}
{about ? (

{about}

) : (

This creator has not written a public bio yet.

)}
{displayName && displayName !== uname ? ( {displayName} ) : null} @{uname} {genderLabel ? {genderLabel} : null} {countryName ? ( {profile?.country_code ? ( {countryName} { e.target.style.display = 'none' }} /> ) : null} {countryName} ) : null} {website ? ( {(() => { try { const url = website.startsWith('http') ? website : `https://${website}` return new URL(url).hostname } catch { return website } })()} ) : null} {birthDate ? {birthDate} : null} {joinDate ? {joinDate} : null} {lastVisit ? {lastSeenRelative ? `${lastSeenRelative} · ${lastVisit}` : lastVisit} : null}
{contributionHistory.length > 0 ? (
{contributionHistory.map((entry) => (
{entry.group?.avatar_url ? ( {entry.group?.name} ) : (
)}
{entry.group?.name}
{entry.role ? {String(entry.role).replaceAll('_', ' ')} : null} {entry.trusted_indicator ? Trusted : null}
{entry.group?.headline ?

{truncateText(entry.group.headline, 100)}

: null} {entry.summary ?

{entry.summary}

: null}
{Number(entry.counts?.credited_artworks || 0).toLocaleString()} credited artworks {Number(entry.counts?.releases || 0).toLocaleString()} releases {Number(entry.counts?.projects || 0).toLocaleString()} projects {entry.joined_at ? Joined {formatContributionDate(entry.joined_at)} : null}
{Array.isArray(entry.role_labels) && entry.role_labels.length > 0 ? (
{entry.role_labels.map((label) => ( {label} ))}
) : null} {Array.isArray(entry.recent_release_titles) && entry.recent_release_titles.length > 0 ? (
Recent releases: {entry.recent_release_titles.join(' • ')}
) : null}
))}
) : null} {followers.length > 0 ? (
{followers.slice(0, 6).map((follower) => ( {follower.username}
{follower.uname || follower.username}
@{follower.username}
))}
) : null} {recentAchievements.length > 0 ? (
{recentAchievements.slice(0, 4).map((achievement) => (
{achievement.name}
{achievement.description ? (
{achievement.description}
) : null}
{achievement.unlocked_at ? ( {formatShortDate(achievement.unlocked_at) || 'Unlocked'} ) : null} +{formatNumber(achievement.xp_reward ?? 0)} XP
))}
) : null} {stories.length > 0 || comments.length > 0 ? (
{stories.length > 0 ? (
Latest story
{formatShortDate(stories[0]?.published_at) || 'Published'}
{stories[0].title} {stories[0].excerpt ? (

{truncateText(stories[0].excerpt, 180)}

) : null}
{stories[0].reading_time ? ( {stories[0].reading_time} min read ) : null} {formatNumber(stories[0].views ?? 0)} views {formatNumber(stories[0].comments_count ?? 0)} comments
) : null} {comments.length > 0 ? (
Latest guestbook comment
{formatRelativeDate(comments[0]?.created_at) || 'Recently'}
{comments[0].author_name} { e.target.src = '/images/avatar_default.webp' }} />
{comments[0].author_name}

{truncateText(comments[0].body, 180)}

) : null}
) : null}
Creator level
Lv {formatNumber(user?.level ?? 1)}
{user?.rank || 'Creator'}
XP
{formatNumber(user?.xp ?? 0)}
Weekly rank
{leaderboardRank?.rank ? `#${formatNumber(leaderboardRank.rank)}` : 'Not ranked'}
{leaderboardRank?.score ?
Score {formatNumber(leaderboardRank.score)}
: null}
Community size
{formatNumber(followerCount)}
Followers
{formatNumber(stats?.uploads_count ?? 0)} {formatNumber(stats?.artwork_views_received_count ?? 0)} {formatNumber(stats?.downloads_received_count ?? 0)} {formatNumber(stats?.favourites_received_count ?? 0)} {formatNumber(stats?.comments_received_count ?? 0)}
{interestGroups.categories.length > 0 || interestGroups.contentTypes.length > 0 ? (
{interestGroups.categories.length > 0 ? (
Top categories
{interestGroups.categories.map((category) => { const catIcon = getCategoryIcon(category.label) return ( {catIcon ? : null} {category.label} {formatNumber(category.count)} ) })}
) : null} {interestGroups.contentTypes.length > 0 ? (
Preferred formats
{interestGroups.contentTypes.map((contentType) => { const ctIcon = getContentTypeIcon(contentType.label) return ( {ctIcon ? : null} {contentType.label} {formatNumber(contentType.count)} ) })}
) : null}
) : null} {socialEntries.length > 0 ? (
{socialEntries.map(([platform, link]) => { const si = SOCIAL_ICONS[platform] ?? { icon: 'fa-solid fa-link', label: platform } const href = link.url.startsWith('http') ? link.url : `https://${link.url}` return ( {si.label} ) })}
) : null}
) }