111 lines
4.0 KiB
TypeScript
111 lines
4.0 KiB
TypeScript
import { useEffect } from 'react'
|
|
|
|
import { flexRender, type Table as ITable } from '@tanstack/react-table'
|
|
import { ChevronDown, ChevronRight } from 'lucide-react'
|
|
|
|
import {
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableHead,
|
|
TableHeader,
|
|
TableRow,
|
|
} from '@/components/ui/table.tsx'
|
|
import { cn } from '@/lib/utils.ts'
|
|
|
|
import { Loading } from './loading.tsx'
|
|
|
|
interface Props<TData> {
|
|
table: ITable<TData>
|
|
}
|
|
|
|
export function BaseTable<TData>({ table }: Props<TData>) {
|
|
const pageIndex = table.getState().pagination.pageIndex
|
|
const pageSize = table.getState().pagination.pageSize
|
|
const rowCount = table.options.rowCount
|
|
const currentPageRowsLength = table.getCoreRowModel().rows.length
|
|
const isFetching = table.options.meta?.isFetching
|
|
|
|
useEffect(() => {
|
|
if (pageIndex > 0 && currentPageRowsLength === 0 && rowCount) {
|
|
const lastPageIndex = Math.max(0, Math.ceil(rowCount / pageSize) - 1)
|
|
if (lastPageIndex !== pageIndex) {
|
|
table.setPageIndex(lastPageIndex)
|
|
table.setPagination((prev) => ({ ...prev, pageIndex: lastPageIndex }))
|
|
}
|
|
}
|
|
}, [pageIndex, currentPageRowsLength, rowCount, pageSize, table])
|
|
|
|
const isTree = !!table.options.getExpandedRowModel
|
|
|
|
return (
|
|
<Loading visible={isFetching}>
|
|
<div className='border border-border/80 rounded-md'>
|
|
<Table>
|
|
<TableHeader>
|
|
{table.getHeaderGroups().map((headerGroup) => (
|
|
<TableRow key={headerGroup.id} className='bg-muted/50'>
|
|
{headerGroup.headers.map((header) => (
|
|
<TableHead
|
|
key={header.id}
|
|
className={cn(header.column.columnDef.meta?.className ?? '')}
|
|
>
|
|
{header.isPlaceholder
|
|
? null
|
|
: flexRender(header.column.columnDef.header, header.getContext())}
|
|
</TableHead>
|
|
))}
|
|
</TableRow>
|
|
))}
|
|
</TableHeader>
|
|
<TableBody>
|
|
{table.getRowModel().rows?.length ? (
|
|
table.getRowModel().rows.map((row) => (
|
|
<TableRow key={row.id} data-state={row.getIsSelected() && 'selected'}>
|
|
{row.getVisibleCells().map((cell, cellIndex) => (
|
|
<TableCell
|
|
key={cell.id}
|
|
className={cn(cell.column.columnDef.meta?.className ?? '')}
|
|
>
|
|
{cellIndex === 0 && isTree ? (
|
|
<div
|
|
className='flex items-center gap-1'
|
|
style={{ paddingLeft: `${row.depth * 1.25}rem` }}
|
|
>
|
|
{row.getCanExpand() ? (
|
|
<button
|
|
onClick={row.getToggleExpandedHandler()}
|
|
className='flex items-center justify-center w-4 h-4 shrink-0 cursor-pointer'
|
|
>
|
|
{row.getIsExpanded() ? (
|
|
<ChevronDown className='w-4 h-4 ' />
|
|
) : (
|
|
<ChevronRight className='w-4 h-4 ' />
|
|
)}
|
|
</button>
|
|
) : (
|
|
<span className='w-4 h-4 shrink-0'></span>
|
|
)}
|
|
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
</div>
|
|
) : (
|
|
flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
)}
|
|
</TableCell>
|
|
))}
|
|
</TableRow>
|
|
))
|
|
) : (
|
|
<TableRow>
|
|
<TableCell colSpan={table.getAllColumns().length} className='h-24 text-center'>
|
|
No results.
|
|
</TableCell>
|
|
</TableRow>
|
|
)}
|
|
</TableBody>
|
|
</Table>
|
|
</div>
|
|
</Loading>
|
|
)
|
|
}
|