"use client"; import { useState, useEffect } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Loader2, Plus, Trash2, GripVertical } from "lucide-react"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Separator } from "@/components/ui/separator"; // 계층 레벨 설정 인터페이스 export interface HierarchyLevel { level: number; name: string; tableName: string; keyColumn: string; nameColumn: string; parentKeyColumn: string; typeColumn?: string; objectTypes: string[]; } // 전체 계층 구조 설정 export interface HierarchyConfig { warehouseKey: string; // 이 레이아웃이 속한 창고 키 (예: "DY99") warehouse?: { tableName: string; // 창고 테이블명 (예: "MWARMA") keyColumn: string; nameColumn: string; }; levels: HierarchyLevel[]; material?: { tableName: string; keyColumn: string; locationKeyColumn: string; layerColumn?: string; quantityColumn?: string; displayColumns?: Array<{ column: string; label: string }>; // 우측 패널에 표시할 컬럼들 (컬럼명 + 표시명) }; } interface HierarchyConfigPanelProps { externalDbConnectionId: number | null; hierarchyConfig: HierarchyConfig | null; onHierarchyConfigChange: (config: HierarchyConfig) => void; availableTables: string[]; onLoadTables: () => Promise; onLoadColumns: (tableName: string) => Promise; } export default function HierarchyConfigPanel({ externalDbConnectionId, hierarchyConfig, onHierarchyConfigChange, availableTables, onLoadTables, onLoadColumns, }: HierarchyConfigPanelProps) { const [localConfig, setLocalConfig] = useState( hierarchyConfig || { warehouseKey: "", levels: [], }, ); const [loadingColumns, setLoadingColumns] = useState(false); const [columnsCache, setColumnsCache] = useState<{ [tableName: string]: string[] }>({}); // 외부에서 변경된 경우 동기화 useEffect(() => { if (hierarchyConfig) { setLocalConfig(hierarchyConfig); } }, [hierarchyConfig]); // 테이블 선택 시 컬럼 로드 const handleTableChange = async (tableName: string, type: "warehouse" | "material" | number) => { if (columnsCache[tableName]) return; // 이미 로드된 경우 스킵 setLoadingColumns(true); try { const columns = await onLoadColumns(tableName); setColumnsCache((prev) => ({ ...prev, [tableName]: columns })); } catch (error) { console.error("컬럼 로드 실패:", error); } finally { setLoadingColumns(false); } }; // 창고 키 변경 (제거됨 - 상위 컴포넌트에서 처리) // 레벨 추가 const handleAddLevel = () => { const maxLevel = localConfig.levels.length > 0 ? Math.max(...localConfig.levels.map((l) => l.level)) : 0; const newLevel: HierarchyLevel = { level: maxLevel + 1, name: `레벨 ${maxLevel + 1}`, tableName: "", keyColumn: "", nameColumn: "", parentKeyColumn: "", objectTypes: [], }; const newConfig = { ...localConfig, levels: [...localConfig.levels, newLevel], }; setLocalConfig(newConfig); // onHierarchyConfigChange(newConfig); // 즉시 전달하지 않음 }; // 레벨 삭제 const handleRemoveLevel = (level: number) => { const newConfig = { ...localConfig, levels: localConfig.levels.filter((l) => l.level !== level), }; setLocalConfig(newConfig); // onHierarchyConfigChange(newConfig); // 즉시 전달하지 않음 }; // 레벨 설정 변경 const handleLevelChange = (level: number, field: keyof HierarchyLevel, value: any) => { const newConfig = { ...localConfig, levels: localConfig.levels.map((l) => (l.level === level ? { ...l, [field]: value } : l)), }; setLocalConfig(newConfig); // onHierarchyConfigChange(newConfig); // 즉시 전달하지 않음 }; // 자재 설정 변경 const handleMaterialChange = (field: keyof NonNullable, value: string) => { const newConfig = { ...localConfig, material: { ...localConfig.material, [field]: value, } as NonNullable, }; setLocalConfig(newConfig); // onHierarchyConfigChange(newConfig); // 즉시 전달하지 않음 }; // 창고 설정 변경 const handleWarehouseChange = (field: keyof NonNullable, value: string) => { const newWarehouse = { ...localConfig.warehouse, [field]: value, } as NonNullable; setLocalConfig({ ...localConfig, warehouse: newWarehouse }); }; // 설정 적용 const handleApplyConfig = () => { onHierarchyConfigChange(localConfig); }; if (!externalDbConnectionId) { return
외부 DB를 먼저 선택하세요
; } return (
{/* 창고 설정 */} 창고 설정 창고 테이블 및 컬럼 매핑 {/* 창고 테이블 선택 */}
{/* 창고 컬럼 매핑 */} {localConfig.warehouse?.tableName && columnsCache[localConfig.warehouse.tableName] && (
)}
{/* 계층 레벨 목록 */} 계층 레벨 영역, 하위 영역 등 {localConfig.levels.length === 0 && (
레벨을 추가하세요
)} {localConfig.levels.map((level) => (
handleLevelChange(level.level, "name", e.target.value)} className="h-7 w-32 text-xs" placeholder="레벨명" />
{level.tableName && columnsCache[level.tableName] && ( <>
)}
))}
{/* 자재 설정 */} 자재 설정 최하위 레벨의 데이터
{localConfig.material?.tableName && columnsCache[localConfig.material.tableName] && ( <>
{/* 표시 컬럼 선택 */}

자재 클릭 시 표시할 정보를 선택하고 라벨을 입력하세요

{columnsCache[localConfig.material.tableName].map((col) => { const displayItem = localConfig.material?.displayColumns?.find((d) => d.column === col); const isSelected = !!displayItem; return (
{ const currentDisplay = localConfig.material?.displayColumns || []; const newDisplay = e.target.checked ? [...currentDisplay, { column: col, label: col }] : currentDisplay.filter((d) => d.column !== col); handleMaterialChange("displayColumns", newDisplay); }} className="h-3 w-3 shrink-0" /> {col} {isSelected && ( { const currentDisplay = localConfig.material?.displayColumns || []; const newDisplay = currentDisplay.map((d) => d.column === col ? { ...d, label: e.target.value } : d, ); handleMaterialChange("displayColumns", newDisplay); }} placeholder="표시명 입력..." className="h-6 flex-1 text-[10px]" /> )}
); })}
)}
{/* 적용 버튼 */}
); }