1import { FC, 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 } = useQuery({
75 queryFn: fetchEntity,
76 queryKey: [entityKey, pageIndex, pageSize],
77 initialData: { entity: [], pageCount: 1 }
78 });
79
80 const columns = columnsFn({ onEdit, onDelete, onOpen })
81 const table = useEntityTable({
82 data,
83 filtering,
84 columns,
85 pageSize,
86 pageIndex,
87 rowSelection,
88 visibility,
89 sorting,
90 onPaginationChange
91 })
92
93 // TODO: Move the selectedEntity to context
94 return (
95 <EntityTableContext.Provider value={{ table, data: data.entity, filtering }}>
96 <SettingsDialog
97 open={settingsDialogOpen}
98 onOpenChange={setSettingsDialogOpen}
99 entity={selectedEntity}
100 />
101 <DeleteConfirmationDialog
102 open={deleteDialogOpen}
103 onOpenChange={setDeleteDialogOpen}
104 entity={selectedEntity}
105 />
106 <MutationDialog
107 open={mutationDialogOpen}
108 onOpenChange={setMutationDialogOpen}
109 entity={selectedEntity}
110 />
111 <div className="flex flex-col">
112 <div className="flex items-center py-4">
113 <TableFiltering />
114 <DataTableViewOptions table={table} />
115 {onCreate && (
116 <Button
117 aria-label={`create-${entityKey}`}
118 onClick={onCreate}>
119 {t('create')}
120 </Button>
121 )}
122 </div>
123 <div className="w-full rounded-md border">
124 <EntityDataTable
125 columns={columns}
126 onRowClick={onOpen}
127 />
128 <DataTablePagination />
129 </div>
130 </div>
131 </EntityTableContext.Provider>
132 );
133}
134
135export * from './hooks'