このコミットが含まれているのは:
2026-07-15 22:26:58 +09:00
コミット 07ce19e32d
8個のファイルの変更784行の追加264行の削除
+116 -117
ファイルの表示
@@ -1,4 +1,4 @@
import { useState } from 'react'
import { useEffect, useState } from 'react'
import PostOriginalCreatedTimeField from '@/components/PostOriginalCreatedTimeField'
import FieldError from '@/components/common/FieldError'
@@ -9,10 +9,9 @@ import { Button } from '@/components/ui/button'
import { useDialogue } from '@/lib/dialogues/useDialogue'
import { inputClass } from '@/lib/utils'
import type { FC } from 'react'
import type { Dispatch, FC, SetStateAction } from 'react'
import type { PostImportResetSnapshot,
PostImportRow } from '@/lib/postImportSession'
import type { PostImportRow } from '@/lib/postImportSession'
type Draft = {
url: string
@@ -25,15 +24,11 @@ type Draft = {
parentPostIds: string }
type Props = {
row: PostImportRow
messageRow?: PostImportRow | null
saving: boolean
onCancel: () => void
onSave: (
payload: { draft: Draft
resetRequested: boolean
resetSnapshot: PostImportResetSnapshot },
) => Promise<boolean> }
row: PostImportRow
messageRow?: PostImportRow | null
saving: boolean
onDraftChange: Dispatch<SetStateAction<Draft | null>>
onResetRequestedChange: Dispatch<SetStateAction<boolean>> }
const buildDraft = (row: PostImportRow): Draft => ({
url: row.url,
@@ -70,13 +65,24 @@ const sameDraft = (left: Draft, right: Draft): boolean =>
const PostImportRowForm: FC<Props> = (
{ row, messageRow, saving, onCancel, onSave },
{ row,
messageRow,
saving,
onDraftChange,
onResetRequestedChange },
) => {
const dialogue = useDialogue ()
const [draft, setDraft] = useState<Draft> (() => buildDraft (row))
const [resetRequested, setResetRequested] = useState (false)
useEffect (() => {
const nextDraft = buildDraft (row)
setDraft (nextDraft)
setResetRequested (false)
onDraftChange (nextDraft)
onResetRequestedChange (false)
}, [onDraftChange, onResetRequestedChange, row])
const displayRow = messageRow ?? row
const resetDraft = buildResetDraft (row)
const resetDisabled = saving || sameDraft (draft, resetDraft)
@@ -85,7 +91,11 @@ const PostImportRowForm: FC<Props> = (
key: Key,
value: Draft[Key],
) => {
setDraft (current => ({ ...current, [key]: value }))
setDraft (current => {
const next = { ...current, [key]: value }
onDraftChange (next)
return next
})
}
const reset = async () => {
@@ -103,116 +113,103 @@ const PostImportRowForm: FC<Props> = (
setDraft (resetDraft)
setResetRequested (true)
}
const save = async () => {
if (await onSave ({
draft,
resetRequested,
resetSnapshot: row.resetSnapshot }))
onCancel ()
onDraftChange (resetDraft)
onResetRequestedChange (true)
}
return (
<>
<div className="min-h-0 flex-1 overflow-y-auto overscroll-contain px-6 pb-6">
<div className="grid gap-6 md:grid-cols-[7rem_minmax(0,1fr)]">
<div className="space-y-3">
<ThumbnailPreview
url={draft.thumbnailBase}
className="h-28 w-28"/>
</div>
<div className="space-y-4">
<p className="text-sm text-muted-foreground">
稿 {row.sourceRow}
</p>
<div className="space-y-4">
<PostImportTextField
label="URL"
value={draft.url}
warnings={displayRow.fieldWarnings.url}
errors={groupedMessages (
displayRow.validationErrors.url,
displayRow.importErrors?.url)}
onChange={value => update ('url', value)}/>
<PostImportTextField
label="タイトル"
value={draft.title}
warnings={displayRow.fieldWarnings.title}
errors={groupedMessages (
displayRow.validationErrors.title,
displayRow.importErrors?.title)}
onChange={value => update ('title', value)}/>
<PostImportTextField
label="サムネール基底 URL"
value={draft.thumbnailBase}
warnings={displayRow.fieldWarnings.thumbnailBase}
errors={groupedMessages (
displayRow.validationErrors.thumbnailBase,
displayRow.importErrors?.thumbnailBase)}
onChange={value => update ('thumbnailBase', value)}/>
<PostOriginalCreatedTimeField
originalCreatedFrom={draft.originalCreatedFrom || null}
setOriginalCreatedFrom={value => update ('originalCreatedFrom', value ?? '')}
originalCreatedBefore={draft.originalCreatedBefore || null}
setOriginalCreatedBefore={value => update ('originalCreatedBefore', value ?? '')}
errors={groupedMessages (
displayRow.validationErrors.originalCreatedAt,
displayRow.validationErrors.originalCreatedFrom,
displayRow.validationErrors.originalCreatedBefore,
displayRow.importErrors?.originalCreatedAt,
displayRow.importErrors?.originalCreatedFrom,
displayRow.importErrors?.originalCreatedBefore)}/>
<PostImportTextField
label="動画時間"
value={draft.duration}
errors={groupedMessages (
displayRow.validationErrors.duration,
displayRow.validationErrors.videoMs,
displayRow.importErrors?.duration,
displayRow.importErrors?.videoMs)}
onChange={value => update ('duration', value)}/>
<PostImportAreaField
label="タグ"
value={draft.tags}
warnings={displayRow.fieldWarnings.tags}
errors={groupedMessages (
displayRow.validationErrors.tags,
displayRow.importErrors?.tags)}
onChange={value => update ('tags', value)}/>
<PostImportTextField
label="親投稿"
value={draft.parentPostIds}
errors={groupedMessages (
displayRow.validationErrors.parentPostIds,
displayRow.importErrors?.parentPostIds)}
onChange={value => update ('parentPostIds', value)}/>
<FieldWarning messages={displayRow.baseWarnings}/>
<FieldError messages={displayRow.validationErrors.base}/>
<FieldError messages={displayRow.importErrors?.base}/>
<div className="grid gap-6 md:grid-cols-[7rem_minmax(0,1fr)]">
<div className="space-y-3">
<ThumbnailPreview
url={draft.thumbnailBase}
className="h-28 w-28"/>
</div>
<div className="space-y-4">
<PostImportTextField
label="URL"
value={draft.url}
warnings={displayRow.fieldWarnings.url}
errors={groupedMessages (
displayRow.validationErrors.url,
displayRow.importErrors?.url)}
onChange={value => update ('url', value)}/>
<PostImportTextField
label="タイトル"
value={draft.title}
warnings={displayRow.fieldWarnings.title}
errors={groupedMessages (
displayRow.validationErrors.title,
displayRow.importErrors?.title)}
onChange={value => update ('title', value)}/>
<PostImportTextField
label="サムネール基底 URL"
value={draft.thumbnailBase}
warnings={displayRow.fieldWarnings.thumbnailBase}
errors={groupedMessages (
displayRow.validationErrors.thumbnailBase,
displayRow.importErrors?.thumbnailBase)}
onChange={value => update ('thumbnailBase', value)}/>
<PostOriginalCreatedTimeField
originalCreatedFrom={draft.originalCreatedFrom || null}
setOriginalCreatedFrom={value => update ('originalCreatedFrom', value ?? '')}
originalCreatedBefore={draft.originalCreatedBefore || null}
setOriginalCreatedBefore={value => update ('originalCreatedBefore', value ?? '')}
errors={groupedMessages (
displayRow.validationErrors.originalCreatedAt,
displayRow.validationErrors.originalCreatedFrom,
displayRow.validationErrors.originalCreatedBefore,
displayRow.importErrors?.originalCreatedAt,
displayRow.importErrors?.originalCreatedFrom,
displayRow.importErrors?.originalCreatedBefore)}/>
<PostImportTextField
label="動画時間"
value={draft.duration}
errors={groupedMessages (
displayRow.validationErrors.duration,
displayRow.validationErrors.videoMs,
displayRow.importErrors?.duration,
displayRow.importErrors?.videoMs)}
onChange={value => update ('duration', value)}/>
<PostImportAreaField
label="タグ"
value={draft.tags}
warnings={displayRow.fieldWarnings.tags}
errors={groupedMessages (
displayRow.validationErrors.tags,
displayRow.importErrors?.tags)}
onChange={value => update ('tags', value)}/>
<PostImportTextField
label="親投稿"
value={draft.parentPostIds}
errors={groupedMessages (
displayRow.validationErrors.parentPostIds,
displayRow.importErrors?.parentPostIds)}
onChange={value => update ('parentPostIds', value)}/>
<FieldWarning messages={displayRow.baseWarnings}/>
<FieldError messages={displayRow.validationErrors.base}/>
<FieldError messages={displayRow.importErrors?.base}/>
<div className="pt-2">
<Button
type="button"
variant="destructive"
onClick={() => reset ()}
disabled={resetDisabled}>
</Button>
</div>
</div>
</div>
</div>
</div>
<div className="flex shrink-0 flex-col-reverse gap-2 px-6 pb-6 pt-4 sm:flex-row sm:justify-end">
<Button
type="button"
variant="destructive"
onClick={() => reset ()}
disabled={resetDisabled}>
</Button>
<Button
type="button"
variant="outline"
onClick={onCancel}
disabled={saving}>
</Button>
<Button
type="button"
onClick={() => save ()}
disabled={saving}>
</Button>
</div>
</>)
}
@@ -260,4 +257,6 @@ const PostImportAreaField = (
</FormField>)
export default PostImportRowForm
export { buildDraft }
export type { Draft as PostImportRowDraft }
export type { Draft as PostImportRowDraft }