import { useCallback, useEffect, useState, type Dispatch, type FormEvent, type SetStateAction } from 'react' import { useRouter } from 'next/router' import { useAuthorPresentation } from '@/hooks/useAuthorPresentation' import { extractPresentationData } from '@/lib/presentationParsing' import { userConfirm } from '@/lib/userConfirm' import { t } from '@/lib/i18n' import type { Article } from '@/types/nostr' import type { AuthorPresentationDraft } from './types' import { validatePresentationDraft } from './validation' export interface AuthorPresentationState { draft: AuthorPresentationDraft setDraft: (next: AuthorPresentationDraft) => void validationError: string | null error: string | null loading: boolean handleSubmit: (e: FormEvent) => Promise deleting: boolean handleDelete: () => Promise success: boolean } export function useAuthorPresentationState( pubkey: string | null, existingAuthorName: string | undefined, existingPresentation: Article | null | undefined, ): AuthorPresentationState { const { loading, error, success, publishPresentation, deletePresentation } = useAuthorPresentation(pubkey) const router = useRouter() const [draft, setDraft] = useState(() => buildInitialDraft(existingPresentation, existingAuthorName)) const [validationError, setValidationError] = useState(null) const [deleting, setDeleting] = useState(false) useEffect(() => { syncAuthorNameIntoDraft({ existingAuthorName, draftAuthorName: draft.authorName, hasExistingPresentation: Boolean(existingPresentation), setDraft }) }, [existingAuthorName, existingPresentation, draft.authorName]) const handleSubmit = useCallback( async (e: FormEvent) => { e.preventDefault() await submitPresentationDraft({ draft, setValidationError, publishPresentation }) }, [draft, publishPresentation], ) const handleDelete = useCallback(async () => { await deletePresentationFlow({ existingPresentationId: existingPresentation?.id, deletePresentation, router, setDeleting, setValidationError, }) }, [existingPresentation, deletePresentation, router]) return { loading, error, success, draft, setDraft, validationError, handleSubmit, deleting, handleDelete } } function buildInitialDraft(existingPresentation: Article | null | undefined, existingAuthorName: string | undefined): AuthorPresentationDraft { if (existingPresentation) { const { presentation, contentDescription } = extractPresentationData(existingPresentation) const authorName = existingPresentation.title.replace(/^Présentation de /, '') ?? existingAuthorName ?? '' return { authorName, presentation, contentDescription, mainnetAddress: existingPresentation.mainnetAddress ?? '', ...(existingPresentation.bannerUrl ? { pictureUrl: existingPresentation.bannerUrl } : {}), } } return { authorName: existingAuthorName ?? '', presentation: '', contentDescription: '', mainnetAddress: '' } } function syncAuthorNameIntoDraft(params: { existingAuthorName: string | undefined draftAuthorName: string hasExistingPresentation: boolean setDraft: Dispatch> }): void { if (!params.existingAuthorName || params.hasExistingPresentation || params.existingAuthorName === params.draftAuthorName) { return } params.setDraft((prev) => ({ ...prev, authorName: params.existingAuthorName as string })) } async function submitPresentationDraft(params: { draft: AuthorPresentationDraft setValidationError: (value: string | null) => void publishPresentation: (draft: AuthorPresentationDraft) => Promise }): Promise { const validationError = validatePresentationDraft(params.draft) if (validationError) { params.setValidationError(validationError) return } params.setValidationError(null) await params.publishPresentation(params.draft) } async function deletePresentationFlow(params: { existingPresentationId: string | undefined deletePresentation: (articleId: string) => Promise router: ReturnType setDeleting: (value: boolean) => void setValidationError: (value: string | null) => void }): Promise { if (!params.existingPresentationId) { return } const confirmed = await userConfirm(t('presentation.delete.confirm')) if (!confirmed) { return } params.setDeleting(true) params.setValidationError(null) try { await params.deletePresentation(params.existingPresentationId) await params.router.push('/') } catch (e) { params.setValidationError(e instanceof Error ? e.message : t('presentation.delete.error')) } finally { params.setDeleting(false) } }