File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
'use client';
import { useActionState } from 'react';
import { FoxFileUpload } from '@fox/core/components/fox-file-upload';
import { FoxHelperText } from '@fox/core/components/fox-helper-text';
import { FoxInput } from '@fox/core/components/fox-input';
import { FoxPageHeader } from '@fox/core/components/fox-page-header';
import { FoxTextArea } from '@fox/core/components/fox-text-area';
import { submitFormAction } from '@/app/_hooks/submit-form-action';
import {
THUMBNAIL_HELP_TEXT,
type ContentItem,
type GradesBySchool,
} from '@/lib/domain/content';
import {
INITIAL_CONTENT_FORM_STATE,
MESSAGE_MAX_LENGTH,
SUBJECT_MAX_LENGTH,
TITLE_MAX_LENGTH,
} from '@/lib/domain/content-form';
import { contentBreadcrumb, contentListPath } from '@/lib/domain/content-query';
import type { CommonCode } from '@/lib/domain/common-code';
import { FILE_MODULE, fileModuleAccept } from '@/lib/domain/file-module';
import { createComicAction, updateComicAction } from '../../_actions';
import { ContentCutsField } from '../../_components/content-cuts-field';
import { ContentFormActions } from '../../_components/content-form-actions';
import { ContentFormRow } from '../../_components/content-form-row';
import { ContentGradeField } from '../../_components/content-grade-field';
import { ContentKeywordField } from '../../_components/content-keyword-field';
import { ContentVisibilityField } from '../../_components/content-visibility-field';
import styles from '../../_components/content-form.module.scss';
interface ComicFormProps {
schools: readonly CommonCode[];
gradesBySchool: GradesBySchool;
item?: ContentItem;
thumbnailUrl?: string | null;
cutUrls?: string[];
}
/** 콘텐츠 등록·수정 (4컷금융만화) — 시안 5449:10850. */
export function ComicForm({
schools,
gradesBySchool,
item,
thumbnailUrl,
cutUrls = [],
}: ComicFormProps) {
const isEdit = item !== undefined;
const [state, formAction, isPending] = useActionState(
isEdit ? updateComicAction : createComicAction,
INITIAL_CONTENT_FORM_STATE
);
const errors = state.status === 'error' ? (state.errors ?? {}) : {};
return (
<>
<FoxPageHeader
title={`콘텐츠 ${isEdit ? '수정' : '등록'} (4컷금융만화)`}
breadcrumb={contentBreadcrumb('comic', isEdit ? '수정' : '등록')}
/>
<form
onSubmit={(event) => submitFormAction(event, formAction)}
className={styles.form}
>
{isEdit && <input type="hidden" name="cntntsSn" value={item.cntntsSn} />}
{isEdit && (
<ContentFormRow label="콘텐츠ID">
<FoxInput size="md" value={item.cntntsSn} readOnly />
</ContentFormRow>
)}
<ContentFormRow label="학년선택" required>
<ContentGradeField
schools={schools}
gradesBySchool={gradesBySchool}
defaultSchoolCode={item?.schoolCode}
defaultGrades={item?.grades}
schoolError={errors.schoolCode}
gradesError={errors.grades}
/>
</ContentFormRow>
<ContentFormRow label="콘텐츠명" required>
<FoxInput
size="md"
name="name"
aria-label="콘텐츠명"
defaultValue={item?.name ?? ''}
placeholder="콘텐츠명을 입력하세요."
maxLength={TITLE_MAX_LENGTH}
invalid={Boolean(errors.name)}
message={errors.name}
/>
</ContentFormRow>
<ContentFormRow label="주제">
<FoxInput
size="md"
name="subject"
aria-label="주제"
defaultValue={item?.subject ?? ''}
placeholder="주제를 입력하세요."
maxLength={SUBJECT_MAX_LENGTH}
/>
</ContentFormRow>
<ContentFormRow label="키워드">
<ContentKeywordField
defaultKeywords={item?.keywords}
error={errors.keywords}
/>
</ContentFormRow>
<ContentFormRow label="전달 메시지(해설)" required>
<FoxTextArea
name="message"
aria-label="전달 메시지(해설)"
defaultValue={item?.message ?? ''}
rows={4}
placeholder="전달 메시지(해설)를 입력하세요."
maxLength={MESSAGE_MAX_LENGTH}
counter
invalid={Boolean(errors.message)}
message={errors.message}
/>
</ContentFormRow>
<ContentFormRow label="썸네일">
<FoxFileUpload
mode="image"
name="thumbnailFile"
accept={fileModuleAccept(FILE_MODULE.contentThumbnail)}
selectLabel="파일선택"
description={THUMBNAIL_HELP_TEXT}
thumbnailWidth={213}
thumbnailHeight={120}
defaultFiles={
thumbnailUrl
? [{ id: 'current', name: '썸네일', previewUrl: thumbnailUrl }]
: undefined
}
/>
<input
type="hidden"
name="thumbnailFileId"
defaultValue={item?.thumbnailFileId ?? ''}
/>
</ContentFormRow>
<ContentFormRow label="만화 이미지" optionalText="(4컷 이상)">
<ContentCutsField
defaultCutUrls={cutUrls}
retainedFileId={item?.attachmentId}
error={errors.cutFileIds}
/>
</ContentFormRow>
<ContentFormRow label="공개 설정" required>
<ContentVisibilityField defaultVisible={item?.isVisible ?? false} />
</ContentFormRow>
{state.status === 'error' && state.message && (
<FoxHelperText type="danger" message={state.message} />
)}
<ContentFormActions
submitLabel={isEdit ? '수정' : '등록'}
listHref={contentListPath('comic')}
pending={isPending}
/>
</form>
</>
);
}