story-research-zapwall/components/ArticleEditorFormFieldsRight.tsx
2026-01-08 23:04:56 +01:00

119 lines
3.3 KiB
TypeScript

import React from 'react'
import type { ArticleDraft } from '@/lib/articlePublisher'
import type { MediaRef } from '@/types/nostr'
import { ArticleField } from './ArticleField'
import { MarkdownEditor } from './MarkdownEditor'
import { MarkdownEditorTwoColumns } from './MarkdownEditorTwoColumns'
import { t } from '@/lib/i18n'
interface ArticleFieldsRightProps {
draft: ArticleDraft
onDraftChange: (draft: ArticleDraft) => void
}
export function ArticleFieldsRight({ draft, onDraftChange }: ArticleFieldsRightProps): React.ReactElement {
return (
<div className="space-y-4">
<ContentEditorSection draft={draft} onDraftChange={onDraftChange} />
<ZapAmountField draft={draft} onDraftChange={onDraftChange} />
</div>
)
}
function ContentEditorSection({
draft,
onDraftChange,
}: {
draft: ArticleDraft
onDraftChange: (draft: ArticleDraft) => void
}): React.ReactElement {
const useTwoColumns = draft.seriesId !== undefined
return (
<div className="space-y-2">
<div className="text-sm font-semibold text-gray-800">{t('article.editor.content.label')}</div>
<ContentEditor draft={draft} onDraftChange={onDraftChange} useTwoColumns={useTwoColumns} />
<p className="text-xs text-gray-500">{t('article.editor.content.help')}</p>
</div>
)
}
function ContentEditor({
draft,
onDraftChange,
useTwoColumns,
}: {
draft: ArticleDraft
onDraftChange: (draft: ArticleDraft) => void
useTwoColumns: boolean
}): React.ReactElement {
const onMediaAdd = buildMediaAddHandler({ draft, onDraftChange })
const onBannerChange = buildBannerChangeHandler({ draft, onDraftChange })
const onContentChange = (value: string): void => onDraftChange({ ...draft, content: value })
if (useTwoColumns) {
return (
<MarkdownEditorTwoColumns
value={draft.content}
onChange={onContentChange}
{...(draft.pages ? { pages: draft.pages } : {})}
onPagesChange={(pages) => onDraftChange({ ...draft, pages })}
onMediaAdd={onMediaAdd}
onBannerChange={onBannerChange}
/>
)
}
return (
<MarkdownEditor
value={draft.content}
onChange={onContentChange}
onMediaAdd={onMediaAdd}
onBannerChange={onBannerChange}
/>
)
}
interface BuildMediaAddHandlerParams {
draft: ArticleDraft
onDraftChange: (draft: ArticleDraft) => void
}
function buildMediaAddHandler(params: BuildMediaAddHandlerParams): (media: MediaRef) => void {
return (media): void => {
const nextMedia = [...(params.draft.media ?? []), media]
params.onDraftChange({ ...params.draft, media: nextMedia })
}
}
interface BuildBannerChangeHandlerParams {
draft: ArticleDraft
onDraftChange: (draft: ArticleDraft) => void
}
function buildBannerChangeHandler(params: BuildBannerChangeHandlerParams): (url: string) => void {
return (url): void => {
params.onDraftChange({ ...params.draft, bannerUrl: url })
}
}
function ZapAmountField({
draft,
onDraftChange,
}: {
draft: ArticleDraft
onDraftChange: (draft: ArticleDraft) => void
}): React.ReactElement {
return (
<ArticleField
id="zapAmount"
label={t('article.editor.sponsoring.label')}
value={draft.zapAmount}
onChange={(value) => onDraftChange({ ...draft, zapAmount: value as number })}
required
type="number"
min={1}
helpText={t('article.editor.sponsoring.help')}
/>
)
}