Files
web/src/components/data-table.tsx

89 lines
2.9 KiB
TypeScript

'use client'
import {Table as TableRoot, TableBody, TableCell, TableHead, TableHeader, TableRow} from '@/components/ui/table'
import {ColumnDef, flexRender, getCoreRowModel, useReactTable} from '@tanstack/react-table'
import {Pagination, PaginationProps} from '@/components/ui/pagination'
import {Loader} from 'lucide-react'
import {merge} from '@/lib/utils'
export type DataTableProps<T> = {
data: T[]
status: 'load' | 'done' | 'fail'
columns: ColumnDef<T>[]
pagination: PaginationProps
classNames?: {
headRow?: string
dataRow?: string
}
}
export default function DataTable<T extends Record<string, unknown>>(props: DataTableProps<T>) {
const table = useReactTable({
data: props.data,
columns: props.columns,
getCoreRowModel: getCoreRowModel(),
manualPagination: true,
rowCount: props.pagination.total,
state: {
pagination: {
pageIndex: props.pagination.page,
pageSize: props.pagination.size,
},
columnFilters: [],
},
})
return (<>
{/* 数据表*/}
<div className={`rounded-md relative bg-card`}>
<TableRoot>
<TableHeader>
{table.getHeaderGroups().map(group => (
<TableRow key={group.id}>
{group.headers.map(header => (
<TableHead key={header.id} colSpan={header.colSpan}>
{header.isPlaceholder ? null : flexRender(
header.column.columnDef.header,
header.getContext(),
)}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
<TableBody>
{props.status === 'fail' ? (
<TableRow>
<TableCell colSpan={props.columns.length} className={`text-center text-fail`}></TableCell>
</TableRow>
) : !props.data?.length ? (
<TableRow>
<TableCell colSpan={props.columns.length} className={`text-center`}></TableCell>
</TableRow>
) : table.getRowModel().rows.map(row => (
<TableRow key={row.id} data-state={row.getIsSelected() && 'selected'} className={merge('h-14', props.classNames?.dataRow)}>
{row.getVisibleCells().map(cell => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext(),
)}
</TableCell>
))}
</TableRow>
))}
</TableBody>
</TableRoot>
{props.status === 'load' && (
<div className={`absolute inset-0 bg-white/10 backdrop-blur-xs flex items-center justify-center gap-2 transition`}>
<Loader className={`animate-spin`}/>
<span></span>
</div>
)}
</div>
{/* 分页器 */}
<Pagination {...props.pagination}/>
</>)
}