export const NAME_MAX_LENGTH = 100; export const URL_MAX_LENGTH = 300; export const DESCRIPTION_MAX_LENGTH = 300; export const SORT_ORDER_MAX = 9999; export interface SystemMenuValues { id: string; parentId: string; parentIdPath: string; name: string; sortOrder: number; isTopActive: boolean; url: string; description: string; largeIconId: string; smallIconId: string; isActive: boolean; } export type SystemMenuFormErrors = Partial< Record< 'name' | 'sortOrder' | 'url' | 'description' | 'largeIconId' | 'smallIconId', string > >; export type SystemMenuFormState = | { status: 'idle' } | { status: 'error'; message?: string; errors?: SystemMenuFormErrors } | { status: 'success' }; export const INITIAL_SYSTEM_MENU_FORM_STATE: SystemMenuFormState = { status: 'idle', }; /** 기획 SYS_MNU_002_p ④ — 미입력 시 이 문구를 띄운다. */ export const REQUIRED_MESSAGE = '필수입력 사항을 입력하세요.'; type ValidationResult = | { ok: true; values: SystemMenuValues } | { ok: false; errors: SystemMenuFormErrors }; function validateText( raw: string, max: number, label: string ): { value: string; error?: string } { const value = raw.trim(); if (!value) { return { value, error: REQUIRED_MESSAGE }; } if (value.length > max) { return { value, error: `${label}은 ${max}자 이내로 입력해 주세요.` }; } return { value }; } export function validateSystemMenu(values: SystemMenuValues): ValidationResult { const errors: SystemMenuFormErrors = {}; const name = validateText(values.name, NAME_MAX_LENGTH, '메뉴명'); if (name.error) { errors.name = name.error; } const url = validateText(values.url, URL_MAX_LENGTH, '메뉴링크'); if (url.error) { errors.url = url.error; } const description = validateText( values.description, DESCRIPTION_MAX_LENGTH, '메뉴설명' ); if (description.error) { errors.description = description.error; } if (!Number.isInteger(values.sortOrder) || values.sortOrder < 1) { errors.sortOrder = '메뉴순번은 1 이상의 숫자로 입력해 주세요.'; } else if (values.sortOrder > SORT_ORDER_MAX) { errors.sortOrder = `메뉴순번은 ${SORT_ORDER_MAX} 이하로 입력해 주세요.`; } if (Object.keys(errors).length > 0) { return { ok: false, errors }; } return { ok: true, values: { ...values, name: name.value, url: url.value, description: description.value, }, }; }