/** * 통합 웹 타입 정의 * 프론트엔드와 백엔드에서 공통으로 사용하는 웹 타입 정의 * * 주의: 이 파일을 수정할 때는 반드시 백엔드 타입도 함께 업데이트 해야 합니다. */ // 기본 웹 타입 (DB web_type_standards와 동기화) export type BaseWebType = | "text" // 일반 텍스트 | "number" // 숫자 (정수) | "decimal" // 소수점 숫자 | "date" // 날짜 | "datetime" // 날짜시간 | "time" // 시간 | "textarea" // 여러줄 텍스트 | "select" // 선택박스 | "dropdown" // 드롭다운 (select와 동일) | "checkbox" // 체크박스 | "radio" // 라디오버튼 | "boolean" // 불린값 | "file" // 파일 업로드 | "email" // 이메일 | "tel" // 전화번호 | "url" // URL | "password" // 패스워드 | "code" // 공통코드 참조 | "entity" // 엔티티 참조 | "button"; // 버튼 // 레거시 지원용 (기존 시스템과의 호환성) export type LegacyWebType = "text_area"; // textarea와 동일 // 전체 웹 타입 (DB 동적 로딩 지원) export type WebType = BaseWebType | LegacyWebType; // 동적 웹 타입 (런타임에 DB에서 로드되는 타입 포함) export type DynamicWebType = WebType | string; // 웹 타입 카테고리 export type WebTypeCategory = | "input" // 입력 컴포넌트 | "selection" // 선택 컴포넌트 | "display" // 표시 컴포넌트 | "action" // 액션 컴포넌트 | "upload" // 업로드 컴포넌트 | "reference"; // 참조 컴포넌트 // 웹 타입 정보 export interface WebTypeInfo { webType: WebType; typeName: string; typeNameEng?: string; description?: string; category: WebTypeCategory; defaultConfig?: Record; validationRules?: Record; componentName?: string; configPanel?: string; isActive: boolean; } // 웹 타입 매핑 (레거시 지원) export const WEB_TYPE_MAPPINGS: Record = { text_area: "textarea", }; // 웹 타입 정규화 함수 export const normalizeWebType = (webType: DynamicWebType): WebType => { if (webType in WEB_TYPE_MAPPINGS) { return WEB_TYPE_MAPPINGS[webType as LegacyWebType]; } return webType as WebType; }; // 웹 타입 검증 함수 export const isValidWebType = (webType: string): webType is WebType => { return ( [ "text", "number", "decimal", "date", "datetime", "time", "textarea", "select", "dropdown", "checkbox", "radio", "boolean", "file", "email", "tel", "url", "password", "code", "entity", "button", "text_area", // 레거시 지원 ] as string[] ).includes(webType); }; // DB 타입과 웹 타입 매핑 export const DB_TYPE_TO_WEB_TYPE: Record = { // 텍스트 타입 "character varying": "text", varchar: "text", text: "textarea", char: "text", // 숫자 타입 integer: "number", bigint: "number", smallint: "number", serial: "number", bigserial: "number", numeric: "decimal", decimal: "decimal", real: "decimal", "double precision": "decimal", // 날짜/시간 타입 date: "date", timestamp: "datetime", "timestamp with time zone": "datetime", "timestamp without time zone": "datetime", time: "time", "time with time zone": "time", "time without time zone": "time", // 불린 타입 boolean: "boolean", // JSON 타입 (텍스트로 처리) json: "textarea", jsonb: "textarea", // 배열 타입 (텍스트로 처리) ARRAY: "textarea", // UUID 타입 uuid: "text", }; // 웹 타입별 기본 설정 export const WEB_TYPE_DEFAULT_CONFIGS: Record> = { text: { maxLength: 255, placeholder: "텍스트를 입력하세요" }, number: { min: 0, max: 2147483647, step: 1 }, decimal: { min: 0, step: 0.01, decimalPlaces: 2 }, date: { format: "YYYY-MM-DD" }, datetime: { format: "YYYY-MM-DD HH:mm:ss", showTime: true }, time: { format: "HH:mm:ss" }, textarea: { rows: 4, cols: 50, maxLength: 1000 }, select: { placeholder: "선택하세요", searchable: false }, dropdown: { placeholder: "선택하세요", searchable: true }, checkbox: { defaultChecked: false }, radio: { inline: false }, boolean: { trueValue: true, falseValue: false }, file: { multiple: false, preview: true }, email: { placeholder: "이메일을 입력하세요" }, tel: { placeholder: "전화번호를 입력하세요" }, url: { placeholder: "URL을 입력하세요" }, password: { placeholder: "비밀번호를 입력하세요" }, code: { placeholder: "코드를 선택하세요", searchable: true }, entity: { placeholder: "항목을 선택하세요", searchable: true }, button: { variant: "default" }, text_area: { rows: 4, cols: 50, maxLength: 1000 }, // 레거시 지원 }; // 웹 타입별 검증 규칙 export const WEB_TYPE_VALIDATION_RULES: Record> = { text: { type: "string", trim: true }, number: { type: "number", integer: true }, decimal: { type: "number", float: true }, date: { type: "date", format: "YYYY-MM-DD" }, datetime: { type: "datetime" }, time: { type: "time" }, textarea: { type: "string", multiline: true }, select: { type: "string", options: true }, dropdown: { type: "string", options: true }, checkbox: { type: "boolean" }, radio: { type: "string", options: true }, boolean: { type: "boolean" }, file: { type: "file" }, email: { type: "email" }, tel: { type: "tel" }, url: { type: "url" }, password: { type: "string", password: true }, code: { type: "string", code: true }, entity: { type: "string", entity: true }, button: { type: "action" }, text_area: { type: "string", multiline: true }, // 레거시 지원 };