/** * 가맹몰 메뉴 — 백엔드 `TB_COM_VOUCHER_PRODUCT`(`/api/v1/mngr/voc/product`). * 기획(BO-MAL-004)은 「메뉴」, 백엔드는 product라 부른다. 코드는 백엔드를 따르고 화면 문구만 * 「메뉴」다 — 앱 메뉴관리(`system-menu`)와 이름이 겹치지 않게 하려는 뜻이다. */ export type MerchantProduct = { /** 백엔드 `frcsProductSn`. */ id: string; frcsNo: string; name: string; price: number | null; description: string | null; /** 기획 BO-MAL-004 ③ — 선택한 순서대로. */ badges: MerchantProductBadge[]; imageFileId: string | null; /** Repository가 만든 이미지 URL. */ imageUrl: string | null; sortOrder: number | null; isVisible: boolean; }; export const MERCHANT_PRODUCT_BADGE_OPTIONS = [ { value: 'BEST', label: 'BEST' }, { value: 'MAIN', label: '대표' }, { value: 'NEW', label: '신규' }, { value: 'SALE', label: '할인' }, ] as const; export type MerchantProductBadge = (typeof MERCHANT_PRODUCT_BADGE_OPTIONS)[number]['value']; /** 기획 BO-MAL-004 ③ [의사결정 필요] 잠정값 — 배지 동시 선택 상한. */ export const MAX_PRODUCT_BADGES = 2; const BADGE_SEPARATOR = ','; /** * 배지 ↔ 백엔드 `frcsBadge`(문자열 하나). 앱·백엔드에 규약이 없어 여기서 정한다(사용자 확정): * 코드를 쉼표로 잇고 순서를 보존한다. 예) `BEST,MAIN` */ export function parseProductBadges(raw: string | null): MerchantProductBadge[] { if (!raw) { return []; } return raw .split(BADGE_SEPARATOR) .map((token) => token.trim()) .filter((token): token is MerchantProductBadge => MERCHANT_PRODUCT_BADGE_OPTIONS.some((option) => option.value === token) ); } export function joinProductBadges(badges: readonly MerchantProductBadge[]): string { return badges.join(BADGE_SEPARATOR); } export function formatProductBadgeLabel(badge: MerchantProductBadge): string { return ( MERCHANT_PRODUCT_BADGE_OPTIONS.find((option) => option.value === badge)?.label ?? badge ); } export const MERCHANT_PRODUCT_VISIBILITY_OPTIONS = [ { value: 'Y', label: '노출' }, { value: 'N', label: '숨김' }, ] as const; export function formatProductVisibilityLabel(isVisible: boolean): string { return isVisible ? '노출' : '숨김'; } /** 기획 BO-MAL-004 ② — 숫자만 받고 노출 시 세 자리 콤마와 '원'을 붙인다. */ export function formatProductPrice(price: number | null): string { return price === null ? '-' : `${price.toLocaleString('ko-KR')}원`; }