"use client"; import React, { useEffect, useState } from "react"; import { DashboardElement, QueryResult, ChartData } from "../types"; import { Chart } from "./Chart"; import { transformQueryResultToChartData } from "../utils/chartDataTransform"; import { ExternalDbConnectionAPI } from "@/lib/api/externalDbConnection"; import { dashboardApi } from "@/lib/api/dashboard"; interface ChartRendererProps { element: DashboardElement; data?: QueryResult; width?: number; height?: number; } /** * 차트 렌더러 컴포넌트 (D3 기반) * - 데이터 소스에서 데이터 페칭 * - QueryResult를 ChartData로 변환 * - D3 Chart 컴포넌트에 전달 */ export function ChartRenderer({ element, data, width = 250, height = 200 }: ChartRendererProps) { const [chartData, setChartData] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); // 데이터 페칭 useEffect(() => { const fetchData = async () => { // 이미 data가 전달된 경우 사용 if (data) { const transformed = transformQueryResultToChartData(data, element.chartConfig || {}); setChartData(transformed); return; } // 데이터 소스가 설정되어 있으면 페칭 if (element.dataSource && element.dataSource.query && element.chartConfig) { setIsLoading(true); setError(null); try { let queryResult: QueryResult; // 현재 DB vs 외부 DB 분기 if (element.dataSource.connectionType === "external" && element.dataSource.externalConnectionId) { // 외부 DB const result = await ExternalDbConnectionAPI.executeQuery( parseInt(element.dataSource.externalConnectionId), element.dataSource.query, ); if (!result.success) { throw new Error(result.message || "외부 DB 쿼리 실행 실패"); } queryResult = { columns: result.data?.[0] ? Object.keys(result.data[0]) : [], rows: result.data || [], totalRows: result.data?.length || 0, executionTime: 0, }; } else { // 현재 DB const result = await dashboardApi.executeQuery(element.dataSource.query); queryResult = { columns: result.columns, rows: result.rows, totalRows: result.rowCount, executionTime: 0, }; } // ChartData로 변환 const transformed = transformQueryResultToChartData(queryResult, element.chartConfig); setChartData(transformed); } catch (err) { const errorMessage = err instanceof Error ? err.message : "데이터 로딩 실패"; setError(errorMessage); } finally { setIsLoading(false); } } }; fetchData(); // 자동 새로고침 설정 (0이면 수동이므로 interval 설정 안 함) const refreshInterval = element.dataSource?.refreshInterval; if (refreshInterval && refreshInterval > 0) { const interval = setInterval(fetchData, refreshInterval); return () => clearInterval(interval); } }, [ element.dataSource?.query, element.dataSource?.connectionType, element.dataSource?.externalConnectionId, element.dataSource?.refreshInterval, element.chartConfig, data, ]); // 로딩 중 if (isLoading) { return (
데이터 로딩 중...
); } // 에러 if (error) { return (
⚠️
오류 발생
{error}
); } // 데이터나 설정이 없으면 if (!chartData || !element.chartConfig?.xAxis || !element.chartConfig?.yAxis) { return (
📊
데이터를 설정해주세요
⚙️ 버튼을 클릭하여 설정
); } // D3 차트 렌더링 return (
); }