"use client"; import React, { useState, useEffect } from "react"; import { ChartDataSource } from "@/components/admin/dashboard/types"; 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 { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Loader2, CheckCircle, XCircle } from "lucide-react"; interface MultiDatabaseConfigProps { dataSource: ChartDataSource; onChange: (updates: Partial) => void; } interface ExternalConnection { id: string; name: string; type: string; } export default function MultiDatabaseConfig({ dataSource, onChange }: MultiDatabaseConfigProps) { const [testing, setTesting] = useState(false); const [testResult, setTestResult] = useState<{ success: boolean; message: string; rowCount?: number } | null>(null); const [externalConnections, setExternalConnections] = useState([]); const [loadingConnections, setLoadingConnections] = useState(false); const [availableColumns, setAvailableColumns] = useState([]); // 쿼리 테스트 후 발견된 컬럼 목록 const [columnTypes, setColumnTypes] = useState>({}); // 컬럼 타입 정보 const [sampleData, setSampleData] = useState([]); // 샘플 데이터 (최대 3개) const [columnSearchTerm, setColumnSearchTerm] = useState(""); // 컬럼 검색어 // 외부 DB 커넥션 목록 로드 useEffect(() => { if (dataSource.connectionType === "external") { loadExternalConnections(); } }, [dataSource.connectionType]); const loadExternalConnections = async () => { setLoadingConnections(true); try { // ExternalDbConnectionAPI 사용 (인증 토큰 자동 포함) const { ExternalDbConnectionAPI } = await import("@/lib/api/externalDbConnection"); const connections = await ExternalDbConnectionAPI.getConnections({ is_active: "Y" }); console.log("✅ 외부 DB 커넥션 로드 성공:", connections.length, "개"); setExternalConnections(connections.map((conn: any) => ({ id: String(conn.id), name: conn.connection_name, type: conn.db_type, }))); } catch (error) { console.error("❌ 외부 DB 커넥션 로드 실패:", error); setExternalConnections([]); } finally { setLoadingConnections(false); } }; // 쿼리 테스트 const handleTestQuery = async () => { if (!dataSource.query) { setTestResult({ success: false, message: "SQL 쿼리를 입력해주세요" }); return; } setTesting(true); setTestResult(null); try { // dashboardApi 사용 (인증 토큰 자동 포함) const { dashboardApi } = await import("@/lib/api/dashboard"); if (dataSource.connectionType === "external" && dataSource.externalConnectionId) { // 외부 DB const { ExternalDbConnectionAPI } = await import("@/lib/api/externalDbConnection"); const result = await ExternalDbConnectionAPI.executeQuery( parseInt(dataSource.externalConnectionId), dataSource.query ); if (result.success && result.data) { const rows = Array.isArray(result.data.rows) ? result.data.rows : []; const rowCount = rows.length; // 컬럼 목록 및 타입 추출 if (rows.length > 0) { const columns = Object.keys(rows[0]); setAvailableColumns(columns); // 컬럼 타입 분석 const types: Record = {}; columns.forEach(col => { const value = rows[0][col]; if (value === null || value === undefined) { types[col] = "unknown"; } else if (typeof value === "number") { types[col] = "number"; } else if (typeof value === "boolean") { types[col] = "boolean"; } else if (typeof value === "string") { if (/^\d{4}-\d{2}-\d{2}/.test(value)) { types[col] = "date"; } else { types[col] = "string"; } } else { types[col] = "object"; } }); setColumnTypes(types); setSampleData(rows.slice(0, 3)); console.log("📊 발견된 컬럼:", columns); console.log("📊 컬럼 타입:", types); } setTestResult({ success: true, message: "쿼리 실행 성공", rowCount, }); } else { setTestResult({ success: false, message: result.message || "쿼리 실행 실패" }); } } else { // 현재 DB const result = await dashboardApi.executeQuery(dataSource.query); // 컬럼 목록 및 타입 추출 if (result.rows && result.rows.length > 0) { const columns = Object.keys(result.rows[0]); setAvailableColumns(columns); // 컬럼 타입 분석 const types: Record = {}; columns.forEach(col => { const value = result.rows[0][col]; if (value === null || value === undefined) { types[col] = "unknown"; } else if (typeof value === "number") { types[col] = "number"; } else if (typeof value === "boolean") { types[col] = "boolean"; } else if (typeof value === "string") { if (/^\d{4}-\d{2}-\d{2}/.test(value)) { types[col] = "date"; } else { types[col] = "string"; } } else { types[col] = "object"; } }); setColumnTypes(types); setSampleData(result.rows.slice(0, 3)); console.log("📊 발견된 컬럼:", columns); console.log("📊 컬럼 타입:", types); } setTestResult({ success: true, message: "쿼리 실행 성공", rowCount: result.rowCount || 0, }); } } catch (error: any) { setTestResult({ success: false, message: error.message || "네트워크 오류" }); } finally { setTesting(false); } }; return (
Database 설정
{/* 커넥션 타입 */}
onChange({ connectionType: value }) } >
{/* 외부 DB 선택 */} {dataSource.connectionType === "external" && (
{loadingConnections ? (
) : ( )}
)} {/* SQL 쿼리 */}