test_task_crm/frontend/src/components/data-table/data-table.tsx

85 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { type ColumnDef, type SortingState, flexRender, getCoreRowModel, getSortedRowModel, useReactTable } from '@tanstack/react-table'
import { Loader2 } from 'lucide-react'
import { useMemo, useState } from 'react'
import { Card } from '@/components/ui/card'
import { Skeleton } from '@/components/ui/skeleton'
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
interface DataTableProps<TData> {
columns: ColumnDef<TData, any>[]
data: TData[]
isLoading?: boolean
renderToolbar?: React.ReactNode
emptyState?: React.ReactNode
skeletonRows?: number
}
export const DataTable = <TData,>({ columns, data, isLoading = false, renderToolbar, emptyState, skeletonRows = 5 }: DataTableProps<TData>) => {
const [sorting, setSorting] = useState<SortingState>([])
const memoizedData = useMemo(() => data, [data])
const table = useReactTable({
data: memoizedData,
columns,
state: { sorting },
onSortingChange: setSorting,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
})
const leafColumns = table.getAllLeafColumns()
return (
<Card className="space-y-4 border bg-card">
{renderToolbar}
<div className="overflow-hidden rounded-xl border bg-background">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id} className="bg-muted/50">
{headerGroup.headers.map((header) => (
<TableHead key={header.id} className="whitespace-nowrap">
{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
<TableBody>
{isLoading ? (
[...Array(skeletonRows)].map((_, index) => (
<TableRow key={`skeleton-${index}`}>
{leafColumns.map((column) => (
<TableCell key={`${column.id}-${index}`}>
<Skeleton className="h-4 w-full" />
</TableCell>
))}
</TableRow>
))
) : table.getRowModel().rows.length ? (
table.getRowModel().rows.map((row) => (
<TableRow key={row.id} data-state={row.getIsSelected() && 'selected'}>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan={columns.length} className="h-32 text-center text-sm text-muted-foreground">
{emptyState ?? (
<div className="flex flex-col items-center gap-2">
<Loader2 className="h-5 w-5" />
<p>Нет данных для отображения</p>
</div>
)}
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
</Card>
)
}