'use client' import * as React from 'react' import type { User } from '@admin/types/auth' import type { ColumnDef } from '@tanstack/react-table' import { authClient } from '@admin/auth/client' import { DataGrid, DataGridBody, DataGridCell, DataGridHead, DataGridHeader, DataGridRow } from '@admin/components/shared/data-table/data-grid' import { DataTablePagination } from '@admin/components/shared/data-table/data-table-pagination' import { useTableUtils } from '@admin/hooks/use-table-utils' import { useUsers } from '@admin/hooks/use-users' import { cn } from '@admin/utils/shared/cn' import { getUsersPage } from '@admin/utils/user/get-users-page' import { flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table' import { GripVertical } from 'lucide-react' import { parseAsInteger, parseAsString, useQueryStates } from 'nuqs' interface UsersTableProps extends React.HTMLAttributes { columns: ColumnDef[] role?: string search?: string status?: string } export function UsersTable({ columns, role, search, status, className }: UsersTableProps) { const defaultPageSize = 20 const { data: session } = authClient.useSession() const { data, error, isPending } = useUsers() const [{ dir: sortDir, page: pageIndex, size: pageSize, sort: sortField }, setTableQuery] = useQueryStates({ dir: parseAsString.withDefault(''), page: parseAsInteger.withDefault(0), size: parseAsInteger.withDefault(defaultPageSize), sort: parseAsString.withDefault('') }) const safePageIndex = Number.isFinite(pageIndex) && pageIndex > 0 ? pageIndex : 0 const safePageSize = pageSize === -1 || (Number.isFinite(pageSize) && pageSize > 0) ? pageSize : defaultPageSize const tablePage = React.useMemo( () => getUsersPage(data?.users ?? [], { pageIndex: safePageIndex, pageSize: safePageSize, role, search, sortDir: sortDir === 'desc' ? 'desc' : sortDir === 'asc' ? 'asc' : undefined, sortField: sortField || undefined, status }), [data?.users, role, safePageIndex, safePageSize, search, sortDir, sortField, status] ) const tableData = tablePage.users const totalRows = tablePage.total const effectivePageSize = safePageSize === -1 ? totalRows : safePageSize const pageCount = effectivePageSize > 0 ? Math.ceil(totalRows / effectivePageSize) : 1 const shouldShowPagination = totalRows > defaultPageSize const { columnSizing, handleColumnSizingChange, handlePaginationChange, handleSortingChange, hoveredColumnId, registerTable, resetColumnSizingToContainer, sorting, setHoveredColumnId, tableContainerRef } = useTableUtils({ pageIndex: safePageIndex, pageSize: effectivePageSize, setPageIndex: (nextPageIndex) => setTableQuery({ page: nextPageIndex }), setSortingParams: ({ pageIndex: nextPageIndex, sortDir: nextSortDir, sortField: nextSortField }) => setTableQuery({ dir: nextSortDir, page: nextPageIndex, sort: nextSortField }), sortDir, sortField }) const table = useReactTable({ data: tableData, columns, columnResizeMode: 'onChange', defaultColumn: { minSize: 48, size: 220 }, getCoreRowModel: getCoreRowModel(), manualPagination: true, manualSorting: true, pageCount, rowCount: totalRows, onSortingChange: handleSortingChange, onColumnSizingChange: handleColumnSizingChange, onPaginationChange: handlePaginationChange, meta: { currentUser: session?.user ? { id: session.user.id, email: session.user.email, name: session.user.name, image: session.user.image, role: (session.user as { role?: string }).role || 'member' } : null }, state: { sorting, columnSizing, pagination: { pageIndex: safePageIndex, pageSize: effectivePageSize } } }) registerTable(table) const gridTemplateColumns = table .getVisibleLeafColumns() .map((column) => `${column.getSize()}px`) .join(' ') return (
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header, headerIndex) => { const resizeLabel = typeof header.column.columnDef.header === 'string' ? header.column.columnDef.header : header.column.id const nextHeader = headerGroup.headers[headerIndex + 1] const canResizeColumn = header.column.getCanResize() && nextHeader?.column.getCanResize() === true return ( setHoveredColumnId(header.column.id)} onMouseLeave={() => setHoveredColumnId((current) => current === header.column.id ? null : current ) } > {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())} {canResizeColumn ? ( ) : null} ) })} ))} {isPending ? (
Loading users…
) : error ? (
Failed to load users. Refresh to try again.
) : table.getRowModel().rows?.length ? ( table.getRowModel().rows.map((row) => ( {row.getVisibleCells().map((cell) => ( setHoveredColumnId(cell.column.id)} onMouseLeave={() => setHoveredColumnId((current) => (current === cell.column.id ? null : current)) } className="px-4" > {flexRender(cell.column.columnDef.cell, cell.getContext())} ))} )) ) : ( No users found. )}
{shouldShowPagination ? ( setTableQuery({ page: nextPageIndex })} setPageSize={(nextPageSize) => setTableQuery({ page: 0, size: nextPageSize })} /> ) : null}
) }