ERP-node/frontend/components/admin/dashboard/ElementConfigModal.tsx

170 lines
5.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client';
import React, { useState, useCallback } from 'react';
import { DashboardElement, ChartDataSource, ChartConfig, QueryResult } from './types';
import { QueryEditor } from './QueryEditor';
import { ChartConfigPanel } from './ChartConfigPanel';
interface ElementConfigModalProps {
element: DashboardElement;
isOpen: boolean;
onClose: () => void;
onSave: (element: DashboardElement) => void;
}
/**
* 요소 설정 모달 컴포넌트
* - 차트/위젯 데이터 소스 설정
* - 쿼리 에디터 통합
* - 차트 설정 패널 통합
*/
export function ElementConfigModal({ element, isOpen, onClose, onSave }: ElementConfigModalProps) {
const [dataSource, setDataSource] = useState<ChartDataSource>(
element.dataSource || { type: 'database', refreshInterval: 30000 }
);
const [chartConfig, setChartConfig] = useState<ChartConfig>(
element.chartConfig || {}
);
const [queryResult, setQueryResult] = useState<QueryResult | null>(null);
const [activeTab, setActiveTab] = useState<'query' | 'chart'>('query');
// 데이터 소스 변경 처리
const handleDataSourceChange = useCallback((newDataSource: ChartDataSource) => {
setDataSource(newDataSource);
}, []);
// 차트 설정 변경 처리
const handleChartConfigChange = useCallback((newConfig: ChartConfig) => {
setChartConfig(newConfig);
}, []);
// 쿼리 테스트 결과 처리
const handleQueryTest = useCallback((result: QueryResult) => {
setQueryResult(result);
// 쿼리 결과가 나오면 자동으로 차트 설정 탭으로 이동
if (result.rows.length > 0) {
setActiveTab('chart');
}
}, []);
// 저장 처리
const handleSave = useCallback(() => {
const updatedElement: DashboardElement = {
...element,
dataSource,
chartConfig,
};
onSave(updatedElement);
onClose();
}, [element, dataSource, chartConfig, onSave, onClose]);
// 모달이 열려있지 않으면 렌더링하지 않음
if (!isOpen) return null;
return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg shadow-xl w-full max-w-4xl h-[80vh] flex flex-col">
{/* 모달 헤더 */}
<div className="flex justify-between items-center p-6 border-b border-gray-200">
<div>
<h2 className="text-xl font-semibold text-gray-800">
{element.title}
</h2>
<p className="text-sm text-muted-foreground mt-1">
</p>
</div>
<button
onClick={onClose}
className="text-gray-400 hover:text-muted-foreground text-2xl"
>
×
</button>
</div>
{/* 탭 네비게이션 */}
<div className="flex border-b border-gray-200">
<button
onClick={() => setActiveTab('query')}
className={`
px-6 py-3 text-sm font-medium border-b-2 transition-colors
${activeTab === 'query'
? 'border-primary text-primary bg-accent'
: 'border-transparent text-gray-500 hover:text-gray-700'}
`}
>
📝 &
</button>
<button
onClick={() => setActiveTab('chart')}
className={`
px-6 py-3 text-sm font-medium border-b-2 transition-colors
${activeTab === 'chart'
? 'border-primary text-primary bg-accent'
: 'border-transparent text-gray-500 hover:text-gray-700'}
`}
>
📊
{queryResult && (
<span className="ml-2 px-2 py-0.5 bg-green-100 text-green-800 text-xs rounded-full">
{queryResult.rows.length}
</span>
)}
</button>
</div>
{/* 탭 내용 */}
<div className="flex-1 overflow-auto p-6">
{activeTab === 'query' && (
<QueryEditor
dataSource={dataSource}
onDataSourceChange={handleDataSourceChange}
onQueryTest={handleQueryTest}
/>
)}
{activeTab === 'chart' && (
<ChartConfigPanel
config={chartConfig}
queryResult={queryResult}
onConfigChange={handleChartConfigChange}
/>
)}
</div>
{/* 모달 푸터 */}
<div className="flex justify-between items-center p-6 border-t border-gray-200">
<div className="text-sm text-gray-500">
{dataSource.query && (
<>
💾 : {dataSource.query.length > 50
? `${dataSource.query.substring(0, 50)}...`
: dataSource.query}
</>
)}
</div>
<div className="flex gap-3">
<button
onClick={onClose}
className="px-4 py-2 text-muted-foreground border border-gray-300 rounded-lg hover:bg-gray-50"
>
</button>
<button
onClick={handleSave}
disabled={!dataSource.query || (!chartConfig.xAxis || !chartConfig.yAxis)}
className="
px-4 py-2 bg-accent0 text-white rounded-lg
hover:bg-blue-600 disabled:bg-gray-300 disabled:cursor-not-allowed
"
>
</button>
</div>
</div>
</div>
</div>
);
}