summaryrefslogtreecommitdiff
path: root/lib/dolce/table/drawing-list-table.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dolce/table/drawing-list-table.tsx')
-rw-r--r--lib/dolce/table/drawing-list-table.tsx144
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>
+ );
+}
+