1import { FC, useEffect, useState } from "react";
2import { Button, DataTableViewOptions } from "@marzneshin/components";
3import { useTranslation } from "react-i18next";
4import { useQuery } from "@tanstack/react-query";
5import { EntityTableContext } from "./entity-table-provider";
6import { EntityDataTable } from "./table"
7import { DataTablePagination } from "./table-pagination"
8import { TableFiltering } from "./table-filtering";
9import {
10 UseRowSelectionReturn,
11 UseDialogProps,
12 useFiltering,
13 useDialog,
14 usePagination,
15 FetchEntityReturn,
16 EntityQueryKeyType,
17 useEntityTable,
18 useVisibility,
19 useSorting
20} from "./hooks";
21
22interface EntityTableProps<T> {
23 fetchEntity: ({ queryKey }: EntityQueryKeyType) => FetchEntityReturn<T>;
24 MutationDialog: FC<UseDialogProps<T>>;
25 DeleteConfirmationDialog: FC<UseDialogProps<T>>;
26 SettingsDialog: FC<UseDialogProps<T | any>>;
27 columnsFn: any;
28 filteredColumn: string;
29 entityKey: string
30 rowSelection?: UseRowSelectionReturn
31}
32
33export function EntityTable<T>({
34 fetchEntity,
35 MutationDialog,
36 DeleteConfirmationDialog,
37 SettingsDialog,
38 columnsFn,
39 filteredColumn,
40 rowSelection,
41 entityKey,
42}: EntityTableProps<T>) {
43 const [mutationDialogOpen, setMutationDialogOpen] = useDialog();
44 const [deleteDialogOpen, setDeleteDialogOpen] = useDialog();
45 const [settingsDialogOpen, setSettingsDialogOpen] = useDialog();
46 const [selectedEntity, selectEntity] = useState<T | null>(null);
47
48 const onEdit = (entity: T) => {
49 selectEntity(entity);
50 setMutationDialogOpen(true);
51 };
52
53 const onDelete = (entity: T) => {
54 selectEntity(entity);
55 setDeleteDialogOpen(true);
56 };
57
58 const onCreate = () => {
59 selectEntity(null);
60 setMutationDialogOpen(true);
61 };
62
63 const onOpen = (entity: T) => {
64 selectEntity(entity);
65 setSettingsDialogOpen(true);
66 };
67
68 const { t } = useTranslation()
69 const filtering = useFiltering({ column: filteredColumn })
70 const sorting = useSorting()
71 const visibility = useVisibility()
72 const { onPaginationChange, pageIndex, pageSize } = usePagination();
73
74 const { data, isLoading } = useQuery({
75 queryFn: fetchEntity,
76 queryKey: [entityKey, pageIndex, pageSize, filtering.columnFilters],
77 initialData: { entity: [], pageCount: 1 }
78 });
79
80 const columns = columnsFn({ onEdit, onDelete, onOpen })
81 const table = useEntityTable({
82 data,
83 columns,
84 pageSize,
85 pageIndex,
86 rowSelection,
87 visibility,
88 sorting,
89 onPaginationChange
90 })
91
92 useEffect(() => table.setPageIndex(1), [filtering.columnFilters, table])
93
94 // TODO: Move the selectedEntity to context
95 return (
96 <EntityTableContext.Provider value={{ table, data: data.entity, filtering, isLoading }}>
97 <SettingsDialog
98 open={settingsDialogOpen}
99 onOpenChange={setSettingsDialogOpen}
100 entity={selectedEntity}
101 />
102 <DeleteConfirmationDialog
103 open={deleteDialogOpen}
104 onOpenChange={setDeleteDialogOpen}
105 entity={selectedEntity}
106 />
107 <MutationDialog
108 open={mutationDialogOpen}
109 onOpenChange={setMutationDialogOpen}
110 entity={selectedEntity}
111 />
112 <div className="flex flex-col">
113 <div className="flex items-center py-4">
114 <TableFiltering />
115 <DataTableViewOptions table={table} />
116 {onCreate && (
117 <Button
118 aria-label={`create-${entityKey}`}
119 onClick={onCreate}>
120 {t('create')}
121 </Button>
122 )}
123 </div>
124 <div className="w-full rounded-md border">
125 <EntityDataTable
126 columns={columns}
127 onRowClick={onOpen}
128 />
129 <DataTablePagination />
130 </div>
131 </div>
132 </EntityTableContext.Provider>
133 );
134}
135
136export * from './hooks'