gitscope
← marzneshin / v0.3.0 / dashboard/src/components/entity-table/index.tsx
https://dev.kronoz.win/r/marzneshin.git
dashboard/src/components/entity-table/index.tsx · TypeScript
Blame Raw
  1import { type FC, useMemo, 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    type UseRowSelectionReturn,
 11    type UseDialogProps,
 12    useFiltering,
 13    usePagination,
 14    type FetchEntityReturn,
 15    useEntityTable,
 16    useVisibility,
 17    useSorting,
 18    type SortableQueryKey,
 19    type QueryKey,
 20    type EntityQueryKeyType,
 21} from "./hooks";
 22import { useDialog } from "@marzneshin/hooks";
 23
 24interface EntityTableProps<T> {
 25    fetchEntity: ({ queryKey }: EntityQueryKeyType) => FetchEntityReturn<T>;
 26    MutationDialog: FC<UseDialogProps<T>>;
 27    DeleteConfirmationDialog: FC<UseDialogProps<T>>;
 28    SettingsDialog: FC<UseDialogProps<T | any>>;
 29    columnsFn: any;
 30    filteredColumn: string;
 31    entityKey: string;
 32    rowSelection?: UseRowSelectionReturn;
 33    manualSorting?: boolean;
 34}
 35
 36export function EntityTable<T>({
 37    fetchEntity,
 38    MutationDialog,
 39    DeleteConfirmationDialog,
 40    SettingsDialog,
 41    columnsFn,
 42    filteredColumn,
 43    rowSelection,
 44    entityKey,
 45    manualSorting = false,
 46}: EntityTableProps<T>) {
 47    const [mutationDialogOpen, setMutationDialogOpen] = useDialog();
 48    const [deleteDialogOpen, setDeleteDialogOpen] = useDialog();
 49    const [settingsDialogOpen, setSettingsDialogOpen] = useDialog();
 50    const [selectedEntity, selectEntity] = useState<T | null>(null);
 51
 52    const onEdit = (entity: T) => {
 53        selectEntity(entity);
 54        setMutationDialogOpen(true);
 55    };
 56
 57    const onDelete = (entity: T) => {
 58        selectEntity(entity);
 59        setDeleteDialogOpen(true);
 60    };
 61
 62    const onCreate = () => {
 63        selectEntity(null);
 64        setMutationDialogOpen(true);
 65    };
 66
 67    const onOpen = (entity: T) => {
 68        selectEntity(entity);
 69        setSettingsDialogOpen(true);
 70    };
 71
 72    const { t } = useTranslation();
 73    const filtering = useFiltering({ column: filteredColumn });
 74    const sorting = useSorting();
 75    const visibility = useVisibility();
 76    const { onPaginationChange, pageIndex, pageSize } = usePagination();
 77    const sortedQuery: SortableQueryKey = [
 78        entityKey,
 79        pageIndex,
 80        pageSize,
 81        filtering.columnFilters,
 82        sorting.sorting[0]?.id ? sorting.sorting[0].id : "created_at",
 83        sorting.sorting[0]?.desc,
 84    ];
 85    const query: QueryKey = [
 86        entityKey,
 87        pageIndex,
 88        pageSize,
 89        filtering.columnFilters,
 90    ];
 91
 92    const { data, isLoading } = useQuery({
 93        queryFn: fetchEntity,
 94        queryKey: manualSorting ? sortedQuery : query,
 95        initialData: { entity: [], pageCount: 1 },
 96    });
 97
 98    const columns = columnsFn({ onEdit, onDelete, onOpen });
 99    const table = useEntityTable({
100        data,
101        columns,
102        pageSize,
103        pageIndex,
104        rowSelection,
105        visibility,
106        sorting,
107        onPaginationChange,
108    });
109
110    const contextValue = useMemo(() => (
111        { table, data: data.entity, filtering, isLoading }
112    ), [table, data.entity, filtering, isLoading])
113
114    return (
115        <EntityTableContext.Provider
116            value={contextValue}
117        >
118            <SettingsDialog
119                open={settingsDialogOpen}
120                onOpenChange={setSettingsDialogOpen}
121                entity={selectedEntity}
122            />
123            <DeleteConfirmationDialog
124                open={deleteDialogOpen}
125                onOpenChange={setDeleteDialogOpen}
126                entity={selectedEntity}
127            />
128            <MutationDialog
129                open={mutationDialogOpen}
130                onOpenChange={setMutationDialogOpen}
131                entity={selectedEntity}
132            />
133            <div className="flex flex-col">
134                <div className="flex items-center py-4">
135                    <TableFiltering />
136                    <DataTableViewOptions table={table} />
137                    {onCreate && (
138                        <Button aria-label={`create-${entityKey}`} onClick={onCreate}>
139                            {t("create")}
140                        </Button>
141                    )}
142                </div>
143                <div className="w-full rounded-md border">
144                    <EntityDataTable columns={columns} onRowClick={onOpen} />
145                    <DataTablePagination />
146                </div>
147            </div>
148        </EntityTableContext.Provider>
149    );
150}
151
152export * from "./hooks";