File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
import {
foxValidationMessage,
foxValidators,
type FoxValidationMessages,
} from '@fox/core/validation';
export type AdminMenuValues = {
name: string;
sortOrder: number;
roleId: string;
isTopActive: boolean;
url: string;
/** 이슈: 백엔드에 대응 컬럼이 없어 저장되지 않는다. 기획대로 화면에만 둔다. */
opensNewWindow: boolean;
description: string;
isActive: boolean;
};
export type AdminMenuFormErrors = Partial<Record<keyof AdminMenuValues, string>>;
export type AdminMenuFormState =
| { status: 'idle' }
| { status: 'error'; message?: string; errors?: AdminMenuFormErrors }
| { status: 'success' };
export const INITIAL_ADMIN_MENU_FORM_STATE: AdminMenuFormState = {
status: 'idle',
};
const NAME_MAX_LENGTH = 100;
const URL_MAX_LENGTH = 300;
const DESCRIPTION_MAX_LENGTH = 500;
const NAME_VALIDATORS = [
foxValidators.required,
foxValidators.maxLength(NAME_MAX_LENGTH),
];
const URL_VALIDATORS = [
foxValidators.required,
foxValidators.maxLength(URL_MAX_LENGTH),
];
const DESCRIPTION_VALIDATORS = [
foxValidators.required,
foxValidators.maxLength(DESCRIPTION_MAX_LENGTH),
];
export const ADMIN_MENU_NAME_MESSAGES: FoxValidationMessages = {
required: '메뉴명을 입력해 주세요.',
maxlength: `메뉴명은 ${NAME_MAX_LENGTH}자 이내로 입력해 주세요.`,
};
export const ADMIN_MENU_URL_MESSAGES: FoxValidationMessages = {
required: '메뉴링크를 입력해 주세요.',
maxlength: `메뉴링크는 ${URL_MAX_LENGTH}자 이내로 입력해 주세요.`,
};
export const ADMIN_MENU_DESCRIPTION_MESSAGES: FoxValidationMessages = {
required: '메뉴설명을 입력해 주세요.',
maxlength: `메뉴설명은 ${DESCRIPTION_MAX_LENGTH}자 이내로 입력해 주세요.`,
};
export { NAME_VALIDATORS, URL_VALIDATORS, DESCRIPTION_VALIDATORS };
function check(
value: string,
validators: typeof NAME_VALIDATORS,
messages: FoxValidationMessages
): string | undefined {
return foxValidationMessage(
foxValidators.compose(validators)(value.trim()),
messages
);
}
export function validateAdminMenu(
values: AdminMenuValues,
allowedRoleIds: string[]
):
| { ok: true; values: AdminMenuValues }
| { ok: false; errors: AdminMenuFormErrors } {
const errors: AdminMenuFormErrors = {};
const name = values.name.trim();
const url = values.url.trim();
const description = values.description.trim();
errors.name = check(name, NAME_VALIDATORS, ADMIN_MENU_NAME_MESSAGES);
errors.url = check(url, URL_VALIDATORS, ADMIN_MENU_URL_MESSAGES);
errors.description = check(
description,
DESCRIPTION_VALIDATORS,
ADMIN_MENU_DESCRIPTION_MESSAGES
);
if (!Number.isInteger(values.sortOrder) || values.sortOrder < 1) {
errors.sortOrder = '메뉴순번은 1 이상의 숫자로 입력해 주세요.';
}
if (!allowedRoleIds.includes(values.roleId)) {
errors.roleId = '메뉴권한을 선택해 주세요.';
}
for (const key of Object.keys(errors) as (keyof AdminMenuFormErrors)[]) {
if (errors[key] === undefined) {
delete errors[key];
}
}
if (Object.keys(errors).length > 0) {
return { ok: false, errors };
}
return { ok: true, values: { ...values, name, url, description } };
}