import React from 'react'
import type { ArticleDraft } from '@/lib/articlePublisher'
import type { ArticleCategory } from '@/types/nostr'
import { ArticleField } from './ArticleField'
import { ArticleFormButtons } from './ArticleFormButtons'
import { CategorySelect } from './CategorySelect'
import { MarkdownEditor } from './MarkdownEditor'
import { MarkdownEditorTwoColumns } from './MarkdownEditorTwoColumns'
import type { MediaRef } from '@/types/nostr'
import { t } from '@/lib/i18n'
interface ArticleEditorFormProps {
draft: ArticleDraft
onDraftChange: (draft: ArticleDraft) => void
onSubmit: (e: React.FormEvent) => void
loading: boolean
error: string | null
onCancel?: () => void
seriesOptions?: { id: string; title: string }[] | undefined
onSelectSeries?: ((seriesId: string | undefined) => void) | undefined
}
function CategoryField({
value,
onChange,
}: {
value: ArticleDraft['category']
onChange: (value: import('@/types/nostr').ArticleCategory | undefined) => void
}): React.ReactElement {
return (
)
}
function ErrorAlert({ error }: { error: string | null }): React.ReactElement | null {
if (!error) {
return null
}
return (
)
}
function buildCategoryChangeHandler(
draft: ArticleDraft,
onDraftChange: (draft: ArticleDraft) => void
): (value: ArticleCategory | undefined) => void {
return (value) => {
if (value === 'science-fiction' || value === 'scientific-research' || value === undefined) {
const nextDraft: ArticleDraft = { ...draft }
if (value) {
nextDraft.category = value
} else {
delete (nextDraft as { category?: ArticleDraft['category'] }).category
}
onDraftChange(nextDraft)
}
}
}
const ArticleFieldsLeft = ({
draft,
onDraftChange,
seriesOptions,
onSelectSeries,
}: {
draft: ArticleDraft
onDraftChange: (draft: ArticleDraft) => void
seriesOptions?: { id: string; title: string }[] | undefined
onSelectSeries?: ((seriesId: string | undefined) => void) | undefined
}): React.ReactElement => (
)
function ArticleTitleField({ draft, onDraftChange }: { draft: ArticleDraft; onDraftChange: (draft: ArticleDraft) => void }): React.ReactElement {
return (
onDraftChange({ ...draft, title: value as string })}
required
placeholder={t('article.editor.title.placeholder')}
/>
)
}
function ArticlePreviewField({
draft,
onDraftChange,
}: {
draft: ArticleDraft
onDraftChange: (draft: ArticleDraft) => void
}): React.ReactElement {
return (
onDraftChange({ ...draft, preview: value as string })}
required
type="textarea"
rows={4}
placeholder={t('article.editor.preview.placeholder')}
helpText={t('article.editor.preview.help')}
/>
)
}
function SeriesSelect({
draft,
onDraftChange,
seriesOptions,
onSelectSeries,
}: {
draft: ArticleDraft
onDraftChange: (draft: ArticleDraft) => void
seriesOptions: { id: string; title: string }[]
onSelectSeries?: ((seriesId: string | undefined) => void) | undefined
}): React.ReactElement {
const handleChange = buildSeriesChangeHandler(draft, onDraftChange, onSelectSeries)
return (
)
}
function buildSeriesChangeHandler(
draft: ArticleDraft,
onDraftChange: (draft: ArticleDraft) => void,
onSelectSeries?: ((seriesId: string | undefined) => void) | undefined
): (e: React.ChangeEvent) => void {
return (e: React.ChangeEvent): void => {
const value = e.target.value || undefined
const nextDraft = { ...draft }
if (value) {
nextDraft.seriesId = value
} else {
delete (nextDraft as { seriesId?: string }).seriesId
}
onDraftChange(nextDraft)
onSelectSeries?.(value)
}
}
const ArticleFieldsRight = ({
draft,
onDraftChange,
}: {
draft: ArticleDraft
onDraftChange: (draft: ArticleDraft) => void
}): React.ReactElement => {
// Use two-column editor with pages for series publications
const useTwoColumns = draft.seriesId !== undefined
return (
{t('article.editor.content.label')}
{useTwoColumns ? (
onDraftChange({ ...draft, content: value })}
pages={draft.pages}
onPagesChange={(pages) => onDraftChange({ ...draft, pages })}
onMediaAdd={(media: MediaRef) => {
const nextMedia = [...(draft.media ?? []), media]
onDraftChange({ ...draft, media: nextMedia })
}}
onBannerChange={(url: string) => {
onDraftChange({ ...draft, bannerUrl: url })
}}
/>
) : (
onDraftChange({ ...draft, content: value })}
onMediaAdd={(media: MediaRef) => {
const nextMedia = [...(draft.media ?? []), media]
onDraftChange({ ...draft, media: nextMedia })
}}
onBannerChange={(url: string) => {
onDraftChange({ ...draft, bannerUrl: url })
}}
/>
)}
{t('article.editor.content.help')}
onDraftChange({ ...draft, zapAmount: value as number })}
required
type="number"
min={1}
helpText={t('article.editor.sponsoring.help')}
/>
)
}
export function ArticleEditorForm({
draft,
onDraftChange,
onSubmit,
loading,
error,
onCancel,
seriesOptions,
onSelectSeries,
}: ArticleEditorFormProps): React.ReactElement {
return (
)
}