File name
Commit message
Commit date
File name
Commit message
Commit date
09-03
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>
);
}