diff options
Diffstat (limited to 'lib/dolce/table/drawing-list-table.tsx')
| -rw-r--r-- | lib/dolce/table/drawing-list-table.tsx | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/lib/dolce/table/drawing-list-table.tsx b/lib/dolce/table/drawing-list-table.tsx new file mode 100644 index 00000000..cc01f8ba --- /dev/null +++ b/lib/dolce/table/drawing-list-table.tsx @@ -0,0 +1,144 @@ +"use client"; + +import { + ColumnDef, + flexRender, + getCoreRowModel, + useReactTable, + getSortedRowModel, + SortingState, +} from "@tanstack/react-table"; +import { useState } from "react"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { ArrowUpDown, ArrowUp, ArrowDown } from "lucide-react"; + +interface DrawingListTableProps<TData, TValue> { + columns: ColumnDef<TData, TValue>[]; + data: TData[]; + onRowClick?: (row: TData) => void; + selectedRow?: TData; + getRowId?: (row: TData) => string; +} + +export function DrawingListTable<TData, TValue>({ + columns, + data, + onRowClick, + selectedRow, + getRowId, +}: DrawingListTableProps<TData, TValue>) { + const [sorting, setSorting] = useState<SortingState>([]); + + const table = useReactTable({ + data, + columns, + getCoreRowModel: getCoreRowModel(), + getSortedRowModel: getSortedRowModel(), + onSortingChange: setSorting, + state: { + sorting, + }, + }); + + // 행이 선택되었는지 확인하는 함수 + const isRowSelected = (row: TData): boolean => { + if (!selectedRow || !getRowId) return false; + return getRowId(row) === getRowId(selectedRow); + }; + + return ( + <div className="rounded-md border overflow-x-auto max-w-full max-h-[600px] overflow-y-auto"> + <Table className="min-w-max"> + <TableHeader className="sticky top-0 z-10 bg-background"> + {table.getHeaderGroups().map((headerGroup) => ( + <TableRow key={headerGroup.id}> + {headerGroup.headers.map((header) => { + const isSorted = header.column.getIsSorted(); + const canSort = header.column.getCanSort(); + + return ( + <TableHead + key={header.id} + style={{ minWidth: header.column.columnDef.minSize }} + className="bg-background" + > + {header.isPlaceholder ? null : ( + <div + className={`flex items-center gap-2 ${ + canSort ? "cursor-pointer select-none hover:text-primary" : "" + }`} + onClick={ + canSort + ? header.column.getToggleSortingHandler() + : undefined + } + > + {flexRender( + header.column.columnDef.header, + header.getContext() + )} + {canSort && ( + <span className="text-muted-foreground"> + {isSorted === "asc" ? ( + <ArrowUp className="h-4 w-4" /> + ) : isSorted === "desc" ? ( + <ArrowDown className="h-4 w-4" /> + ) : ( + <ArrowUpDown className="h-4 w-4 opacity-50" /> + )} + </span> + )} + </div> + )} + </TableHead> + ); + })} + </TableRow> + ))} + </TableHeader> + <TableBody> + {table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map((row) => { + const isSelected = isRowSelected(row.original); + return ( + <TableRow + key={row.id} + data-state={row.getIsSelected() && "selected"} + onClick={() => onRowClick?.(row.original)} + className={`cursor-pointer transition-colors ${ + isSelected + ? "bg-accent hover:bg-accent" + : "hover:bg-muted/50" + }`} + > + {row.getVisibleCells().map((cell) => ( + <TableCell + key={cell.id} + style={{ minWidth: cell.column.columnDef.minSize }} + > + {flexRender(cell.column.columnDef.cell, cell.getContext())} + </TableCell> + ))} + </TableRow> + ); + }) + ) : ( + <TableRow> + <TableCell colSpan={columns.length} className="h-24 text-center"> + 데이터가 없습니다. + </TableCell> + </TableRow> + )} + </TableBody> + </Table> + </div> + ); +} + |
