diff --git a/frontend/components/dataflow/ConnectionSetupModal.tsx b/frontend/components/dataflow/ConnectionSetupModal.tsx index 16a2676f..056381af 100644 --- a/frontend/components/dataflow/ConnectionSetupModal.tsx +++ b/frontend/components/dataflow/ConnectionSetupModal.tsx @@ -454,30 +454,63 @@ export const ConnectionSetupModal: React.FC = ({ }; const isButtonDisabled = () => { - const hasRelationshipName = !!config.relationshipName; - const isDataSave = config.connectionType === "data-save"; - const hasActions = dataSaveSettings.actions.length > 0; - const allActionsHaveMappings = dataSaveSettings.actions.every((action) => action.fieldMappings.length > 0); - const allMappingsComplete = dataSaveSettings.actions.every((action) => - action.fieldMappings.every((mapping) => { - // 타겟은 항상 필요 - if (!mapping.targetTable || !mapping.targetField) return false; + // 공통 검증: 관계 이름은 필수 + const hasRelationshipName = !!config.relationshipName?.trim(); + if (!hasRelationshipName) return true; - // 소스와 기본값 중 하나는 있어야 함 - const hasSource = mapping.sourceTable && mapping.sourceField; - const hasDefault = mapping.defaultValue && mapping.defaultValue.trim(); + // 연결 타입별 검증 + switch (config.connectionType) { + case "simple-key": + // 단순 키값 연결: From과 To 컬럼이 모두 선택되어야 함 + const hasFromColumns = selectedFromColumns.length > 0; + const hasToColumns = selectedToColumns.length > 0; + return !hasFromColumns || !hasToColumns; - // FROM 테이블이 비어있으면 기본값이 필요 - if (!mapping.sourceTable) { - return !!hasDefault; + case "data-save": + // 데이터 저장: 액션과 필드 매핑이 완성되어야 함 + const hasActions = dataSaveSettings.actions.length > 0; + const allActionsHaveMappings = dataSaveSettings.actions.every((action) => action.fieldMappings.length > 0); + const allMappingsComplete = dataSaveSettings.actions.every((action) => + action.fieldMappings.every((mapping) => { + // 타겟은 항상 필요 + if (!mapping.targetTable || !mapping.targetField) return false; + + // 소스와 기본값 중 하나는 있어야 함 + const hasSource = mapping.sourceTable && mapping.sourceField; + const hasDefault = mapping.defaultValue && mapping.defaultValue.trim(); + + // FROM 테이블이 비어있으면 기본값이 필요 + if (!mapping.sourceTable) { + return !!hasDefault; + } + + // FROM 테이블이 있으면 소스 매핑 완성 또는 기본값 필요 + return hasSource || hasDefault; + }), + ); + return !hasActions || !allActionsHaveMappings || !allMappingsComplete; + + case "external-call": + // 외부 호출: 호출 타입과 필수 설정이 있어야 함 + const hasCallType = !!externalCallSettings.callType; + if (!hasCallType) return true; + + switch (externalCallSettings.callType) { + case "rest-api": + return !externalCallSettings.apiUrl?.trim(); + case "kakao-talk": + return !externalCallSettings.kakaoAccessToken?.trim() || !externalCallSettings.bodyTemplate?.trim(); + case "email": + return !externalCallSettings.apiUrl?.trim(); // 이메일 서버 URL 필요 + case "webhook": + return !externalCallSettings.apiUrl?.trim(); + default: + return true; } - // FROM 테이블이 있으면 소스 매핑 완성 또는 기본값 필요 - return hasSource || hasDefault; - }), - ); - - return !hasRelationshipName || (isDataSave && (!hasActions || !allActionsHaveMappings || !allMappingsComplete)); + default: + return false; + } }; if (!connection) return null;