gitscope
https://dev.kronoz.win/r/marzneshin.git
dashboard/src/features/entity-table/selectable-entity-table.tsx · v0.6.2
Source
1 7738ec1 Mardin 2y ago import { useEffect, useMemo } from "react";
2 7738ec1 Mardin 2y ago import { DataTableViewOptions } from "./components";
3 7738ec1 Mardin 2y ago import { useQuery } from "@tanstack/react-query";
4 7738ec1 Mardin 2y ago import { RowSelectionState, ColumnDef } from "@tanstack/react-table";
5 7738ec1 Mardin 2y ago import { EntityTableContext } from "./contexts";
6 7738ec1 Mardin 2y ago import { TableSearch, DataTablePagination, EntityDataTable } from "./components";
7 7738ec1 Mardin 2y ago import {
8 7738ec1 Mardin 2y ago type UseRowSelectionReturn,
9 7738ec1 Mardin 2y ago usePrimaryFiltering,
10 7738ec1 Mardin 2y ago usePagination,
11 7738ec1 Mardin 2y ago type FetchEntityReturn,
12 7738ec1 Mardin 2y ago useEntityTable,
13 7738ec1 Mardin 2y ago useVisibility,
14 7738ec1 Mardin 2y ago useSorting,
15 7738ec1 Mardin 2y ago type SelectableQueryKey,
16 7738ec1 Mardin 2y ago type SelectableEntityQueryKeyType,
17 7738ec1 Mardin 2y ago useFilters,
18 7738ec1 Mardin 2y ago } from "./hooks";
19 7738ec1 Mardin 2y ago
20 7738ec1 Mardin 2y ago export interface SelectableEntityTableProps<T extends { id: number }> {
21 7738ec1 Mardin 2y ago fetchEntity: ({ queryKey }: SelectableEntityQueryKeyType) => FetchEntityReturn<T>;
22 7738ec1 Mardin 2y ago columns: ColumnDef<T>[];
23 7738ec1 Mardin 2y ago primaryFilter: string;
24 7738ec1 Mardin 2y ago parentEntityKey: string;
25 7738ec1 Mardin 2y ago parentEntityId: string | number;
26 7738ec1 Mardin 2y ago entityKey: string;
27 7738ec1 Mardin 2y ago rowSelection: UseRowSelectionReturn;
28 7738ec1 Mardin 2y ago entitySelection: {
29 7738ec1 Mardin 2y ago selectedEntity: number[];
30 7738ec1 Mardin 2y ago setSelectedEntity: (s: number[]) => void;
31 7738ec1 Mardin 2y ago }
32 7738ec1 Mardin 2y ago existingEntityIds: number[];
33 7738ec1 Mardin 2y ago }
34 7738ec1 Mardin 2y ago
35 7738ec1 Mardin 2y ago export function SelectableEntityTable<T extends { id: number }>({
36 7738ec1 Mardin 2y ago fetchEntity,
37 7738ec1 Mardin 2y ago columns,
38 7738ec1 Mardin 2y ago primaryFilter,
39 7738ec1 Mardin 2y ago rowSelection,
40 7738ec1 Mardin 2y ago entitySelection,
41 7738ec1 Mardin 2y ago entityKey,
42 7738ec1 Mardin 2y ago parentEntityKey,
43 7738ec1 Mardin 2y ago parentEntityId,
44 7738ec1 Mardin 2y ago existingEntityIds,
45 7738ec1 Mardin 2y ago }: SelectableEntityTableProps<T>) {
46 7738ec1 Mardin 2y ago const columnPrimaryFilter = usePrimaryFiltering({ column: primaryFilter });
47 7738ec1 Mardin 2y ago const filters = useFilters();
48 7738ec1 Mardin 2y ago const sorting = useSorting();
49 7738ec1 Mardin 2y ago const visibility = useVisibility();
50 7738ec1 Mardin 2y ago const { selectedRow, setSelectedRow } = rowSelection;
51 7738ec1 Mardin 2y ago const { setSelectedEntity } = entitySelection;
52 7738ec1 Mardin 2y ago const { onPaginationChange, pageIndex, pageSize } = usePagination();
53 7738ec1 Mardin 2y ago const query: SelectableQueryKey = [
54 7738ec1 Mardin 2y ago parentEntityKey,
55 7738ec1 Mardin 2y ago parentEntityId,
56 7738ec1 Mardin 2y ago entityKey,
57 7738ec1 Mardin 2y ago {
58 7738ec1 Mardin 2y ago page: pageIndex,
59 7738ec1 Mardin 2y ago size: pageSize,
60 7738ec1 Mardin 2y ago },
61 7738ec1 Mardin 2y ago columnPrimaryFilter.columnFilters,
62 7738ec1 Mardin 2y ago {
63 7738ec1 Mardin 2y ago sortBy: sorting.sorting[0]?.id || "created_at",
64 7738ec1 Mardin 2y ago desc: sorting.sorting[0]?.desc || true,
65 7738ec1 Mardin 2y ago },
66 7738ec1 Mardin 2y ago { filters: filters.columnsFilter }
67 7738ec1 Mardin 2y ago ];
68 7738ec1 Mardin 2y ago
69 7738ec1 Mardin 2y ago const { data, isFetching } = useQuery({
70 7738ec1 Mardin 2y ago queryFn: fetchEntity,
71 7738ec1 Mardin 2y ago queryKey: query,
72 7738ec1 Mardin 2y ago initialData: { entities: [], pageCount: 1 },
73 7738ec1 Mardin 2y ago });
74 7738ec1 Mardin 2y ago
75 7738ec1 Mardin 2y ago const table = useEntityTable({
76 7738ec1 Mardin 2y ago data,
77 7738ec1 Mardin 2y ago columns,
78 7738ec1 Mardin 2y ago pageSize,
79 7738ec1 Mardin 2y ago pageIndex,
80 7738ec1 Mardin 2y ago rowSelection,
81 7738ec1 Mardin 2y ago visibility,
82 7738ec1 Mardin 2y ago sorting,
83 7738ec1 Mardin 2y ago onPaginationChange,
84 7738ec1 Mardin 2y ago });
85 7738ec1 Mardin 2y ago
86 7738ec1 Mardin 2y ago useEffect(() => {
87 7738ec1 Mardin 2y ago setSelectedRow((selected) => {
88 7738ec1 Mardin 2y ago const updatedSelected: RowSelectionState = { ...selected };
89 7738ec1 Mardin 2y ago for (const [i, fetchedEntity] of data.entities.entries()) {
90 7738ec1 Mardin 2y ago if (existingEntityIds.includes(fetchedEntity.id)) {
91 7738ec1 Mardin 2y ago updatedSelected[i] = true;
92 7738ec1 Mardin 2y ago } else {
93 7738ec1 Mardin 2y ago updatedSelected[i] = false;
94 7738ec1 Mardin 2y ago }
95 7738ec1 Mardin 2y ago }
96 7738ec1 Mardin 2y ago return updatedSelected;
97 7738ec1 Mardin 2y ago });
98 7738ec1 Mardin 2y ago
99 7738ec1 Mardin 2y ago }, [data, setSelectedRow, existingEntityIds]);
100 7738ec1 Mardin 2y ago
101 7738ec1 Mardin 2y ago useEffect(() => {
102 7738ec1 Mardin 2y ago const selectedRowId = Object.keys(selectedRow).filter(key => selectedRow[key] === true).map(Number);
103 7738ec1 Mardin 2y ago
104 7738ec1 Mardin 2y ago setSelectedEntity(
105 7738ec1 Mardin 2y ago selectedRowId
106 7738ec1 Mardin 2y ago .map(id => data.entities[id]?.id)
107 7738ec1 Mardin 2y ago .filter(id => id !== null && id !== undefined)
108 7738ec1 Mardin 2y ago );
109 7738ec1 Mardin 2y ago }, [data, setSelectedEntity, setSelectedRow, existingEntityIds, selectedRow]);
110 7738ec1 Mardin 2y ago
111 7738ec1 Mardin 2y ago
112 7738ec1 Mardin 2y ago const contextValue = useMemo(
113 7738ec1 Mardin 2y ago () => ({ table, data: data.entities, primaryFilter: columnPrimaryFilter, filters, isLoading: isFetching }),
114 7738ec1 Mardin 2y ago [table, data.entities, filters, columnPrimaryFilter, isFetching],
115 7738ec1 Mardin 2y ago );
116 7738ec1 Mardin 2y ago
117 7738ec1 Mardin 2y ago return (
118 7738ec1 Mardin 2y ago <EntityTableContext.Provider value={contextValue}>
119 7738ec1 Mardin 2y ago <div className="flex flex-col">
120 7738ec1 Mardin 2y ago <div className="flex flex-col md:flex-row-reverse items-center py-4 gap-2 w-full">
121 7738ec1 Mardin 2y ago <div className="flex flex-row items-center w-full">
122 7738ec1 Mardin 2y ago <DataTableViewOptions table={table} />
123 7738ec1 Mardin 2y ago </div>
124 7738ec1 Mardin 2y ago <TableSearch />
125 7738ec1 Mardin 2y ago </div>
126 7738ec1 Mardin 2y ago <div className="w-full rounded-md border">
127 7738ec1 Mardin 2y ago <EntityDataTable columns={columns} />
128 7738ec1 Mardin 2y ago <DataTablePagination table={table} />
129 7738ec1 Mardin 2y ago </div>
130 7738ec1 Mardin 2y ago </div>
131 7738ec1 Mardin 2y ago </EntityTableContext.Provider>
132 7738ec1 Mardin 2y ago );
133 7738ec1 Mardin 2y ago }