gitscope
← marzneshin / v0.6.0 / 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
 69const Loading = () => (
 70    <>
 71        {Array.from({ length: 5 }).map((_, rowIndex) => (
 72            <TableRow key={`skeleton-row-${rowIndex}`} className="w-full">
 73                <TableCell className="h-12">
 74                    <Skeleton className="w-full h-full" />
 75                </TableCell>
 76                <TableCell className="h-12">
 77                    <Skeleton className="w-full h-full" />
 78                </TableCell>
 79                <TableCell className="h-12">
 80                    <Skeleton className="w-full h-full" />
 81                </TableCell>
 82                <TableCell className="h-12">
 83                    <Skeleton className="w-full h-full" />
 84                </TableCell>
 85                <TableCell className="h-12">
 86                    <Skeleton className="w-full h-full" />
 87                </TableCell>
 88            </TableRow>
 89        ))}
 90    </>
 91);
 92
 93export function EntityDataTable<TData, TValue>({
 94    columns,
 95    onRowClick,
 96}: Readonly<DataTableProps<TData, TValue>>) {
 97    const { isLoading } = useEntityTableContext();
 98
 99    return (
100        <Table className="w-full">
101            <TableHeader> <Headers /> </TableHeader>
102            <TableBody>
103                {isLoading ? <Loading /> : <Rows onRowClick={onRowClick} columns={columns} />}
104            </TableBody>
105        </Table>
106    );
107}