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 { FoxChip } from '@fox/core/components/fox-chip';
import { FoxChipArea } from '@fox/core/components/fox-chip-area';
import { FoxHelperText } from '@fox/core/components/fox-helper-text';
import { FoxSelect } from '@fox/core/components/fox-select';
import { gradesOf, type GradesBySchool } from '@/lib/domain/content';
import type { CommonCode } from '@/lib/domain/common-code';
import styles from './content-form.module.scss';
interface ContentGradeFieldProps {
/** 공통코드 `COM_SCHUL_CD`. */
schools: readonly CommonCode[];
/** 학교 코드 → 그 학교의 `GRD_CD` 목록. */
gradesBySchool: GradesBySchool;
defaultSchoolCode?: string;
defaultGrades?: readonly string[];
schoolError?: string;
gradesError?: string;
}
/**
* 학년선택 — 학교를 고르면 그 학교의 학년 코드만 칩으로 열린다.
* 학년이 없는 학교(전체연령 등)는 코드 목록이 비어 있어 칩을 그리지 않는다.
*/
export function ContentGradeField({
schools,
gradesBySchool,
defaultSchoolCode,
defaultGrades = [],
schoolError,
gradesError,
}: ContentGradeFieldProps) {
const [schoolCode, setSchoolCode] = useState(
defaultSchoolCode || schools[0]?.code || ''
);
const [grades, setGrades] = useState<string[]>([...defaultGrades]);
const gradeCodes = gradesOf(gradesBySchool, schoolCode);
function changeSchool(next: string) {
setSchoolCode(next);
// 학교가 바뀌면 이전 학교의 학년 코드는 남길 수 없다.
setGrades([]);
}
function toggleGrade(code: string) {
setGrades((current) =>
current.includes(code)
? current.filter((value) => value !== code)
: [...current, code]
);
}
return (
<div className={styles.grades}>
<div className={styles.inline}>
<FoxSelect
size="md"
options={schools.map((school) => ({
value: school.code,
label: school.label,
}))}
placeholder="학교를 선택하세요."
value={schoolCode}
onValueChange={changeSchool}
error={Boolean(schoolError)}
/>
{gradeCodes.length > 0 && (
<FoxChipArea size="md" label="학년" wrap>
{gradeCodes.map((grade) => (
<FoxChip
key={grade.code}
type="check"
label={grade.label}
checked={grades.includes(grade.code)}
onCheckedChange={() => toggleGrade(grade.code)}
/>
))}
</FoxChipArea>
)}
</div>
<input type="hidden" name="schoolCode" value={schoolCode} />
<input type="hidden" name="grades" value={grades.join(',')} />
{(schoolError || gradesError) && (
<FoxHelperText type="danger" message={schoolError ?? gradesError ?? ''} />
)}
</div>
);
}