rez-table-listing-mui 0.0.25 → 0.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.uat +1 -0
- package/.eslintrc.cjs +11 -9
- package/dist/index.d.ts +102 -8
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +25 -11
- package/src/App.tsx +172 -129
- package/src/assets/svg.tsx +65 -2
- package/src/components/common/confirm-modal/index.tsx +200 -0
- package/src/components/filter/components/attributes-filter.tsx +28 -0
- package/src/components/filter/components/forms/components/Attributes-select.tsx +182 -0
- package/src/components/filter/components/forms/components/Date.tsx +58 -0
- package/src/components/filter/components/forms/components/Dropdown.tsx +62 -0
- package/src/components/filter/components/forms/components/Filter-criteria.tsx +164 -0
- package/src/components/filter/components/forms/components/Multi-Select.tsx +57 -0
- package/src/components/filter/components/forms/components/Select.tsx +53 -0
- package/src/components/filter/components/forms/components/Textfield.tsx +43 -0
- package/src/components/filter/components/forms/components/styles.tsx +11 -0
- package/src/components/filter/components/forms/index.tsx +444 -0
- package/src/components/filter/components/main-filter.tsx +66 -0
- package/src/components/filter/components/saved-edit-filter.tsx +107 -0
- package/src/components/filter/components/saved-filter.tsx +150 -0
- package/src/components/filter/components/search/index.tsx +56 -0
- package/src/components/filter/components/tabs/custom-tab-panel.tsx +29 -0
- package/src/components/filter/components/tabs/index.tsx +85 -0
- package/src/components/filter/index.tsx +261 -0
- package/src/components/index-table.tsx +3 -6
- package/src/components/index.scss +4 -0
- package/src/components/login/index.tsx +49 -0
- package/src/components/table-body.tsx +6 -4
- package/src/components/table-head.tsx +0 -10
- package/src/components/topbar/index.scss +5 -0
- package/src/components/topbar/index.tsx +54 -19
- package/src/components/viewmore/index.tsx +2 -2
- package/src/libs/hooks/useCraftTable.tsx +29 -5
- package/src/libs/hooks/useDefaultColumns.tsx +2 -2
- package/src/libs/hooks/useEntityTableAPI.tsx +183 -0
- package/src/libs/hooks/useEntityTableHooks.ts +25 -0
- package/src/libs/utils/apiColumn.ts +123 -0
- package/src/libs/utils/common.ts +42 -0
- package/src/main.tsx +6 -3
- package/src/types/common.ts +67 -0
- package/src/types/filter.ts +215 -0
- package/src/types/table-options.ts +15 -2
- package/src/types/table.ts +5 -5
- package/tsconfig.json +1 -1
- package/vite.config.ts +3 -3
|
@@ -17,7 +17,6 @@ import {
|
|
|
17
17
|
import DraggableTableHeader from "./table-head-dnd-cell";
|
|
18
18
|
import TableHeadPin from "./table-head-pin";
|
|
19
19
|
import Checkbox from "./inputs/checkbox";
|
|
20
|
-
import TableHeadPopover from "./table-head-popover";
|
|
21
20
|
|
|
22
21
|
interface TableHeadProps<T> {
|
|
23
22
|
table: Table<T>;
|
|
@@ -41,15 +40,6 @@ function TableHead<T>({
|
|
|
41
40
|
|
|
42
41
|
// Popover
|
|
43
42
|
const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
|
|
44
|
-
const [wrap, setWrap] = useState(false);
|
|
45
|
-
|
|
46
|
-
const handleClose = () => {
|
|
47
|
-
setAnchorEl(null);
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const toggleWrap = () => {
|
|
51
|
-
setWrap((prev) => !prev);
|
|
52
|
-
};
|
|
53
43
|
|
|
54
44
|
const handleHover = (event: React.MouseEvent<HTMLElement>) => {
|
|
55
45
|
setAnchorEl((prev) => (prev ? null : event.currentTarget));
|
|
@@ -2,7 +2,7 @@ import React, { useState, useRef, useEffect } from "react";
|
|
|
2
2
|
import {
|
|
3
3
|
ChangeLayoutIcon,
|
|
4
4
|
SortingIcon,
|
|
5
|
-
|
|
5
|
+
FilterationIcon,
|
|
6
6
|
HideColumnIcon,
|
|
7
7
|
} from "../../assets/svg";
|
|
8
8
|
import { Popover } from "@mui/material";
|
|
@@ -17,9 +17,11 @@ import SortPopover from "../sorting-modal.tsx";
|
|
|
17
17
|
import ColumnToggle from "../column-visibility-modal/index.tsx";
|
|
18
18
|
import { CraftTableOptionsProps } from "../../types/table-options.ts";
|
|
19
19
|
import TableSearch from "../search/index.tsx";
|
|
20
|
+
import FilterDrawer from "../filter/index.tsx";
|
|
20
21
|
|
|
21
22
|
interface TopbarProps<T> {
|
|
22
23
|
table: Table<T>;
|
|
24
|
+
isFullscreen: boolean;
|
|
23
25
|
fullscreenToggle: () => void;
|
|
24
26
|
isCompactTable: boolean;
|
|
25
27
|
setIsCompactTable: React.Dispatch<React.SetStateAction<boolean>>;
|
|
@@ -35,13 +37,14 @@ interface TopbarProps<T> {
|
|
|
35
37
|
function Topbar<T>({
|
|
36
38
|
table,
|
|
37
39
|
isCompactTable,
|
|
40
|
+
isFullscreen,
|
|
38
41
|
fullscreenToggle,
|
|
39
42
|
setIsCompactTable,
|
|
40
43
|
paginationComponent,
|
|
41
44
|
topbarOptions,
|
|
42
45
|
tableStates,
|
|
43
46
|
}: TopbarProps<T>) {
|
|
44
|
-
const [
|
|
47
|
+
const [isFullscreenState, setIsFullscreenState] = useState(isFullscreen);
|
|
45
48
|
const [sortAnchorEl, setSortAnchorEl] = useState<HTMLElement | null>(null);
|
|
46
49
|
const [groupBy, setGroupBy] = useState<string>("None");
|
|
47
50
|
|
|
@@ -57,7 +60,12 @@ function Topbar<T>({
|
|
|
57
60
|
table.getAllLeafColumns().map((col) => col.id)
|
|
58
61
|
);
|
|
59
62
|
|
|
60
|
-
//
|
|
63
|
+
//Filter
|
|
64
|
+
const [showFilterInput, setShowFilterInput] = useState(false);
|
|
65
|
+
|
|
66
|
+
// search
|
|
67
|
+
const [showSearchInput, setShowSearchInput] = useState(false);
|
|
68
|
+
const searchContainerRef = useRef<HTMLDivElement>(null);
|
|
61
69
|
|
|
62
70
|
// sync column order with table instance
|
|
63
71
|
useEffect(() => {
|
|
@@ -70,11 +78,22 @@ function Topbar<T>({
|
|
|
70
78
|
showColumnToggle,
|
|
71
79
|
showChangeLayoutToggle,
|
|
72
80
|
viewMoreToggle,
|
|
81
|
+
showSortingToggle,
|
|
82
|
+
showFilterToggle,
|
|
73
83
|
showSearch,
|
|
74
|
-
showFilter,
|
|
75
|
-
showCustomizationToggle,
|
|
76
84
|
searchValue,
|
|
77
85
|
onSearchChange,
|
|
86
|
+
filterOptions = {
|
|
87
|
+
columnsData: {
|
|
88
|
+
column_list: [],
|
|
89
|
+
operation_list: {},
|
|
90
|
+
saved_filter: [],
|
|
91
|
+
},
|
|
92
|
+
onDeleteFilter: () => {},
|
|
93
|
+
onSaveFilter: () => {},
|
|
94
|
+
dropdownData: [],
|
|
95
|
+
onUpdateFilter: () => {},
|
|
96
|
+
},
|
|
78
97
|
} = topbarOptions ?? {};
|
|
79
98
|
|
|
80
99
|
const { container: fullscreenContainer } = useFullscreenPopoverContainer();
|
|
@@ -94,15 +113,15 @@ function Topbar<T>({
|
|
|
94
113
|
setLayoutAnchorEl(null);
|
|
95
114
|
};
|
|
96
115
|
|
|
97
|
-
// search
|
|
98
|
-
const [showSearchInput, setShowSearchInput] = useState(false);
|
|
99
|
-
const searchContainerRef = useRef<HTMLDivElement>(null);
|
|
100
|
-
|
|
101
116
|
useOutsideClick({
|
|
102
117
|
ref: searchContainerRef,
|
|
103
118
|
handler: () => setShowSearchInput(false),
|
|
104
119
|
});
|
|
105
120
|
|
|
121
|
+
const handleFilterDrawer = () => {
|
|
122
|
+
setShowFilterInput((prev) => !prev);
|
|
123
|
+
};
|
|
124
|
+
|
|
106
125
|
return (
|
|
107
126
|
<div className="ts-topbar">
|
|
108
127
|
<div className="tabs-section">{leftSideComponent}</div>
|
|
@@ -112,10 +131,12 @@ function Topbar<T>({
|
|
|
112
131
|
{paginationComponent}
|
|
113
132
|
|
|
114
133
|
{showSearch && (
|
|
115
|
-
<
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
134
|
+
<div title="Search">
|
|
135
|
+
<TableSearch
|
|
136
|
+
value={searchValue ?? ""}
|
|
137
|
+
onChange={onSearchChange ?? (() => {})}
|
|
138
|
+
/>
|
|
139
|
+
</div>
|
|
119
140
|
)}
|
|
120
141
|
|
|
121
142
|
{showChangeLayoutToggle && (
|
|
@@ -168,7 +189,7 @@ function Topbar<T>({
|
|
|
168
189
|
</>
|
|
169
190
|
)}
|
|
170
191
|
|
|
171
|
-
{
|
|
192
|
+
{showSortingToggle && (
|
|
172
193
|
<>
|
|
173
194
|
<div
|
|
174
195
|
className="filter ts--button"
|
|
@@ -189,9 +210,23 @@ function Topbar<T>({
|
|
|
189
210
|
</>
|
|
190
211
|
)}
|
|
191
212
|
|
|
192
|
-
{
|
|
193
|
-
<div
|
|
194
|
-
|
|
213
|
+
{showFilterToggle && (
|
|
214
|
+
<div
|
|
215
|
+
className="filter ts--button"
|
|
216
|
+
title="Filter"
|
|
217
|
+
onClick={() => setShowFilterInput(true)}
|
|
218
|
+
>
|
|
219
|
+
<FilterationIcon />
|
|
220
|
+
<FilterDrawer
|
|
221
|
+
tableStates={tableStates}
|
|
222
|
+
open={showFilterInput}
|
|
223
|
+
onClose={handleFilterDrawer}
|
|
224
|
+
onDeleteFilter={filterOptions?.onDeleteFilter}
|
|
225
|
+
columnsData={filterOptions.columnsData} // @ts-ignore
|
|
226
|
+
onSaveFilter={filterOptions?.onSaveFilter}
|
|
227
|
+
dropdownData={filterOptions.dropdownData}
|
|
228
|
+
onUpdateFilter={filterOptions?.onUpdateFilter}
|
|
229
|
+
/>
|
|
195
230
|
</div>
|
|
196
231
|
)}
|
|
197
232
|
|
|
@@ -202,10 +237,10 @@ function Topbar<T>({
|
|
|
202
237
|
onCompactToggle={(value: string) =>
|
|
203
238
|
setIsCompactTable(value === "Compact")
|
|
204
239
|
}
|
|
205
|
-
isFullscreen={
|
|
240
|
+
isFullscreen={isFullscreenState}
|
|
206
241
|
onFullscreenToggle={() => {
|
|
207
242
|
fullscreenToggle();
|
|
208
|
-
|
|
243
|
+
setIsFullscreenState((prev) => !prev);
|
|
209
244
|
}}
|
|
210
245
|
groupBy={groupBy}
|
|
211
246
|
onGroupByChange={(value: string) => setGroupBy(value)}
|
|
@@ -27,8 +27,8 @@ const ViewMore = ({
|
|
|
27
27
|
onCompactToggle,
|
|
28
28
|
isFullscreen,
|
|
29
29
|
onFullscreenToggle,
|
|
30
|
-
groupBy,
|
|
31
|
-
onGroupByChange,
|
|
30
|
+
// groupBy,
|
|
31
|
+
// onGroupByChange,
|
|
32
32
|
tableStates,
|
|
33
33
|
}: ViewMorePopoverProps) => {
|
|
34
34
|
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
|
@@ -6,6 +6,11 @@ import {
|
|
|
6
6
|
} from "@tanstack/react-table";
|
|
7
7
|
import { useState } from "react";
|
|
8
8
|
import { CraftTableOptionsProps } from "../../types/table-options";
|
|
9
|
+
import {
|
|
10
|
+
FilterMasterStateProps,
|
|
11
|
+
FilterOperationListProps,
|
|
12
|
+
FilterStateProps,
|
|
13
|
+
} from "../../types/filter";
|
|
9
14
|
|
|
10
15
|
export function useCraftTable(paginationPageSize: number = 25) {
|
|
11
16
|
const [pagination, setPagination] = useState<PaginationState>({
|
|
@@ -18,9 +23,20 @@ export function useCraftTable(paginationPageSize: number = 25) {
|
|
|
18
23
|
const [wrapColumns, setWrapColumns] = useState<Record<string, boolean>>({
|
|
19
24
|
all_wrap: true,
|
|
20
25
|
});
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
);
|
|
26
|
+
|
|
27
|
+
// Filters to be rendered in form
|
|
28
|
+
const [filters, setFilters] = useState<FilterStateProps[]>([]);
|
|
29
|
+
// Saved filter Component - savedFilterEditValue is set on list click
|
|
30
|
+
const [savedFilterEditValue, setSavedFilterEditValue] = useState<
|
|
31
|
+
string | number
|
|
32
|
+
>("");
|
|
33
|
+
const [filterToDelete, setFilterToDelete] =
|
|
34
|
+
useState<FilterOperationListProps | null>(null);
|
|
35
|
+
const [filterSelectedAttributeValue, setFilterSelectedAttributeValue] =
|
|
36
|
+
useState<string>("");
|
|
37
|
+
|
|
38
|
+
const [filterMaster, setFilterMaster] =
|
|
39
|
+
useState<FilterMasterStateProps | null>(null);
|
|
24
40
|
|
|
25
41
|
if (pagination.pageIndex < 0 || pagination.pageSize <= 0) {
|
|
26
42
|
throw new Error(
|
|
@@ -39,8 +55,16 @@ export function useCraftTable(paginationPageSize: number = 25) {
|
|
|
39
55
|
setExpanded: setExpanded,
|
|
40
56
|
wrapColumns: wrapColumns,
|
|
41
57
|
setWrapColumns: setWrapColumns,
|
|
42
|
-
|
|
43
|
-
|
|
58
|
+
filters: filters,
|
|
59
|
+
setFilters: setFilters,
|
|
60
|
+
savedFilterEditValue: savedFilterEditValue,
|
|
61
|
+
setSavedFilterEditValue: setSavedFilterEditValue,
|
|
62
|
+
filterToDelete: filterToDelete,
|
|
63
|
+
setFilterToDelete: setFilterToDelete,
|
|
64
|
+
filterSelectedAttributeValue: filterSelectedAttributeValue,
|
|
65
|
+
setFilterSelectedAttributeValue: setFilterSelectedAttributeValue,
|
|
66
|
+
filterMaster: filterMaster,
|
|
67
|
+
setFilterMaster: setFilterMaster,
|
|
44
68
|
};
|
|
45
69
|
|
|
46
70
|
return craftTableOptions;
|
|
@@ -11,7 +11,7 @@ export const useDefaultColumns = () => {
|
|
|
11
11
|
header: "First Name",
|
|
12
12
|
id: "firstName",
|
|
13
13
|
accessorKey: "firstName",
|
|
14
|
-
|
|
14
|
+
meta: { label: "First Name" },
|
|
15
15
|
// header: ({ table }) => (
|
|
16
16
|
// <>
|
|
17
17
|
// <button
|
|
@@ -58,7 +58,7 @@ export const useDefaultColumns = () => {
|
|
|
58
58
|
header: "Last Name",
|
|
59
59
|
accessorKey: "lastName",
|
|
60
60
|
size: 100,
|
|
61
|
-
meta: {
|
|
61
|
+
meta: { label: "Last Name" },
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
64
|
header: "Email Id",
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useMutation,
|
|
3
|
+
useQueries,
|
|
4
|
+
useQuery,
|
|
5
|
+
useQueryClient,
|
|
6
|
+
} from "@tanstack/react-query";
|
|
7
|
+
import { api, ENTITY_TYPE } from "../utils/common";
|
|
8
|
+
import {
|
|
9
|
+
APIParamsProps,
|
|
10
|
+
EntityListingResponse,
|
|
11
|
+
EntityTableAPIProps,
|
|
12
|
+
} from "../../types/common";
|
|
13
|
+
import {
|
|
14
|
+
commonGetDropdownDataAPI,
|
|
15
|
+
createSavedFilter,
|
|
16
|
+
deleteSavedFilter,
|
|
17
|
+
updateSavedFilter,
|
|
18
|
+
} from "../utils/apiColumn";
|
|
19
|
+
import { FilterColumnsDataProps } from "../../types/filter";
|
|
20
|
+
|
|
21
|
+
const entityListingCall = async ({
|
|
22
|
+
page,
|
|
23
|
+
size,
|
|
24
|
+
entity_type = ENTITY_TYPE,
|
|
25
|
+
tabs = {
|
|
26
|
+
columnName: "status",
|
|
27
|
+
sortBy: "ASC",
|
|
28
|
+
value: "",
|
|
29
|
+
},
|
|
30
|
+
sortby = [
|
|
31
|
+
{
|
|
32
|
+
sortColum: "name",
|
|
33
|
+
sortType: "ASC",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
sortColum: "status",
|
|
37
|
+
sortType: "DSC",
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
quickFilter = [],
|
|
41
|
+
attributeFilter = [],
|
|
42
|
+
}: EntityTableAPIProps): Promise<{
|
|
43
|
+
responseStatus: number;
|
|
44
|
+
data: EntityListingResponse;
|
|
45
|
+
}> => {
|
|
46
|
+
const url = `filter`;
|
|
47
|
+
|
|
48
|
+
const body = {
|
|
49
|
+
entity_type,
|
|
50
|
+
tabs,
|
|
51
|
+
sortby,
|
|
52
|
+
quickFilter,
|
|
53
|
+
attributeFilter,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const params: APIParamsProps = {
|
|
57
|
+
page,
|
|
58
|
+
size,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const response = await api.post(url, body, { params });
|
|
62
|
+
|
|
63
|
+
return { responseStatus: response.status, data: response.data };
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const useEntityTableAPI = ({
|
|
67
|
+
page = 0,
|
|
68
|
+
size = 50,
|
|
69
|
+
quickFilter = [],
|
|
70
|
+
}: EntityTableAPIProps) => {
|
|
71
|
+
const { data, isPending: isTableDataPending } = useQuery({
|
|
72
|
+
queryKey: [page, size, quickFilter],
|
|
73
|
+
queryFn: () =>
|
|
74
|
+
entityListingCall({
|
|
75
|
+
page,
|
|
76
|
+
size,
|
|
77
|
+
quickFilter,
|
|
78
|
+
}),
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
tableData: data?.data.data,
|
|
83
|
+
status: data?.responseStatus,
|
|
84
|
+
isTableDataPending,
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
//for saved filter API
|
|
89
|
+
export const useSavedFilterAPI = () => {
|
|
90
|
+
const queryClient = useQueryClient();
|
|
91
|
+
const savedMutation = useMutation({
|
|
92
|
+
mutationKey: ["savedFilter"],
|
|
93
|
+
mutationFn: ({
|
|
94
|
+
entity_type,
|
|
95
|
+
payload,
|
|
96
|
+
}: {
|
|
97
|
+
entity_type: string;
|
|
98
|
+
payload: any;
|
|
99
|
+
}) => {
|
|
100
|
+
return createSavedFilter(entity_type, payload);
|
|
101
|
+
},
|
|
102
|
+
onSuccess: () => {
|
|
103
|
+
queryClient.invalidateQueries({ queryKey: ["meta"] });
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
return { savedMutation };
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
//for delete filter API
|
|
111
|
+
export const useDeleteFilterAPI = () => {
|
|
112
|
+
const queryClient = useQueryClient();
|
|
113
|
+
const deleteMutation = useMutation({
|
|
114
|
+
mutationKey: ["deleteFilter"],
|
|
115
|
+
mutationFn: ({
|
|
116
|
+
entity_type,
|
|
117
|
+
payload,
|
|
118
|
+
}: {
|
|
119
|
+
entity_type: string;
|
|
120
|
+
payload: any;
|
|
121
|
+
}) => {
|
|
122
|
+
return deleteSavedFilter(entity_type, payload);
|
|
123
|
+
},
|
|
124
|
+
onSuccess: () => {
|
|
125
|
+
queryClient.invalidateQueries({ queryKey: ["meta"] });
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
return { deleteMutation };
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// for updating saved filter API
|
|
133
|
+
export const useUpdateFilterAPI = () => {
|
|
134
|
+
const queryClient = useQueryClient();
|
|
135
|
+
|
|
136
|
+
const updateMutation = useMutation({
|
|
137
|
+
mutationKey: ["updateFilter"],
|
|
138
|
+
mutationFn: ({
|
|
139
|
+
entity_type,
|
|
140
|
+
payload,
|
|
141
|
+
}: {
|
|
142
|
+
entity_type: string;
|
|
143
|
+
payload: any;
|
|
144
|
+
}) => {
|
|
145
|
+
return updateSavedFilter(entity_type, payload);
|
|
146
|
+
},
|
|
147
|
+
onSuccess: () => {
|
|
148
|
+
queryClient.invalidateQueries({ queryKey: ["meta"] });
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
return { updateMutation };
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
export const useCommonDropdownAPI = (
|
|
156
|
+
metaData?: FilterColumnsDataProps,
|
|
157
|
+
value?: string
|
|
158
|
+
) => {
|
|
159
|
+
// Step 1: Extract all keys and query types
|
|
160
|
+
const dropdownConfigs = (metaData?.column_list || [])
|
|
161
|
+
.filter((col) => col?.datasource_list)
|
|
162
|
+
.map((col) => ({
|
|
163
|
+
key: col.attribute_key,
|
|
164
|
+
dataSourceType: value ?? col.datasource_list ?? "STS",
|
|
165
|
+
}));
|
|
166
|
+
|
|
167
|
+
// Step 2: Use useQueries to fetch them all in parallel
|
|
168
|
+
const dropdownResults = useQueries({
|
|
169
|
+
queries: dropdownConfigs.map((cfg) => ({
|
|
170
|
+
queryKey: ["commonDropdown", cfg.dataSourceType],
|
|
171
|
+
queryFn: () => commonGetDropdownDataAPI(cfg.dataSourceType, null),
|
|
172
|
+
enabled: !!cfg.dataSourceType,
|
|
173
|
+
})),
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Step 3: Map results to keys
|
|
177
|
+
const dropdownData: Record<string, any> = {};
|
|
178
|
+
dropdownConfigs.forEach((cfg, idx) => {
|
|
179
|
+
dropdownData[cfg.key] = dropdownResults[idx].data;
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
return { dropdownData };
|
|
183
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useQuery } from "@tanstack/react-query";
|
|
2
|
+
import {
|
|
3
|
+
entityTableFilterMaster,
|
|
4
|
+
fetchDetailsByFilterId,
|
|
5
|
+
} from "../utils/apiColumn";
|
|
6
|
+
|
|
7
|
+
export const useDetailsQueryAPI = (value: string) => {
|
|
8
|
+
const detailsQuery = useQuery({
|
|
9
|
+
queryKey: ["details", value],
|
|
10
|
+
queryFn: () => fetchDetailsByFilterId(value),
|
|
11
|
+
enabled: !!value, // This ensures that the second query only runs if the first one has data
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
return { detailsQuery };
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const useFetchData = (entity_type: string) => {
|
|
18
|
+
// First query to get meta data
|
|
19
|
+
const metaQuery = useQuery({
|
|
20
|
+
queryKey: ["meta", entity_type],
|
|
21
|
+
queryFn: () => entityTableFilterMaster(entity_type),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return { metaQuery };
|
|
25
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { api } from "./common";
|
|
2
|
+
import {
|
|
3
|
+
createSavedFilterPaload,
|
|
4
|
+
deleteSavedFilterPayload,
|
|
5
|
+
updateSavedFilterPayload,
|
|
6
|
+
} from "../../types/filter";
|
|
7
|
+
|
|
8
|
+
export const entityTableMetaMaster = async (entity_type: string) => {
|
|
9
|
+
try {
|
|
10
|
+
const response = await api.post(
|
|
11
|
+
`/meta/get-table-data?entity_type=${entity_type}&list_type=${entity_type}`
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
const rawColumns = response.data?.data?.column_list || [];
|
|
15
|
+
|
|
16
|
+
const res = rawColumns.map((item: any) => ({
|
|
17
|
+
id: item.attribute_key,
|
|
18
|
+
accessorKey: item.attribute_key,
|
|
19
|
+
header: item.name,
|
|
20
|
+
}));
|
|
21
|
+
return { res };
|
|
22
|
+
} catch (error) {
|
|
23
|
+
console.error("Failed to fetch table meta:", error);
|
|
24
|
+
return { res: [] };
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const entityTableFilterMaster = async (entity_type: string) => {
|
|
29
|
+
try {
|
|
30
|
+
const response = await api.post(
|
|
31
|
+
`/meta/get-table-data?entity_type=${entity_type}&list_type=${entity_type}`
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const filteredData = {
|
|
35
|
+
...response.data.data,
|
|
36
|
+
column_list: response.data.data.column_list.filter(
|
|
37
|
+
(item: any) => item.attribute_key !== "action"
|
|
38
|
+
),
|
|
39
|
+
};
|
|
40
|
+
// console.log("response", filteredData.column_list);
|
|
41
|
+
// return response.data.data;
|
|
42
|
+
return filteredData; // FOR ACTION COLUMN REMOVE
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.error("Failed to fetch filter operation list meta:", error);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const fetchDetailsByFilterId = async (filterId: string) => {
|
|
49
|
+
const response = await api.get(`/filter/${filterId}`);
|
|
50
|
+
return response.data;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const commonGetDropdownDataAPI = async (
|
|
54
|
+
entity_type: string,
|
|
55
|
+
organization_id?: string | null,
|
|
56
|
+
data?: any
|
|
57
|
+
) => {
|
|
58
|
+
try {
|
|
59
|
+
const requestBody = {
|
|
60
|
+
status: "ACTIVE",
|
|
61
|
+
organization_id: organization_id,
|
|
62
|
+
...data,
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const response = await api.post(
|
|
66
|
+
`/list-master/getDropdownData/${entity_type}`,
|
|
67
|
+
requestBody
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
return response.data;
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.error("Failed to fetch dropdown data:", error);
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const createSavedFilter = async (
|
|
78
|
+
entity_type: string,
|
|
79
|
+
payload: createSavedFilterPaload
|
|
80
|
+
) => {
|
|
81
|
+
try {
|
|
82
|
+
const response = await api.post(
|
|
83
|
+
`/entity/create?entity_type=${entity_type}`,
|
|
84
|
+
payload
|
|
85
|
+
);
|
|
86
|
+
return response.data;
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.error("Failed to fetch saved filter list:", error);
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export const deleteSavedFilter = async (
|
|
94
|
+
entity_type: string,
|
|
95
|
+
payload: deleteSavedFilterPayload
|
|
96
|
+
) => {
|
|
97
|
+
try {
|
|
98
|
+
const response = await api.post(
|
|
99
|
+
`/entity/update/17?entity_type=${entity_type}`,
|
|
100
|
+
payload
|
|
101
|
+
);
|
|
102
|
+
return response.data;
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.error("Failed to delete saved filter:", error);
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export const updateSavedFilter = async (
|
|
110
|
+
entity_type: string,
|
|
111
|
+
payload: updateSavedFilterPayload
|
|
112
|
+
) => {
|
|
113
|
+
try {
|
|
114
|
+
const response = await api.post(
|
|
115
|
+
`/entity/update/17?entity_type=${entity_type}`,
|
|
116
|
+
payload
|
|
117
|
+
);
|
|
118
|
+
return response.data;
|
|
119
|
+
} catch (error) {
|
|
120
|
+
console.error("Failed to update saved filter:", error);
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
};
|
package/src/libs/utils/common.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Column } from "@tanstack/react-table";
|
|
2
2
|
import { alignProps } from "../../types/common";
|
|
3
3
|
import { CSSProperties } from "react";
|
|
4
|
+
import axios from "axios";
|
|
4
5
|
|
|
5
6
|
export const formatClassName = (className: string): string => {
|
|
6
7
|
return className.replace(/\s+/g, " ").trim();
|
|
@@ -60,3 +61,44 @@ export const getColumnPinningStylesBody = <T>(
|
|
|
60
61
|
width: column.getSize(),
|
|
61
62
|
};
|
|
62
63
|
};
|
|
64
|
+
|
|
65
|
+
export function customDebounce<T extends (...args: any[]) => any>(
|
|
66
|
+
func: T,
|
|
67
|
+
delay: number
|
|
68
|
+
): (...args: Parameters<T>) => void {
|
|
69
|
+
let timerId: ReturnType<typeof setTimeout> | null = null;
|
|
70
|
+
|
|
71
|
+
return function (this: ThisParameterType<T>, ...args: Parameters<T>): void {
|
|
72
|
+
if (timerId) clearTimeout(timerId);
|
|
73
|
+
timerId = setTimeout(() => {
|
|
74
|
+
func.apply(this, args);
|
|
75
|
+
}, delay);
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// uat http://13.200.182.92:9091/api
|
|
80
|
+
// local http://localhost:9091/api
|
|
81
|
+
|
|
82
|
+
// API INTEGRATION
|
|
83
|
+
export const api = axios.create({
|
|
84
|
+
baseURL: "http://13.200.182.92:9091/api",
|
|
85
|
+
timeout: 10000,
|
|
86
|
+
headers: {
|
|
87
|
+
"Content-Type": "application/json",
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
api.interceptors.request.use(
|
|
92
|
+
(config) => {
|
|
93
|
+
const token = localStorage.getItem("authToken");
|
|
94
|
+
if (token) {
|
|
95
|
+
config.headers.Authorization = `Bearer ${token}`;
|
|
96
|
+
}
|
|
97
|
+
return config;
|
|
98
|
+
},
|
|
99
|
+
(error) => {
|
|
100
|
+
return Promise.reject(error);
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
export const ENTITY_TYPE = "UPR";
|
package/src/main.tsx
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import ReactDOM from "react-dom/client";
|
|
3
3
|
import App from "./App.tsx";
|
|
4
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
4
5
|
|
|
5
6
|
ReactDOM.createRoot(document.getElementById("root")!).render(
|
|
6
|
-
<
|
|
7
|
-
<
|
|
8
|
-
|
|
7
|
+
<QueryClientProvider client={new QueryClient()}>
|
|
8
|
+
<React.StrictMode>
|
|
9
|
+
<App />
|
|
10
|
+
</React.StrictMode>
|
|
11
|
+
</QueryClientProvider>
|
|
9
12
|
);
|