"use client"; import React, { useState, useEffect } from "react"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Checkbox } from "@/components/ui/checkbox"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Button } from "@/components/ui/button"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Separator } from "@/components/ui/separator"; import { TableListConfig, ColumnConfig } from "./types"; import { Plus, Trash2, ArrowUp, ArrowDown, Eye, EyeOff, Settings, Columns, Filter, Palette, MousePointer, } from "lucide-react"; export interface TableListConfigPanelProps { config: TableListConfig; onChange: (config: Partial) => void; screenTableName?: string; // 화면에 연결된 테이블명 tableColumns?: any[]; // 테이블 컬럼 정보 } /** * TableList 설정 패널 * 컴포넌트의 설정값들을 편집할 수 있는 UI 제공 */ export const TableListConfigPanel: React.FC = ({ config, onChange, screenTableName, tableColumns, }) => { console.log("🔍 TableListConfigPanel props:", { config, screenTableName, tableColumns }); const [availableTables, setAvailableTables] = useState>([]); const [loadingTables, setLoadingTables] = useState(false); const [availableColumns, setAvailableColumns] = useState< Array<{ columnName: string; dataType: string; label?: string }> >([]); // 화면 테이블명이 있으면 자동으로 설정 useEffect(() => { if (screenTableName && (!config.selectedTable || config.selectedTable !== screenTableName)) { console.log("🔄 화면 테이블명 자동 설정:", screenTableName); onChange({ selectedTable: screenTableName }); } }, [screenTableName, config.selectedTable, onChange]); // 테이블 목록 가져오기 useEffect(() => { const fetchTables = async () => { setLoadingTables(true); try { const response = await fetch("/api/tables"); if (response.ok) { const result = await response.json(); if (result.success && result.data) { setAvailableTables( result.data.map((table: any) => ({ tableName: table.tableName, displayName: table.displayName || table.tableName, })), ); } } } catch (error) { console.error("테이블 목록 가져오기 실패:", error); } finally { setLoadingTables(false); } }; fetchTables(); }, []); // 선택된 테이블의 컬럼 목록 설정 (tableColumns prop 우선 사용) useEffect(() => { console.log("🔍 useEffect 실행됨 - tableColumns:", tableColumns, "length:", tableColumns?.length); if (tableColumns && tableColumns.length > 0) { // tableColumns prop이 있으면 사용 console.log("🔧 tableColumns prop 사용:", tableColumns); console.log("🔧 첫 번째 컬럼 상세:", tableColumns[0]); const mappedColumns = tableColumns.map((column: any) => ({ columnName: column.columnName || column.name, dataType: column.dataType || column.type || "text", label: column.label || column.displayName || column.columnLabel || column.columnName || column.name, })); console.log("🏷️ availableColumns 설정됨:", mappedColumns); console.log("🏷️ 첫 번째 mappedColumn:", mappedColumns[0]); setAvailableColumns(mappedColumns); } else if (config.selectedTable || screenTableName) { // API에서 컬럼 정보 가져오기 const fetchColumns = async () => { const tableName = config.selectedTable || screenTableName; if (!tableName) { setAvailableColumns([]); return; } console.log("🔧 API에서 컬럼 정보 가져오기:", tableName); try { const response = await fetch(`/api/tables/${tableName}/columns`); if (response.ok) { const result = await response.json(); if (result.success && result.data) { console.log("🔧 API 응답 컬럼 데이터:", result.data); setAvailableColumns( result.data.map((col: any) => ({ columnName: col.columnName, dataType: col.dataType, label: col.displayName || col.columnName, })), ); } } } catch (error) { console.error("컬럼 목록 가져오기 실패:", error); } }; fetchColumns(); } else { setAvailableColumns([]); } }, [config.selectedTable, screenTableName, tableColumns]); const handleChange = (key: keyof TableListConfig, value: any) => { onChange({ [key]: value }); }; const handleNestedChange = (parentKey: keyof TableListConfig, childKey: string, value: any) => { const parentValue = config[parentKey] as any; onChange({ [parentKey]: { ...parentValue, [childKey]: value, }, }); }; // 컬럼 추가 const addColumn = (columnName: string) => { const existingColumn = config.columns?.find((col) => col.columnName === columnName); if (existingColumn) return; // tableColumns에서 해당 컬럼의 라벨 정보 찾기 const columnInfo = tableColumns?.find((col: any) => (col.columnName || col.name) === columnName); // 라벨명 우선 사용, 없으면 컬럼명 사용 const displayName = columnInfo?.label || columnInfo?.displayName || columnName; const newColumn: ColumnConfig = { columnName, displayName, visible: true, sortable: true, searchable: true, align: "left", format: "text", order: config.columns?.length || 0, }; handleChange("columns", [...(config.columns || []), newColumn]); }; // 컬럼 제거 const removeColumn = (columnName: string) => { const updatedColumns = config.columns?.filter((col) => col.columnName !== columnName) || []; handleChange("columns", updatedColumns); }; // 컬럼 업데이트 const updateColumn = (columnName: string, updates: Partial) => { const updatedColumns = config.columns?.map((col) => (col.columnName === columnName ? { ...col, ...updates } : col)) || []; handleChange("columns", updatedColumns); }; // 컬럼 순서 변경 const moveColumn = (columnName: string, direction: "up" | "down") => { const columns = [...(config.columns || [])]; const index = columns.findIndex((col) => col.columnName === columnName); if (index === -1) return; const targetIndex = direction === "up" ? index - 1 : index + 1; if (targetIndex < 0 || targetIndex >= columns.length) return; [columns[index], columns[targetIndex]] = [columns[targetIndex], columns[index]]; // order 값 재정렬 columns.forEach((col, idx) => { col.order = idx; }); handleChange("columns", columns); }; return (
테이블 리스트 설정
기본 컬럼 필터 액션 스타일 {/* 기본 설정 탭 */} 연결된 테이블 화면에 연결된 테이블 정보가 자동으로 매핑됩니다
{screenTableName ? ( {screenTableName} ) : ( 테이블이 연결되지 않았습니다 )}
{screenTableName && (
화면 설정에서 자동으로 연결된 테이블입니다
)}
handleChange("title", e.target.value)} placeholder="테이블 제목 (선택사항)" />
표시 설정
handleChange("showHeader", checked)} />
handleChange("showFooter", checked)} />
handleChange("autoLoad", checked)} />
높이 설정
{config.height === "fixed" && (
handleChange("fixedHeight", parseInt(e.target.value) || 400)} min={200} max={1000} />
)}
페이지네이션
handleNestedChange("pagination", "enabled", checked)} />
{config.pagination?.enabled && ( <>
handleNestedChange("pagination", "showSizeSelector", checked)} />
handleNestedChange("pagination", "showPageInfo", checked)} />
)}
{/* 컬럼 설정 탭 */} {!screenTableName ? (

테이블이 연결되지 않았습니다.

화면에 테이블을 연결한 후 컬럼을 설정할 수 있습니다.

) : ( <> 컬럼 추가 - {screenTableName} {availableColumns.length > 0 ? `${availableColumns.length}개의 사용 가능한 컬럼에서 선택하세요` : "컬럼 정보를 불러오는 중..."} {availableColumns.length > 0 ? (
{availableColumns .filter((col) => !config.columns?.find((c) => c.columnName === col.columnName)) .map((column) => ( ))}
) : (

컬럼 정보를 불러오는 중입니다...

)}
)} {screenTableName && ( 컬럼 설정 선택된 컬럼들의 표시 옵션을 설정하세요
{config.columns?.map((column, index) => (
updateColumn(column.columnName, { visible: checked as boolean }) } /> {availableColumns.find((col) => col.columnName === column.columnName)?.label || column.displayName || column.columnName}
{column.visible && (
col.columnName === column.columnName)?.label || column.displayName || column.columnName } onChange={(e) => updateColumn(column.columnName, { displayName: e.target.value })} className="h-8" />
updateColumn(column.columnName, { width: e.target.value ? parseInt(e.target.value) : undefined, }) } placeholder="자동" className="h-8" />
updateColumn(column.columnName, { sortable: checked as boolean }) } />
updateColumn(column.columnName, { searchable: checked as boolean }) } />
)}
))}
)}
{/* 필터 설정 탭 */} 검색 및 필터
handleNestedChange("filter", "enabled", checked)} />
{config.filter?.enabled && ( <>
handleNestedChange("filter", "quickSearch", checked)} />
{config.filter?.quickSearch && (
handleNestedChange("filter", "showColumnSelector", checked)} />
)}
handleNestedChange("filter", "advancedFilter", checked)} />
)}
{/* 액션 설정 탭 */} 행 액션
handleNestedChange("actions", "showActions", checked)} />
handleNestedChange("actions", "bulkActions", checked)} />
{/* 스타일 설정 탭 */} 테이블 스타일
handleNestedChange("tableStyle", "alternateRows", checked)} />
handleNestedChange("tableStyle", "hoverEffect", checked)} />
handleChange("stickyHeader", checked)} />
); };