"use client"; /** * TableColumnPalette — 테이블 데이터 연결 탭의 컬럼 팔레트 * * 2단계 플로우: * 1. 체크박스로 사용할 컬럼을 중복 선택 * 2. 선택된 컬럼만 드래그 가능한 칩으로 표시 → 드롭 존에 배치 */ import React, { useState, useMemo, useEffect } from "react"; import { useDrag } from "react-dnd"; import { Columns, Loader2, ChevronDown, ChevronUp, X } from "lucide-react"; export const TABLE_COLUMN_DND_TYPE = "table-column"; export interface SchemaColumn { column_name: string; data_type: string; is_nullable: string; } // ─── 드래그 가능한 선택된 컬럼 칩 ──────────────────────────────────────────── interface DraggableColumnProps { column: SchemaColumn; placed?: boolean; onRemove?: () => void; } function DraggableColumn({ column, placed = false, onRemove }: DraggableColumnProps) { const [{ isDragging }, drag] = useDrag(() => ({ type: TABLE_COLUMN_DND_TYPE, item: { columnName: column.column_name, dataType: column.data_type }, canDrag: () => !placed, collect: (monitor) => ({ isDragging: monitor.isDragging(), }), }), [column, placed]); return (
{column.column_name} {placed ? ( 배치됨 ) : ( {column.data_type} )} {onRemove && ( )}
); } // ─── 메인 팔레트 ────────────────────────────────────────────────────────────── interface TableColumnPaletteProps { columns: SchemaColumn[]; loading?: boolean; maxSelectable?: number; placedColumns?: Set; onColumnRemove?: (columnName: string) => void; } export function TableColumnPalette({ columns, loading, maxSelectable = 0, placedColumns, onColumnRemove }: TableColumnPaletteProps) { const [selectedNames, setSelectedNames] = useState>(new Set()); const [listExpanded, setListExpanded] = useState(false); // 이미 배치된 컬럼을 선택 목록에 자동 포함 useEffect(() => { if (!placedColumns || placedColumns.size === 0) return; setSelectedNames((prev) => { const next = new Set(prev); let changed = false; placedColumns.forEach((name) => { if (!next.has(name)) { next.add(name); changed = true; } }); return changed ? next : prev; }); }, [placedColumns]); const isLimitReached = maxSelectable > 0 && selectedNames.size >= maxSelectable; const selectedColumns = useMemo( () => columns.filter((c) => selectedNames.has(c.column_name)), [columns, selectedNames], ); const toggleColumn = (name: string) => { setSelectedNames((prev) => { const next = new Set(prev); if (next.has(name)) { next.delete(name); } else { if (maxSelectable > 0 && next.size >= maxSelectable) return prev; next.add(name); } return next; }); }; return (
{/* Step 1: 컬럼 선택 */}
{listExpanded && (
{loading ? (
컬럼 로딩 중...
) : columns.length === 0 ? (

레이아웃 탭에서 데이터 소스를 먼저 선택하세요.

) : ( <> {maxSelectable > 0 && (
배치 가능 열 수: {maxSelectable}개
)}
{columns.map((col) => { const checked = selectedNames.has(col.column_name); const disabled = !checked && isLimitReached; return ( ); })}
)}
)}
{/* Step 2: 선택된 컬럼 드래그 영역 */} {selectedColumns.length > 0 && (
선택된 열 드래그하여 아래 표에 배치 ({selectedColumns.length}개)
{selectedColumns.map((col) => ( { setSelectedNames((prev) => { const next = new Set(prev); next.delete(col.column_name); return next; }); onColumnRemove?.(col.column_name); }} /> ))}
)}
); }