File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
import type { CommonCode } from '@/lib/domain/common-code';
import { MAX_PRODUCT_BADGES, type MerchantProductBadge } from '@/lib/domain/merchant-product';
/** 기획 BO-MAL-004 ② — 필수는 메뉴명·가격·노출 여부 셋. */
export const PRODUCT_NAME_MAX_LENGTH = 100;
/** 기획 BO-MAL-004 ⑤ [의사결정 필요] 잠정값 — 설명 최대 글자수. */
export const PRODUCT_DESCRIPTION_MAX_LENGTH = 120;
export const PRODUCT_PRICE_MAX = 99_999_999;
export const PRODUCT_SORT_ORDER_MAX = 9999;
export type MerchantProductValues = {
frcsNo: string;
name: string;
price: number | null;
description: string;
badges: MerchantProductBadge[];
isVisible: boolean;
sortOrder: number | null;
imageFileId: string;
};
export type MerchantProductFormErrors = Partial<
Record<'name' | 'price' | 'description' | 'badges' | 'sortOrder' | 'image', string>
>;
export type MerchantProductFormState =
| { status: 'idle' }
| { status: 'error'; message?: string; errors?: MerchantProductFormErrors }
| { status: 'success' };
export const INITIAL_MERCHANT_PRODUCT_FORM_STATE: MerchantProductFormState = {
status: 'idle',
};
type ValidationResult =
| { ok: true; values: MerchantProductValues }
| { ok: false; errors: MerchantProductFormErrors };
export function validateMerchantProduct(
values: MerchantProductValues,
badgeCodes: readonly CommonCode[]
): ValidationResult {
const errors: MerchantProductFormErrors = {};
const name = values.name.trim();
if (!name) {
errors.name = '메뉴명을 입력해 주세요.';
} else if (name.length > PRODUCT_NAME_MAX_LENGTH) {
errors.name = `메뉴명은 ${PRODUCT_NAME_MAX_LENGTH}자 이내로 입력해 주세요.`;
}
if (
values.price === null ||
!Number.isInteger(values.price) ||
values.price < 0 ||
values.price > PRODUCT_PRICE_MAX
) {
errors.price = '가격은 숫자만 입력해 주세요.';
}
const description = values.description.trim();
if (description.length > PRODUCT_DESCRIPTION_MAX_LENGTH) {
errors.description = `설명은 ${PRODUCT_DESCRIPTION_MAX_LENGTH}자 이내로 입력해 주세요.`;
}
const badges = values.badges.filter((badge) => badgeCodes.some((code) => code.code === badge));
if (badges.length > MAX_PRODUCT_BADGES) {
errors.badges = `배지는 최대 ${MAX_PRODUCT_BADGES}개까지 고를 수 있습니다.`;
}
if (
values.sortOrder !== null &&
(!Number.isInteger(values.sortOrder) ||
values.sortOrder < 0 ||
values.sortOrder > PRODUCT_SORT_ORDER_MAX)
) {
errors.sortOrder = `노출 순서는 0 이상 ${PRODUCT_SORT_ORDER_MAX} 이하의 숫자로 입력해 주세요.`;
}
if (Object.keys(errors).length > 0) {
return { ok: false, errors };
}
return { ok: true, values: { ...values, name, description, badges } };
}