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 { useState } from 'react';
import { FoxFileUpload } from '@fox/core/components/fox-file-upload';
import { FoxHelperText } from '@fox/core/components/fox-helper-text';
import { FoxTextButton } from '@fox/core/components/fox-text-button';
import { MIN_COMIC_CUTS } from '@/lib/domain/content';
import { FILE_MODULE, fileModuleAccept } from '@/lib/domain/file-module';
import styles from './content-form.module.scss';
interface ContentCutsFieldProps {
/** 수정 화면에서 이미 등록된 컷 이미지 URL(1컷부터 순서대로). */
defaultCutUrls?: readonly string[];
/** 새로 고르지 않은 컷이 잃어버리지 않도록 들고 있는 기존 첨부 ID. */
retainedFileId?: string | null;
error?: string;
}
type Cut = { key: number; url: string | null };
/**
* 만화 이미지 — 기본 4컷을 깔고 「컷 추가」로 계속 늘린다(기획 "4컷 이상 구성도 가능").
* 각 컷은 개별 이미지로 올린다.
*/
export function ContentCutsField({
defaultCutUrls = [],
retainedFileId,
error,
}: ContentCutsFieldProps) {
const [cuts, setCuts] = useState<Cut[]>(() => {
const count = Math.max(MIN_COMIC_CUTS, defaultCutUrls.length);
return Array.from({ length: count }, (_, index) => ({
key: index,
url: defaultCutUrls[index] ?? null,
}));
});
const [nextKey, setNextKey] = useState(cuts.length);
function addCut() {
setCuts((current) => [...current, { key: nextKey, url: null }]);
setNextKey((current) => current + 1);
}
function removeCut(key: number) {
setCuts((current) =>
current.length <= MIN_COMIC_CUTS
? current
: current.filter((cut) => cut.key !== key)
);
}
return (
<>
<div className={styles.cuts}>
{cuts.map((cut, index) => (
<div key={cut.key} className={styles.cut}>
<FoxFileUpload
mode="image"
name="cutFile"
accept={fileModuleAccept(FILE_MODULE.toonContent)}
selectLabel="파일선택"
thumbnailWidth={132}
thumbnailHeight={74}
defaultFiles={
cut.url
? [{ id: String(cut.key), name: `${index + 1}컷`, previewUrl: cut.url }]
: undefined
}
/>
<input
type="hidden"
name="cutFileId"
defaultValue={cut.url ? (retainedFileId ?? '') : ''}
/>
<div className={styles.cutFooter}>
<span className={styles.cutLabel}>{index + 1}컷</span>
<FoxTextButton
size="sm"
leadingIcon={<i className="fox-ico fox-ico-Trash" aria-hidden="true" />}
label="삭제"
disabled={cuts.length <= MIN_COMIC_CUTS}
onAction={() => removeCut(cut.key)}
/>
</div>
</div>
))}
</div>
<div>
<FoxTextButton
size="md"
leadingIcon={<i className="fox-ico fox-ico-Plus" aria-hidden="true" />}
label="컷 추가"
onAction={addCut}
/>
</div>
{error && <FoxHelperText type="danger" message={error} />}
</>
);
}