Files
blog-admin/src/components/data-table/base-table.tsx
2026-07-29 22:10:33 +08:00

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>
)
}