86 lines
3.1 KiB
TypeScript
86 lines
3.1 KiB
TypeScript
import Link from 'next/link'
|
|
import Image from 'next/image'
|
|
import { useNostrAuth } from '@/hooks/useNostrAuth'
|
|
import { useAuthorPresentation } from '@/hooks/useAuthorPresentation'
|
|
import { useEffect, useState } from 'react'
|
|
import { Button } from './ui'
|
|
import { t } from '@/lib/i18n'
|
|
import type { Article } from '@/types/nostr'
|
|
|
|
function CreateAuthorPageLink(): React.ReactElement {
|
|
return (
|
|
<Link href="/presentation">
|
|
<Button variant="primary" size="small">
|
|
{t('nav.createAuthorPage')}
|
|
</Button>
|
|
</Link>
|
|
)
|
|
}
|
|
|
|
function AuthorProfileLink({ presentation, profile }: { presentation: Article; profile: { name?: string; picture?: string } | null }): React.ReactElement {
|
|
// Extract author name from presentation title or profile
|
|
// Title format: "Présentation de <name>" or just use profile name
|
|
let authorName = presentation.title.replace(/^Présentation de /, '').trim()
|
|
if (!authorName || authorName === 'Présentation') {
|
|
authorName = profile?.name ?? t('common.author')
|
|
}
|
|
|
|
// Extract picture from presentation (bannerUrl or from JSON metadata) or profile
|
|
const picture = presentation.bannerUrl ?? profile?.picture
|
|
|
|
return (
|
|
<Link
|
|
href={`/author/${presentation.pubkey}`}
|
|
className="flex items-center gap-2 px-3 py-2 bg-cyber-dark/50 hover:bg-cyber-dark border border-neon-cyan/20 hover:border-neon-cyan/40 rounded-lg transition-all"
|
|
>
|
|
{picture ? (
|
|
<div className="relative w-8 h-8 rounded-full overflow-hidden border border-neon-cyan/30 flex-shrink-0">
|
|
<Image
|
|
src={picture}
|
|
alt={authorName}
|
|
fill
|
|
className="object-cover"
|
|
sizes="32px"
|
|
/>
|
|
</div>
|
|
) : (
|
|
<div className="w-8 h-8 rounded-full bg-cyber-light border border-neon-cyan/30 flex items-center justify-center flex-shrink-0">
|
|
<span className="text-xs text-neon-cyan font-medium">{authorName.charAt(0).toUpperCase()}</span>
|
|
</div>
|
|
)}
|
|
<span className="text-sm text-neon-cyan font-medium truncate max-w-[120px]">{authorName}</span>
|
|
</Link>
|
|
)
|
|
}
|
|
|
|
export function ConditionalPublishButton(): React.ReactElement {
|
|
const { connected, pubkey, profile } = useNostrAuth()
|
|
const { checkPresentationExists } = useAuthorPresentation(pubkey ?? null)
|
|
const [presentation, setPresentation] = useState<Article | null>(null)
|
|
|
|
useEffect(() => {
|
|
const check = async (): Promise<void> => {
|
|
if (!connected || !pubkey) {
|
|
setPresentation(null)
|
|
return
|
|
}
|
|
// Check for presentation asynchronously, but don't show loading state
|
|
const pres = await checkPresentationExists()
|
|
setPresentation(pres)
|
|
}
|
|
void check()
|
|
}, [connected, pubkey, checkPresentationExists])
|
|
|
|
if (!connected || !pubkey) {
|
|
return <CreateAuthorPageLink />
|
|
}
|
|
|
|
// If presentation exists, show author profile link with image/fallback
|
|
if (presentation) {
|
|
return <AuthorProfileLink presentation={presentation} profile={profile} />
|
|
}
|
|
|
|
// Otherwise, show create author page button immediately (no loading state)
|
|
return <CreateAuthorPageLink />
|
|
}
|