"use client"; import React, { useState, useEffect } from "react"; import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Checkbox } from "@/components/ui/checkbox"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Separator } from "@/components/ui/separator"; import { Settings, Layout, ArrowRight, Database, Loader2, Check, ChevronsUpDown, Plus, Trash2, Link2 } from "lucide-react"; import { screenApi } from "@/lib/api/screen"; import { getTableColumns } from "@/lib/api/tableManagement"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { cn } from "@/lib/utils"; import type { ParentDataMapping } from "@/contexts/SplitPanelContext"; interface ScreenSplitPanelConfigPanelProps { config: any; onChange: (newConfig: any) => void; } export function ScreenSplitPanelConfigPanel({ config = {}, onChange }: ScreenSplitPanelConfigPanelProps) { // 화면 목록 상태 const [screens, setScreens] = useState([]); const [isLoadingScreens, setIsLoadingScreens] = useState(true); // Combobox 상태 const [leftOpen, setLeftOpen] = useState(false); const [rightOpen, setRightOpen] = useState(false); // 좌측 화면의 테이블 컬럼 목록 const [leftScreenColumns, setLeftScreenColumns] = useState>([]); const [isLoadingColumns, setIsLoadingColumns] = useState(false); const [localConfig, setLocalConfig] = useState({ screenId: config.screenId || 0, leftScreenId: config.leftScreenId || 0, rightScreenId: config.rightScreenId || 0, splitRatio: config.splitRatio || 50, resizable: config.resizable ?? true, buttonLabel: config.buttonLabel || "데이터 전달", buttonPosition: config.buttonPosition || "center", parentDataMapping: config.parentDataMapping || [] as ParentDataMapping[], ...config, }); // config prop이 변경되면 localConfig 동기화 useEffect(() => { console.log("🔄 [ScreenSplitPanelConfigPanel] config prop 변경 감지:", config); setLocalConfig({ screenId: config.screenId || 0, leftScreenId: config.leftScreenId || 0, rightScreenId: config.rightScreenId || 0, splitRatio: config.splitRatio || 50, resizable: config.resizable ?? true, buttonLabel: config.buttonLabel || "데이터 전달", buttonPosition: config.buttonPosition || "center", parentDataMapping: config.parentDataMapping || [], ...config, }); }, [config]); // 좌측 화면이 변경되면 해당 화면의 테이블 컬럼 로드 useEffect(() => { const loadLeftScreenColumns = async () => { if (!localConfig.leftScreenId) { setLeftScreenColumns([]); return; } try { setIsLoadingColumns(true); // 좌측 화면 정보 조회 const screenData = await screenApi.getScreen(localConfig.leftScreenId); if (!screenData?.tableName) { console.warn("좌측 화면에 테이블이 설정되지 않았습니다."); setLeftScreenColumns([]); return; } // 테이블 컬럼 조회 const columnsResponse = await getTableColumns(screenData.tableName); if (columnsResponse.success && columnsResponse.data?.columns) { const columns = columnsResponse.data.columns.map((col: any) => ({ columnName: col.column_name || col.columnName, columnLabel: col.column_label || col.columnLabel || col.column_name || col.columnName, })); setLeftScreenColumns(columns); console.log("📋 좌측 화면 컬럼 로드 완료:", columns.length); } } catch (error) { console.error("좌측 화면 컬럼 로드 실패:", error); setLeftScreenColumns([]); } finally { setIsLoadingColumns(false); } }; loadLeftScreenColumns(); }, [localConfig.leftScreenId]); // 화면 목록 로드 useEffect(() => { const loadScreens = async () => { try { setIsLoadingScreens(true); const response = await screenApi.getScreens({ page: 1, size: 1000 }); if (response.data) { setScreens(response.data); } } catch (error) { console.error("화면 목록 로드 실패:", error); } finally { setIsLoadingScreens(false); } }; loadScreens(); }, []); const updateConfig = (key: string, value: any) => { const newConfig = { ...localConfig, [key]: value, }; setLocalConfig(newConfig); console.log("📝 [ScreenSplitPanelConfigPanel] 설정 변경:", { key, value, newConfig, hasOnChange: !!onChange, }); // 변경 즉시 부모에게 전달 if (onChange) { onChange(newConfig); } }; // 부모 데이터 매핑 추가 const addParentDataMapping = () => { const newMapping: ParentDataMapping = { sourceColumn: "", targetColumn: "", }; const newMappings = [...(localConfig.parentDataMapping || []), newMapping]; updateConfig("parentDataMapping", newMappings); }; // 부모 데이터 매핑 수정 const updateParentDataMapping = (index: number, field: keyof ParentDataMapping, value: string) => { const newMappings = [...(localConfig.parentDataMapping || [])]; newMappings[index] = { ...newMappings[index], [field]: value, }; updateConfig("parentDataMapping", newMappings); }; // 부모 데이터 매핑 삭제 const removeParentDataMapping = (index: number) => { const newMappings = (localConfig.parentDataMapping || []).filter((_: any, i: number) => i !== index); updateConfig("parentDataMapping", newMappings); }; return (
레이아웃 화면 설정 데이터 전달 {/* 레이아웃 탭 */} 분할 비율 좌측과 우측 패널의 너비 비율을 설정합니다
{localConfig.splitRatio}%
updateConfig("splitRatio", parseInt(e.target.value))} className="h-2" />
20% 50% 80%

사용자가 패널 크기를 조절할 수 있습니다

updateConfig("resizable", checked)} />
{/* 화면 설정 탭 */} 임베드할 화면 선택 좌측과 우측에 표시할 화면을 선택합니다 {isLoadingScreens ? (
화면 목록 로딩 중...
) : ( <>
화면을 찾을 수 없습니다. {screens.map((screen) => ( { updateConfig("leftScreenId", screen.screenId); setLeftOpen(false); }} className="text-xs" >
{screen.screenName} {screen.screenCode}
))}

데이터를 선택할 소스 화면

화면을 찾을 수 없습니다. {screens.map((screen) => ( { updateConfig("rightScreenId", screen.screenId); setRightOpen(false); }} className="text-xs" >
{screen.screenName} {screen.screenCode}
))}

데이터를 받을 타겟 화면

데이터 전달 방법: 좌측 화면에 테이블과 버튼을 배치하고, 버튼의 액션을 "transferData"로 설정하세요.
버튼 설정에서 소스 컴포넌트(테이블), 타겟 화면, 필드 매핑을 지정할 수 있습니다.

)}
{/* 데이터 전달 탭 */} 부모 데이터 자동 전달 좌측 화면에서 행을 선택하면, 우측 화면의 추가/저장 시 지정된 컬럼 값이 자동으로 포함됩니다. {!localConfig.leftScreenId ? (

먼저 "화면 설정" 탭에서 좌측 화면을 선택하세요.

) : isLoadingColumns ? (
컬럼 정보 로딩 중...
) : leftScreenColumns.length === 0 ? (

좌측 화면에 테이블이 설정되지 않았거나 컬럼 정보를 불러올 수 없습니다.

) : ( <> {/* 매핑 목록 */}
{(localConfig.parentDataMapping || []).map((mapping: ParentDataMapping, index: number) => (
updateParentDataMapping(index, "targetColumn", e.target.value)} placeholder="저장할 컬럼명" className="h-8 text-xs" />
))}
{/* 매핑 추가 버튼 */} {/* 안내 메시지 */}

사용 예시:
좌측: 설비 목록 (equipment_mng)
우측: 점검항목 추가 화면

매핑 설정:
- 소스: equipment_code → 타겟: equipment_code

좌측에서 설비를 선택하고 우측에서 점검항목을 추가하면, 선택한 설비의 equipment_code가 자동으로 저장됩니다.

)}
{/* 설정 요약 */} 현재 설정
좌측 화면: {localConfig.leftScreenId ? screens.find((s) => s.screenId === localConfig.leftScreenId)?.screenName || `ID: ${localConfig.leftScreenId}` : "미설정"}
우측 화면: {localConfig.rightScreenId ? screens.find((s) => s.screenId === localConfig.rightScreenId)?.screenName || `ID: ${localConfig.rightScreenId}` : "미설정"}
분할 비율: {localConfig.splitRatio}% / {100 - localConfig.splitRatio}%
크기 조절: {localConfig.resizable ? "가능" : "불가능"}
데이터 매핑: {(localConfig.parentDataMapping || []).length > 0 ? `${localConfig.parentDataMapping.length}개 설정` : "미설정"}
); }