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