"use client"; import { ColumnDef, flexRender, getCoreRowModel, useReactTable, getSortedRowModel, SortingState, getPaginationRowModel, } from "@tanstack/react-table"; import { useState } from "react"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Button } from "@/components/ui/button"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { ArrowUpDown, ArrowUp, ArrowDown, ChevronLeft, ChevronRight } from "lucide-react"; // 도면 데이터의 기본 인터페이스 interface DrawingData { RegisterGroupId?: string | number | null; DrawingNo?: string | null; Discipline?: string | null; CreateDt?: string | Date | null; } interface DrawingListTableV2Props { columns: ColumnDef[]; data: TData[]; onRowClick?: (row: TData) => void; selectedRow?: TData; getRowId?: (row: TData) => string; maxHeight?: string; // e.g., "45vh" minHeight?: string; // e.g., "400px" defaultPageSize?: number; } export function DrawingListTableV2({ columns, data, onRowClick, selectedRow, getRowId, maxHeight, minHeight = "400px", defaultPageSize, }: DrawingListTableV2Props) { const [sorting, setSorting] = useState([]); const [pageIndex, setPageIndex] = useState(0); // defaultPageSize가 없으면 전체 데이터 길이를 사용 const [pageSize, setPageSize] = useState(defaultPageSize ?? data.length); // 기본 getRowId 함수: RegisterGroupId + DrawingNo + Discipline + CreateDt 조합 const defaultGetRowId = (row: TData): string => { const registerId = row.RegisterGroupId || ''; const drawingNo = row.DrawingNo || ''; const discipline = row.Discipline || ''; const createDt = row.CreateDt ? (row.CreateDt instanceof Date ? row.CreateDt.toISOString() : String(row.CreateDt)) : ''; return `${registerId}-${drawingNo}-${discipline}-${createDt}`; }; const rowIdGetter = getRowId || defaultGetRowId; const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), getPaginationRowModel: getPaginationRowModel(), onSortingChange: setSorting, onPaginationChange: (updater) => { if (typeof updater === 'function') { const newState = updater({ pageIndex, pageSize }); setPageIndex(newState.pageIndex); setPageSize(newState.pageSize); } }, state: { sorting, pagination: { pageIndex, pageSize, }, }, }); // 행이 선택되었는지 확인하는 함수 const isRowSelected = (row: TData): boolean => { if (!selectedRow) return false; return rowIdGetter(row) === rowIdGetter(selectedRow); }; const handlePageSizeChange = (value: string) => { const newSize = value === "all" ? data.length : parseInt(value, 10); setPageSize(newSize); setPageIndex(0); }; return (
{/* 테이블 영역 */}
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => { const isSorted = header.column.getIsSorted(); const canSort = header.column.getCanSort(); return ( {header.isPlaceholder ? null : (
{flexRender( header.column.columnDef.header, header.getContext() )} {canSort && ( {isSorted === "asc" ? ( ) : isSorted === "desc" ? ( ) : ( )} )}
)}
); })}
))}
{table.getRowModel().rows?.length ? ( table.getRowModel().rows.map((row) => { const isSelected = isRowSelected(row.original); return ( onRowClick?.(row.original)} className={`cursor-pointer transition-colors ${ isSelected ? "bg-accent hover:bg-accent" : "hover:bg-muted/50" }`} > {row.getVisibleCells().map((cell) => ( {flexRender(cell.column.columnDef.cell, cell.getContext())} ))} ); }) ) : (
No Data.
)}
{/* 페이지네이션 컨트롤 - 항상 렌더링하여 높이 일관성 유지 */}
{data.length > 0 ? ( <>
Rows per page:
{table.getState().pagination.pageIndex * pageSize + 1}- {Math.min( (table.getState().pagination.pageIndex + 1) * pageSize, data.length )}{" "} / {data.length}
) : (
Placeholder for consistent height
)}
); }