import React, { useState } from 'react' import NovaConfirmDialog from '../ui/NovaConfirmDialog' import ProfileCoverEditor from './ProfileCoverEditor' /** * ProfileHero * Cover banner + avatar + identity block + action buttons */ export default function ProfileHero({ user, profile, isOwner, viewerIsFollowing, followerCount, heroBgUrl, countryName }) { const [following, setFollowing] = useState(viewerIsFollowing) const [count, setCount] = useState(followerCount) const [loading, setLoading] = useState(false) const [hovering, setHovering] = useState(false) const [editorOpen, setEditorOpen] = useState(false) const [coverUrl, setCoverUrl] = useState(user?.cover_url || heroBgUrl || null) const [coverPosition, setCoverPosition] = useState(Number.isFinite(user?.cover_position) ? user.cover_position : 50) const [confirmOpen, setConfirmOpen] = useState(false) const [pendingFollowState, setPendingFollowState] = useState(null) const uname = user.username || user.name || 'Unknown' const displayName = user.name || uname const joinDate = user.created_at ? new Date(user.created_at).toLocaleDateString('en-US', { month: 'long', year: 'numeric' }) : null const bio = profile?.bio || profile?.about || '' const persistFollowState = async (nextState) => { if (loading) return setLoading(true) try { const res = await fetch(`/@${uname.toLowerCase()}/follow`, { method: 'POST', headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.content ?? '', 'Accept': 'application/json', }, }) if (res.ok) { const data = await res.json() setFollowing(data.following) setCount(data.follower_count) } } catch (_) {} setLoading(false) } const toggleFollow = async () => { const nextState = !following if (!nextState) { setPendingFollowState(nextState) setConfirmOpen(true) return } await persistFollowState(nextState) } const onConfirmUnfollow = async () => { if (pendingFollowState === null) return setConfirmOpen(false) await persistFollowState(pendingFollowState) setPendingFollowState(null) } const onCloseConfirm = () => { setConfirmOpen(false) setPendingFollowState(null) } return ( <>
{isOwner && (
)}
{`${uname}'s

{displayName}

@{uname}

{countryName && ( {profile?.country_code && ( {countryName} { e.target.style.display = 'none' }} /> )} {countryName} )} {joinDate && ( Joined {joinDate} )} {profile?.website && ( {(() => { try { const url = profile.website.startsWith('http') ? profile.website : `https://${profile.website}` return new URL(url).hostname } catch { return profile.website } })()} )}
{bio && (

{bio}

)}
{isOwner ? ( <> Edit Profile Studio ) : ( <> )}
setEditorOpen(false)} coverUrl={coverUrl} coverPosition={coverPosition} onCoverUpdated={(nextUrl, nextPosition) => { setCoverUrl(nextUrl) setCoverPosition(nextPosition) }} onCoverRemoved={() => { setCoverUrl(null) setCoverPosition(50) }} /> ) }