gitscope
← marzneshin / v0.3.2 / dashboard/src/features/entity-table/entity-table.tsx
https://dev.kronoz.win/r/marzneshin.git
dashboard/src/features/entity-table/entity-table.tsx · TypeScript
Blame Raw
  1import { useMemo } from "react";
  2import { Button, DataTableViewOptions } from "@marzneshin/components";
  3import { useTranslation } from "react-i18next";
  4import { useQuery } from "@tanstack/react-query";
  5import { EntityTableContext } from "./contexts";
  6import { TableFiltering, DataTablePagination, EntityDataTable } from "./components";
  7import {
  8    type UseRowSelectionReturn,
  9    useFiltering,
 10    usePagination,
 11    type FetchEntityReturn,
 12    useEntityTable,
 13    useVisibility,
 14    useSorting,
 15    type SortableQueryKey,
 16    type QueryKey,
 17    type EntityQueryKeyType,
 18} from "./hooks";
 19
 20export interface EntityTableProps<T> {
 21    fetchEntity: ({ queryKey }: EntityQueryKeyType) => FetchEntityReturn<T>;
 22    columnsFn: any;
 23    filteredColumn: string;
 24    entityKey: string;
 25    rowSelection?: UseRowSelectionReturn;
 26    manualSorting?: boolean;
 27    onCreate: () => void;
 28    onEdit: (entity: T) => void;
 29    onOpen: (entity: T) => void;
 30    onDelete: (entity: T) => void;
 31}
 32
 33export function EntityTable<T>({
 34    fetchEntity,
 35    columnsFn,
 36    filteredColumn,
 37    rowSelection,
 38    entityKey,
 39    manualSorting = false,
 40    onCreate,
 41    onEdit,
 42    onOpen,
 43    onDelete,
 44}: EntityTableProps<T>) {
 45    const { t } = useTranslation();
 46    const filtering = useFiltering({ column: filteredColumn });
 47    const sorting = useSorting();
 48    const visibility = useVisibility();
 49    const { onPaginationChange, pageIndex, pageSize } = usePagination();
 50    const sortedQuery: SortableQueryKey = [
 51        entityKey,
 52        pageIndex,
 53        pageSize,
 54        filtering.columnFilters,
 55        sorting.sorting[0]?.id ? sorting.sorting[0].id : "created_at",
 56        sorting.sorting[0]?.desc,
 57    ];
 58    const query: QueryKey = [
 59        entityKey,
 60        pageIndex,
 61        pageSize,
 62        filtering.columnFilters,
 63    ];
 64
 65    const { data, isFetching } = useQuery({
 66        queryFn: fetchEntity,
 67        queryKey: manualSorting ? sortedQuery : query,
 68        initialData: { entity: [], pageCount: 1 },
 69    });
 70
 71    const columns = columnsFn({ onEdit, onDelete, onOpen });
 72    const table = useEntityTable({
 73        data,
 74        columns,
 75        pageSize,
 76        pageIndex,
 77        rowSelection,
 78        visibility,
 79        sorting,
 80        onPaginationChange,
 81    });
 82
 83    const contextValue = useMemo(
 84        () => ({ table, data: data.entity, filtering, isLoading: isFetching }),
 85        [table, data.entity, filtering, isFetching],
 86    );
 87
 88    return (
 89        <EntityTableContext.Provider value={contextValue}>
 90            <div className="flex flex-col">
 91                <div className="flex items-center py-4">
 92                    <TableFiltering />
 93                    <DataTableViewOptions table={table} />
 94                    {onCreate && (
 95                        <Button aria-label={`create-${entityKey}`} onClick={onCreate}>
 96                            {t("create")}
 97                        </Button>
 98                    )}
 99                </div>
100                <div className="w-full rounded-md border">
101                    <EntityDataTable columns={columns} onRowClick={onOpen} />
102                    <DataTablePagination />
103                </div>
104            </div>
105        </EntityTableContext.Provider>
106    );
107}