/** * Page Service * 페이지 관련 도메인 로직 중앙화 * - validation * - path generation * - transform (폼 ↔ API) * - defaults */ import type { ItemPage } from '@/contexts/ItemMasterContext'; // ===== Types ===== export type ItemType = 'FG' | 'PT' | 'SM' | 'RM' | 'CS'; export interface PageFormData { pageName: string; itemType: ItemType; absolutePath?: string; } export interface PageValidationResult { valid: boolean; errors: { page_name?: string; item_type?: string; absolute_path?: string; }; } // ===== Constants ===== const ITEM_TYPE_MAP: Record = { 'FG': '제품관리', 'PT': '부품관리', 'SM': '부자재관리', 'RM': '원자재관리', 'CS': '소모품관리', }; // ===== Service ===== export const pageService = { // ===== Validation ===== /** * 전체 페이지 폼 유효성 검사 */ validate: (data: Partial): PageValidationResult => { const errors: PageValidationResult['errors'] = {}; const nameValidation = pageService.validatePageName(data.pageName || ''); if (!nameValidation.valid) { errors.page_name = nameValidation.error; } const typeValidation = pageService.validateItemType(data.itemType || ''); if (!typeValidation.valid) { errors.item_type = typeValidation.error; } return { valid: Object.keys(errors).length === 0, errors, }; }, /** * 페이지명 유효성 검사 */ validatePageName: (name: string): { valid: boolean; error?: string } => { if (!name || !name.trim()) { return { valid: false, error: '페이지명을 입력해주세요' }; } return { valid: true }; }, /** * 품목 타입 유효성 검사 */ validateItemType: (type: string): { valid: boolean; error?: string } => { const validTypes: ItemType[] = ['FG', 'PT', 'SM', 'RM', 'CS']; if (!validTypes.includes(type as ItemType)) { return { valid: false, error: '유효하지 않은 품목 타입입니다' }; } return { valid: true }; }, /** * 절대경로 유효성 검사 */ validateAbsolutePath: (path: string): { valid: boolean; error?: string } => { if (!path || !path.trim()) { return { valid: false, error: '절대경로를 입력해주세요' }; } if (!path.startsWith('/')) { return { valid: false, error: '절대경로는 /로 시작해야 합니다' }; } return { valid: true }; }, // ===== Path Generation ===== /** * 품목 타입과 페이지명으로 절대 경로 생성 */ generateAbsolutePath: (itemType: ItemType, pageName: string): string => { const category = ITEM_TYPE_MAP[itemType] || '기타'; return `/${category}/${pageName}`; }, /** * 품목 타입 코드를 한글 카테고리명으로 변환 */ getItemTypeLabel: (itemType: ItemType): string => { return ITEM_TYPE_MAP[itemType] || '기타'; }, // ===== Transform ===== /** * 폼 데이터 → API 요청 객체 변환 */ toApiRequest: ( formData: PageFormData ): Omit => { const absolutePath = formData.absolutePath || pageService.generateAbsolutePath(formData.itemType, formData.pageName); return { page_name: formData.pageName, item_type: formData.itemType, absolute_path: absolutePath, is_active: true, sections: [], order_no: 0, }; }, /** * ItemPage → 폼 데이터 변환 */ toFormData: (page: ItemPage): PageFormData => { return { pageName: page.page_name, itemType: page.item_type as ItemType, absolutePath: page.absolute_path, }; }, /** * 페이지 복제용 데이터 생성 */ toDuplicateRequest: ( originalPage: ItemPage ): Omit => { const duplicatedName = `${originalPage.page_name} (복제)`; const absolutePath = pageService.generateAbsolutePath( originalPage.item_type as ItemType, duplicatedName ); return { page_name: duplicatedName, item_type: originalPage.item_type, absolute_path: absolutePath, is_active: true, sections: [], // 섹션은 별도 API로 복제 order_no: 0, }; }, // ===== Defaults ===== /** * 새 페이지 생성 시 기본값 */ getDefaultFormData: (): PageFormData => ({ pageName: '', itemType: 'FG', }), /** * 지원하는 품목 타입 목록 */ itemTypes: [ { value: 'FG', label: '제품관리', description: '완제품' }, { value: 'PT', label: '부품관리', description: '조립 부품' }, { value: 'SM', label: '부자재관리', description: '부자재' }, { value: 'RM', label: '원자재관리', description: '원자재' }, { value: 'CS', label: '소모품관리', description: '소모품' }, ] as const, };