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 { FoxHelperText } from '@fox/core/components/fox-helper-text';
import { FoxIconButton } from '@fox/core/components/fox-icon-button';
import { FoxInput } from '@fox/core/components/fox-input';
import { FoxTextButton } from '@fox/core/components/fox-text-button';
import { FoxPlusIcon, FoxTrashIcon } from '@fox/core/icons';
import {
DEFAULT_KEYWORD_ROWS,
type ContentKeyword,
} from '@/lib/domain/content';
import {
KEYWORD_DESCRIPTION_MAX_LENGTH,
KEYWORD_MAX_LENGTH,
} from '@/lib/domain/content-form';
import styles from './content-form.module.scss';
interface ContentKeywordFieldProps {
defaultKeywords?: readonly ContentKeyword[];
error?: string;
}
const EMPTY_ROW: ContentKeyword = { keyword: '', description: '' };
function initialRows(
defaults: readonly ContentKeyword[]
): Array<ContentKeyword & { key: number }> {
const rows = defaults.length > 0 ? defaults : Array.from({ length: DEFAULT_KEYWORD_ROWS }, () => EMPTY_ROW);
return rows.map((row, index) => ({ ...row, key: index }));
}
/** 키워드 — 키워드와 설명을 쌍으로 입력한다. 기본 2줄이고 줄을 더 늘릴 수 있다. */
export function ContentKeywordField({
defaultKeywords = [],
error,
}: ContentKeywordFieldProps) {
const [rows, setRows] = useState(() => initialRows(defaultKeywords));
const [nextKey, setNextKey] = useState(rows.length);
function addRow() {
setRows((current) => [...current, { ...EMPTY_ROW, key: nextKey }]);
setNextKey((current) => current + 1);
}
function removeRow(key: number) {
setRows((current) =>
current.length === 1 ? current : current.filter((row) => row.key !== key)
);
}
return (
<>
{rows.map((row) => (
<div key={row.key} className={styles.keywordRow}>
<div className={styles.keywordName}>
<FoxInput
size="md"
name="keyword"
aria-label="키워드"
defaultValue={row.keyword}
placeholder="키워드"
maxLength={KEYWORD_MAX_LENGTH}
/>
</div>
<div className={styles.keywordDescription}>
<FoxInput
size="md"
name="keywordDescription"
aria-label="키워드 설명"
defaultValue={row.description}
placeholder="키워드에 대한 간단한 설명"
maxLength={KEYWORD_DESCRIPTION_MAX_LENGTH}
/>
</div>
<FoxIconButton
type="default"
size="md"
icon={<FoxTrashIcon />}
label="키워드 삭제"
disabled={rows.length === 1}
onAction={() => removeRow(row.key)}
/>
</div>
))}
<div>
<FoxTextButton
size="md"
leadingIcon={<FoxPlusIcon />}
label="키워드 추가"
onAction={addRow}
/>
</div>
{error && <FoxHelperText type="danger" message={error} />}
</>
);
}