import React, { useState, useEffect } from "react"; import { useTableOptions } from "@/contexts/TableOptionsContext"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Checkbox } from "@/components/ui/checkbox"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { ScrollArea } from "@/components/ui/scroll-area"; import { GripVertical, Eye, EyeOff, Lock } from "lucide-react"; import { ColumnVisibility } from "@/types/table-options"; interface Props { isOpen: boolean; onClose: () => void; } export const ColumnVisibilityPanel: React.FC = ({ isOpen, onClose, }) => { const { getTable, selectedTableId } = useTableOptions(); const table = selectedTableId ? getTable(selectedTableId) : undefined; const [localColumns, setLocalColumns] = useState([]); const [draggedIndex, setDraggedIndex] = useState(null); const [frozenColumnCount, setFrozenColumnCount] = useState(0); // 테이블 정보 로드 useEffect(() => { if (table) { setLocalColumns( table.columns.map((col) => ({ columnName: col.columnName, visible: col.visible, width: col.width, order: 0, })) ); // 현재 틀고정 컬럼 수 로드 setFrozenColumnCount(table.frozenColumnCount ?? 0); } }, [table]); const handleVisibilityChange = (columnName: string, visible: boolean) => { setLocalColumns((prev) => prev.map((col) => col.columnName === columnName ? { ...col, visible } : col ) ); }; const handleWidthChange = (columnName: string, width: number) => { setLocalColumns((prev) => prev.map((col) => col.columnName === columnName ? { ...col, width } : col ) ); }; const moveColumn = (fromIndex: number, toIndex: number) => { const newColumns = [...localColumns]; const [movedItem] = newColumns.splice(fromIndex, 1); newColumns.splice(toIndex, 0, movedItem); setLocalColumns(newColumns); }; const handleDragStart = (index: number) => { setDraggedIndex(index); }; const handleDragOver = (e: React.DragEvent, index: number) => { e.preventDefault(); if (draggedIndex === null || draggedIndex === index) return; moveColumn(draggedIndex, index); setDraggedIndex(index); }; const handleDragEnd = () => { setDraggedIndex(null); }; const handleApply = () => { table?.onColumnVisibilityChange(localColumns); // 컬럼 순서 변경 콜백 호출 if (table?.onColumnOrderChange) { const newOrder = localColumns .map((col) => col.columnName) .filter((name) => name !== "__checkbox__"); table.onColumnOrderChange(newOrder); } // 틀고정 컬럼 수 변경 콜백 호출 (현재 컬럼 상태도 함께 전달) if (table?.onFrozenColumnCountChange) { const updatedColumns = localColumns.map((col) => ({ columnName: col.columnName, visible: col.visible, })); table.onFrozenColumnCountChange(frozenColumnCount, updatedColumns); } onClose(); }; const handleReset = () => { if (table) { setLocalColumns( table.columns.map((col) => ({ columnName: col.columnName, visible: true, width: 150, order: 0, })) ); setFrozenColumnCount(0); } }; // 틀고정 컬럼 수 변경 핸들러 const handleFrozenColumnCountChange = (value: string) => { const count = parseInt(value) || 0; // 최대값은 표시 가능한 컬럼 수 const maxCount = localColumns.filter((col) => col.visible).length; setFrozenColumnCount(Math.min(Math.max(0, count), maxCount)); }; const visibleCount = localColumns.filter((col) => col.visible).length; return ( 테이블 옵션 컬럼 표시/숨기기, 순서 변경, 너비 등을 설정할 수 있습니다. 모든 테두리를 드래그하여 크기를 조정할 수 있습니다.
{/* 상태 표시 및 틀고정 설정 */}
{visibleCount}/{localColumns.length}개 컬럼 표시 중
{/* 틀고정 설정 */}
handleFrozenColumnCountChange(e.target.value)} className="h-7 w-16 text-xs sm:h-8 sm:w-20 sm:text-sm" min={0} max={visibleCount} placeholder="0" /> 개 컬럼
{/* 컬럼 리스트 */}
{localColumns.map((col, index) => { const columnMeta = table?.columns.find( (c) => c.columnName === col.columnName ); // 표시 가능한 컬럼 중 몇 번째인지 계산 (틀고정 표시용) const visibleIndex = localColumns .slice(0, index + 1) .filter((c) => c.visible).length; const isFrozen = col.visible && visibleIndex <= frozenColumnCount; return (
handleDragStart(index)} onDragOver={(e) => handleDragOver(e, index)} onDragEnd={handleDragEnd} className={`flex items-center gap-3 rounded-lg border p-3 transition-colors cursor-move ${ isFrozen ? "bg-blue-50 border-blue-200 dark:bg-blue-950/30 dark:border-blue-800" : "bg-background hover:bg-muted/50" }`} > {/* 드래그 핸들 */} {/* 체크박스 */} handleVisibilityChange( col.columnName, checked as boolean ) } /> {/* 가시성/틀고정 아이콘 */} {isFrozen ? ( ) : col.visible ? ( ) : ( )} {/* 컬럼명 */}
{columnMeta?.columnLabel} {isFrozen && ( (고정) )}
{col.columnName}
{/* 너비 설정 */}
handleWidthChange( col.columnName, parseInt(e.target.value) || 150 ) } className="h-7 w-16 text-xs sm:h-8 sm:w-20 sm:text-sm" min={50} max={500} />
); })}
); };