gitscope
← marzneshin / v0.5.3 / dashboard/src/features/entity-table/components/table.tsx
https://dev.kronoz.win/r/marzneshin.git
dashboard/src/features/entity-table/components/table.tsx · TypeScript
Blame Raw
 1import {
 2    ColumnDef,
 3    flexRender,
 4} from "@tanstack/react-table";
 5import {
 6    Table,
 7    TableBody,
 8    TableCell,
 9    TableHead,
10    TableHeader,
11    TableRow,
12    Skeleton
13} from "@marzneshin/components";
14import { useTranslation } from "react-i18next";
15import { useEntityTableContext } from "@marzneshin/features/entity-table/contexts";
16import { type FC } from "react";
17
18interface DataTableProps<TData, TValue> {
19    columns: ColumnDef<TData, TValue>[]
20    onRowClick?: (object: TData) => void
21}
22
23const Headers = () => {
24    const { table } = useEntityTableContext();
25    return (
26        table.getHeaderGroups().map(headerGroup => (
27            <TableRow key={headerGroup.id}>
28                {headerGroup.headers.map(header => (
29                    <TableHead key={header.id}>
30                        {!header.isPlaceholder && flexRender(header.column.columnDef.header, header.getContext())}
31                    </TableHead>
32                ))}
33            </TableRow>
34        ))
35    )
36};
37
38const Rows: FC<Readonly<DataTableProps<any, any>>> = ({
39    columns,
40    onRowClick
41}) => {
42    const { table } = useEntityTableContext();
43    const { t } = useTranslation();
44
45    return (table.getRowModel().rows.length ? (
46        table.getRowModel().rows.map(row => (
47            <TableRow
48                key={row.id}
49                data-state={row.getIsSelected() ? "selected" : undefined}
50                data-testid="entity-table-row"
51                onClick={() => onRowClick?.(row.original)}
52            >
53                {row.getVisibleCells().map(cell => (
54                    <TableCell key={cell.id}>
55                        {flexRender(cell.column.columnDef.cell, cell.getContext())}
56                    </TableCell>
57                ))}
58            </TableRow>
59        ))
60    ) : (
61        <TableRow>
62            <TableCell colSpan={columns.length} className="h-24 text-center">
63                {t('table.no-result')}
64            </TableCell>
65        </TableRow>
66    ))
67};
68
69export function EntityDataTable<TData, TValue>({
70    columns,
71    onRowClick,
72}: Readonly<DataTableProps<TData, TValue>>) {
73    const { isLoading } = useEntityTableContext();
74
75    const Loading = () => (
76        <>
77            {Array.from({ length: 5 }).map((_, rowIndex) => (
78                <TableRow key={`skeleton-row-${rowIndex}`} className="w-full">
79                    {columns.map((column, cellIndex) => (
80                        <TableCell key={`${column.cell}-skeleton-cell-${rowIndex}-${cellIndex}`} className="h-12">
81                            <Skeleton className="w-full h-full" />
82                        </TableCell>
83                    ))}
84                </TableRow>
85            ))}
86        </>
87    );
88
89    return (
90        <Table className="w-full">
91            <TableHeader> <Headers /> </TableHeader>
92            <TableBody>
93                {isLoading ? <Loading /> : <Rows onRowClick={onRowClick} columns={columns} />}
94            </TableBody>
95        </Table>
96    );
97}