"use client"; import React, { useState, useEffect } from "react"; import { Eye, EyeOff, ChevronDown, ChevronRight } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"; import { useToast } from "@/hooks/use-toast"; import { ExternalDbConnectionAPI, ExternalDbConnection, ConnectionTestRequest, ConnectionTestResult, } from "@/lib/api/externalDbConnection"; interface ExternalDbConnectionModalProps { isOpen: boolean; onClose: () => void; onSave: () => void; connection?: ExternalDbConnection; supportedDbTypes: Array<{ value: string; label: string }>; } // 기본 포트 설정 const DEFAULT_PORTS: Record = { mysql: 3306, postgresql: 5432, oracle: 1521, mssql: 1433, sqlite: 0, // SQLite는 파일 기반이므로 포트 없음 }; export const ExternalDbConnectionModal: React.FC = ({ isOpen, onClose, onSave, connection, supportedDbTypes, }) => { const { toast } = useToast(); // 상태 관리 const [loading, setSaving] = useState(false); const [showPassword, setShowPassword] = useState(false); const [showAdvanced, setShowAdvanced] = useState(false); const [testingConnection, setTestingConnection] = useState(false); const [testResult, setTestResult] = useState(null); // 폼 데이터 const [formData, setFormData] = useState({ connection_name: "", description: "", db_type: "postgresql", host: "localhost", port: DEFAULT_PORTS.postgresql, database_name: "", username: "", password: "", connection_timeout: 30, query_timeout: 60, max_connections: 10, ssl_enabled: "N", ssl_cert_path: "", company_code: "*", is_active: "Y", }); // 편집 모드인지 확인 const isEditMode = !!connection; // 연결 정보가 변경될 때 폼 데이터 업데이트 useEffect(() => { if (connection) { setFormData({ ...connection, // 편집 시에는 비밀번호를 빈 문자열로 설정 (보안상 기존 비밀번호는 보여주지 않음) password: "", }); } else { // 새 연결 생성 시 기본값 설정 setFormData({ connection_name: "", description: "", db_type: "postgresql", host: "localhost", port: DEFAULT_PORTS.postgresql, database_name: "", username: "", password: "", connection_timeout: 30, query_timeout: 60, max_connections: 10, ssl_enabled: "N", ssl_cert_path: "", company_code: "*", is_active: "Y", }); } }, [connection]); // DB 타입 변경 시 기본 포트 설정 const handleDbTypeChange = (dbType: string) => { setFormData({ ...formData, db_type: dbType as ExternalDbConnection["db_type"], port: DEFAULT_PORTS[dbType] || 5432, }); }; // 입력값 변경 처리 const handleInputChange = (field: keyof ExternalDbConnection, value: string | number) => { setFormData({ ...formData, [field]: value, }); }; // 폼 검증 const validateForm = (): boolean => { if (!formData.connection_name.trim()) { toast({ title: "검증 오류", description: "연결명을 입력해주세요.", variant: "destructive", }); return false; } if (!formData.host.trim()) { toast({ title: "검증 오류", description: "호스트를 입력해주세요.", variant: "destructive", }); return false; } if (!formData.database_name.trim()) { toast({ title: "검증 오류", description: "데이터베이스명을 입력해주세요.", variant: "destructive", }); return false; } if (!formData.username.trim()) { toast({ title: "검증 오류", description: "사용자명을 입력해주세요.", variant: "destructive", }); return false; } if (!isEditMode && !formData.password.trim()) { toast({ title: "검증 오류", description: "비밀번호를 입력해주세요.", variant: "destructive", }); return false; } return true; }; // 연결 테스트 처리 const handleTestConnection = async () => { // 기본 필수 필드 검증 if (!formData.host.trim()) { toast({ title: "검증 오류", description: "호스트를 입력해주세요.", variant: "destructive", }); return; } if (!formData.database_name.trim()) { toast({ title: "검증 오류", description: "데이터베이스명을 입력해주세요.", variant: "destructive", }); return; } if (!formData.username.trim()) { toast({ title: "검증 오류", description: "사용자명을 입력해주세요.", variant: "destructive", }); return; } if (!formData.password.trim()) { toast({ title: "검증 오류", description: "비밀번호를 입력해주세요.", variant: "destructive", }); return; } try { setTestingConnection(true); setTestResult(null); const testData: ConnectionTestRequest = { db_type: formData.db_type, host: formData.host, port: formData.port, database_name: formData.database_name, username: formData.username, password: formData.password, connection_timeout: formData.connection_timeout, ssl_enabled: formData.ssl_enabled, }; const result = await ExternalDbConnectionAPI.testConnection(testData); setTestResult(result); if (result.success) { toast({ title: "연결 테스트 성공", description: result.message, }); } else { toast({ title: "연결 테스트 실패", description: result.message, variant: "destructive", }); } } catch (error) { console.error("연결 테스트 오류:", error); const errorResult: ConnectionTestResult = { success: false, message: "연결 테스트 중 오류가 발생했습니다.", error: { code: "TEST_ERROR", details: error instanceof Error ? error.message : "알 수 없는 오류", }, }; setTestResult(errorResult); toast({ title: "연결 테스트 오류", description: errorResult.message, variant: "destructive", }); } finally { setTestingConnection(false); } }; // 저장 처리 const handleSave = async () => { if (!validateForm()) return; try { setSaving(true); // 편집 모드에서 비밀번호가 비어있으면 기존 비밀번호 유지 let dataToSave = { ...formData }; if (isEditMode && !dataToSave.password.trim()) { // eslint-disable-next-line @typescript-eslint/no-unused-vars const { password, ...dataWithoutPassword } = dataToSave; dataToSave = dataWithoutPassword as ExternalDbConnection; } if (isEditMode && connection?.id) { await ExternalDbConnectionAPI.updateConnection(connection.id, dataToSave); toast({ title: "성공", description: "연결 정보가 수정되었습니다.", }); } else { await ExternalDbConnectionAPI.createConnection(dataToSave); toast({ title: "성공", description: "새 연결이 생성되었습니다.", }); } onSave(); } catch (error) { console.error("연결 저장 오류:", error); toast({ title: "오류", description: error instanceof Error ? error.message : "연결 저장에 실패했습니다.", variant: "destructive", }); } finally { setSaving(false); } }; return ( {isEditMode ? "연결 정보 수정" : "새 외부 DB 연결 추가"}
{/* 기본 정보 */}

기본 정보

handleInputChange("connection_name", e.target.value)} placeholder="예: 운영 DB" />