import { useState } from 'react' import { publishSeries } from '@/lib/articleMutations' import { useNostrAuth } from '@/hooks/useNostrAuth' import { nostrService } from '@/lib/nostr' import { t } from '@/lib/i18n' import type { SeriesDraft, SeriesAggregates } from './createSeriesModalTypes' export interface CreateSeriesModalController { draft: SeriesDraft setDraft: (draft: SeriesDraft) => void loading: boolean error: string | null canPublish: boolean handleClose: () => void handleSubmit: (e: React.FormEvent) => Promise } export function useCreateSeriesModalController(params: { authorPubkey: string onClose: () => void onSuccess: () => void isOpen: boolean }): CreateSeriesModalController { const { pubkey, isUnlocked } = useNostrAuth() const [draft, setDraft] = useState(createInitialDraft()) const [loading, setLoading] = useState(false) const [error, setError] = useState(null) const aggregates = computeAggregates({ pubkey, isUnlocked, authorPubkey: params.authorPubkey }) const handleClose = createHandleClose({ loading, setDraft, setError, onClose: params.onClose }) const handleSubmit = createHandleSubmit({ authorPubkey: params.authorPubkey, onClose: params.onClose, onSuccess: params.onSuccess, draft, aggregates, setDraft, setLoading, setError, }) return { draft, setDraft, loading, error, canPublish: aggregates.canPublish, handleClose, handleSubmit } } function createInitialDraft(): SeriesDraft { return { title: '', description: '', preview: '', coverUrl: '', category: 'science-fiction' } } function resetForm(params: { setDraft: (draft: SeriesDraft) => void; setError: (error: string | null) => void }): void { params.setDraft(createInitialDraft()) params.setError(null) } function computeAggregates(params: { pubkey: string | null; isUnlocked: boolean; authorPubkey: string }): SeriesAggregates { const privateKey = nostrService.getPrivateKey() const canPublish = params.pubkey === params.authorPubkey && params.isUnlocked && privateKey !== null return { canPublish, privateKey } } function getCanSubmitError(params: { canPublish: boolean; draft: SeriesDraft; privateKey: string | null }): string | null { if (!params.canPublish || !params.privateKey) { return t('series.create.error.notAuthor') } if (!params.draft.title.trim() || !params.draft.description.trim() || !params.draft.preview.trim()) { return t('series.create.error.missingFields') } return null } function createHandleClose(params: { loading: boolean setDraft: (draft: SeriesDraft) => void setError: (error: string | null) => void onClose: () => void }): () => void { return (): void => { if (params.loading) { return } resetForm({ setDraft: params.setDraft, setError: params.setError }) params.onClose() } } function createHandleSubmit(params: { authorPubkey: string onClose: () => void onSuccess: () => void draft: SeriesDraft aggregates: SeriesAggregates setDraft: (draft: SeriesDraft) => void setLoading: (loading: boolean) => void setError: (error: string | null) => void }): (e: React.FormEvent) => Promise { return async (e: React.FormEvent): Promise => submitSeriesForm(params, e) } async function submitSeriesForm( params: { authorPubkey: string onClose: () => void onSuccess: () => void draft: SeriesDraft aggregates: SeriesAggregates setDraft: (draft: SeriesDraft) => void setLoading: (loading: boolean) => void setError: (error: string | null) => void }, e: React.FormEvent ): Promise { e.preventDefault() const canSubmitError = getCanSubmitError({ canPublish: params.aggregates.canPublish, draft: params.draft, privateKey: params.aggregates.privateKey }) if (canSubmitError) { params.setError(canSubmitError) return } params.setLoading(true) params.setError(null) try { await publishSeries(buildPublishSeriesParams(params)) resetForm({ setDraft: params.setDraft, setError: params.setError }) params.onSuccess() params.onClose() } catch (submitError) { params.setError(submitError instanceof Error ? submitError.message : t('series.create.error.publishFailed')) } finally { params.setLoading(false) } } function buildPublishSeriesParams(params: { authorPubkey: string draft: SeriesDraft aggregates: SeriesAggregates }): { title: string description: string preview: string coverUrl?: string category: SeriesDraft['category'] authorPubkey: string authorPrivateKey: string } { return { title: params.draft.title, description: params.draft.description, preview: params.draft.preview, ...(params.draft.coverUrl ? { coverUrl: params.draft.coverUrl } : {}), category: params.draft.category, authorPubkey: params.authorPubkey, authorPrivateKey: params.aggregates.privateKey ?? '', } }