@djb25/digit-ui-module-ekyc 1.0.14 → 1.0.15
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/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.modern.js +3334 -3345
- package/dist/index.modern.js.map +1 -1
- package/package.json +1 -1
- package/src/components/AssignEkyc.js +317 -0
- package/src/components/AssignEkycModal.js +362 -0
- package/src/components/EKYCCard.js +6 -4
- package/src/components/Review.js +155 -88
- package/src/components/StatusCards.js +6 -17
- package/src/components/SurveyorDetailsCard.js +282 -0
- package/src/components/VendorDetails.jsx +18 -1
- package/src/hook/SupervisorInboxTableConfig.js +138 -0
- package/src/hook/useInboxTableConfig.js +4 -3
- package/src/pages/citizen/Home.js +27 -14
- package/src/pages/citizen/index.js +48 -1
- package/src/pages/employee/index.js +94 -85
package/package.json
CHANGED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import React, { useMemo, useCallback, useReducer, useState } from "react";
|
|
2
|
+
import { useLocation } from "react-router-dom";
|
|
3
|
+
import { InboxComposer } from "@djb25/digit-ui-react-components";
|
|
4
|
+
import SupervisorInboxTableConfig from "../hook/SupervisorInboxTableConfig";
|
|
5
|
+
import SearchFormFieldsComponents from "./SearchFormFieldsComponent";
|
|
6
|
+
|
|
7
|
+
// Mock data removed in favor of API integration
|
|
8
|
+
|
|
9
|
+
const AssignEkyc = () => {
|
|
10
|
+
const tenantId = Digit.ULBService.getCurrentTenantId();
|
|
11
|
+
const location = useLocation();
|
|
12
|
+
const [sortParams, setSortParams] = useState([{ id: "", desc: true }]);
|
|
13
|
+
const [pageOffset, setPageOffset] = useState(0);
|
|
14
|
+
const [pageSize, setPageSize] = useState(10);
|
|
15
|
+
let paginationParms = { limit: pageSize, offset: pageOffset, sortBy: sortParams?.[0]?.id, sortOrder: sortParams?.[0]?.desc ? "DESC" : "ASC" };
|
|
16
|
+
|
|
17
|
+
const formInitValue = {
|
|
18
|
+
filterForm: {},
|
|
19
|
+
searchForm: {},
|
|
20
|
+
tableForm: {
|
|
21
|
+
limit: 10,
|
|
22
|
+
offset: 0,
|
|
23
|
+
sortBy: "createdTime",
|
|
24
|
+
sortOrder: "DESC",
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const [formState, dispatch] = useReducer(formReducer, formInitValue);
|
|
29
|
+
|
|
30
|
+
const { data: dashboardData, isLoading } = Digit.Hooks.fsm.useSurveyorSearch(
|
|
31
|
+
tenantId,
|
|
32
|
+
{ ...paginationParms, status: "ACTIVE,DISABLED" },
|
|
33
|
+
{ enabled: !!tenantId, keepPreviousData: true }
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const handleSort = useCallback((args) => {
|
|
37
|
+
if (args?.length === 0) return;
|
|
38
|
+
setSortParams(args);
|
|
39
|
+
}, []);
|
|
40
|
+
|
|
41
|
+
const fetchNextPage = () => {
|
|
42
|
+
setPageOffset((prevState) => prevState + pageSize);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const fetchPrevPage = () => {
|
|
46
|
+
setPageOffset((prevState) => prevState - pageSize);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const handlePageSizeChange = (e) => {
|
|
50
|
+
setPageSize(Number(e.target.value));
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const searchDetails = useMemo(
|
|
54
|
+
() => ({
|
|
55
|
+
kno: formState?.searchForm?.kNumber || "",
|
|
56
|
+
name: formState?.searchForm?.kName || "",
|
|
57
|
+
}),
|
|
58
|
+
[formState?.searchForm?.kNumber, formState?.searchForm?.kName]
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const isSearchActive = !!(searchDetails.kno || searchDetails.name);
|
|
62
|
+
|
|
63
|
+
const { isLoading: isSearchLoading, data: searchData } = Digit.Hooks.ekyc.useSearchConnection(
|
|
64
|
+
{
|
|
65
|
+
tenantId,
|
|
66
|
+
details: searchDetails,
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
enabled: !!tenantId && !!searchDetails.kno, // 🔥 important
|
|
70
|
+
keepPreviousData: true,
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const sourceData = useMemo(() => {
|
|
75
|
+
if (isSearchActive) {
|
|
76
|
+
if (!searchData) return [];
|
|
77
|
+
return [searchData];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return dashboardData?.surveyors || [];
|
|
81
|
+
}, [isSearchActive, searchData, dashboardData]);
|
|
82
|
+
|
|
83
|
+
const filteredData = useMemo(() => {
|
|
84
|
+
return (sourceData || []).map((item) => {
|
|
85
|
+
const owner = item?.owner || {};
|
|
86
|
+
|
|
87
|
+
const roleCodes = owner?.roles?.map((role) => role.code)?.join(", ") || "";
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
...item,
|
|
91
|
+
|
|
92
|
+
id: item?.id || "",
|
|
93
|
+
|
|
94
|
+
surveyorName: item?.name || owner?.name || "",
|
|
95
|
+
|
|
96
|
+
mobileNo: item?.mobileNo || owner?.mobileNumber || "",
|
|
97
|
+
|
|
98
|
+
email: owner?.emailId || "",
|
|
99
|
+
|
|
100
|
+
vendorId: item?.vendorId || "",
|
|
101
|
+
|
|
102
|
+
tenantId: item?.tenantId || "",
|
|
103
|
+
|
|
104
|
+
supervisorId: item?.supervisorId || "",
|
|
105
|
+
|
|
106
|
+
status: item?.status || "",
|
|
107
|
+
|
|
108
|
+
roleCodes,
|
|
109
|
+
|
|
110
|
+
userName: owner?.userName || "",
|
|
111
|
+
|
|
112
|
+
gender: owner?.gender || "",
|
|
113
|
+
|
|
114
|
+
serviceType: item?.additionalDetails?.serviceType || "",
|
|
115
|
+
|
|
116
|
+
createdTime: item?.auditDetails?.createdTime || 0,
|
|
117
|
+
|
|
118
|
+
lastModifiedTime: item?.auditDetails?.lastModifiedTime || 0,
|
|
119
|
+
};
|
|
120
|
+
});
|
|
121
|
+
}, [sourceData]);
|
|
122
|
+
|
|
123
|
+
const totalRecords = dashboardData?.dashboardInfo?.totalRecords || dashboardData?.totalCount || 0;
|
|
124
|
+
|
|
125
|
+
const checkPathName = location.pathname.includes("ekyc/inbox");
|
|
126
|
+
const PropsForInboxLinks = {
|
|
127
|
+
headerText: checkPathName ? "EKYC_MODULE" : "MODULE_SW",
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const SearchFormFields = useCallback(
|
|
131
|
+
({ registerRef, searchFormState, controlSearchForm }) => (
|
|
132
|
+
<SearchFormFieldsComponents {...{ registerRef, searchFormState, controlSearchForm }} className="search" />
|
|
133
|
+
),
|
|
134
|
+
[]
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
const tableOrderFormDefaultValues = {
|
|
138
|
+
sortBy: "createdTime",
|
|
139
|
+
limit: window.Digit.Utils.browser.isMobile() ? 50 : 10,
|
|
140
|
+
offset: 0,
|
|
141
|
+
sortOrder: "DESC",
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const onSearchFormSubmit = (data) => {
|
|
145
|
+
data.hasOwnProperty("") && delete data?.[""];
|
|
146
|
+
dispatch({ action: "mutateTableForm", data: { ...tableOrderFormDefaultValues }, checkPathName });
|
|
147
|
+
dispatch({ action: "mutateSearchForm", data, checkPathName });
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const searchFormDefaultValues = {
|
|
151
|
+
mobileNumber: "",
|
|
152
|
+
applicationNumber: "",
|
|
153
|
+
consumerNo: "",
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const onSearchFormReset = (setSearchFormValue) => {
|
|
157
|
+
setSearchFormValue("mobileNumber", null);
|
|
158
|
+
setSearchFormValue("applicationNumber", null);
|
|
159
|
+
setSearchFormValue("consumerNo", null);
|
|
160
|
+
dispatch({ action: "mutateSearchForm", data: searchFormDefaultValues });
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const propsForSearchForm = {
|
|
164
|
+
SearchFormFields,
|
|
165
|
+
onSearchFormSubmit,
|
|
166
|
+
searchFormDefaultValues: formState?.searchForm,
|
|
167
|
+
resetSearchFormDefaultValues: searchFormDefaultValues,
|
|
168
|
+
onSearchFormReset,
|
|
169
|
+
className: "search-form-wns-inbox",
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const FilterFormFields = useCallback(
|
|
173
|
+
({ registerRef, controlFilterForm, setFilterFormValue, getFilterFormValue }) => <React.Fragment></React.Fragment>,
|
|
174
|
+
[]
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
const propsForFilterForm = {
|
|
178
|
+
FilterFormFields,
|
|
179
|
+
onFilterFormSubmit: () => {},
|
|
180
|
+
filterFormDefaultValues: "",
|
|
181
|
+
resetFilterFormDefaultValues: "",
|
|
182
|
+
onFilterFormReset: () => {},
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
function formReducer(state, payload) {
|
|
186
|
+
const storageKey = payload.checkPathName ? "EKYC.INBOX" : "EKYC.SW.INBOX";
|
|
187
|
+
|
|
188
|
+
// ✅ safety for SLA
|
|
189
|
+
switch (payload.action) {
|
|
190
|
+
case "mutateSearchForm":
|
|
191
|
+
Digit.SessionStorage.set(storageKey, { ...state, searchForm: payload.data });
|
|
192
|
+
return { ...state, searchForm: payload.data };
|
|
193
|
+
|
|
194
|
+
case "mutateFilterForm":
|
|
195
|
+
Digit.SessionStorage.set(storageKey, { ...state, filterForm: payload.data });
|
|
196
|
+
return { ...state, filterForm: payload.data };
|
|
197
|
+
|
|
198
|
+
case "mutateTableForm":
|
|
199
|
+
Digit.SessionStorage.set(storageKey, { ...state, tableForm: payload.data });
|
|
200
|
+
return { ...state, tableForm: payload.data };
|
|
201
|
+
|
|
202
|
+
default:
|
|
203
|
+
return state; // ✅ IMPORTANT
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const onPageSizeChange = (e) => {
|
|
208
|
+
const newLimit = Number(e.target.value);
|
|
209
|
+
|
|
210
|
+
dispatch({
|
|
211
|
+
action: "mutateTableForm",
|
|
212
|
+
data: {
|
|
213
|
+
...formState.tableForm,
|
|
214
|
+
limit: newLimit,
|
|
215
|
+
offset: 0, // reset page
|
|
216
|
+
},
|
|
217
|
+
checkPathName,
|
|
218
|
+
});
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
const onSortingByData = (e) => {
|
|
222
|
+
if (e.length > 0) {
|
|
223
|
+
const [{ id, desc }] = e;
|
|
224
|
+
const sortOrder = desc ? "DESC" : "ASC";
|
|
225
|
+
const sortBy = id;
|
|
226
|
+
|
|
227
|
+
if (!(formState.tableForm.sortBy === sortBy && formState.tableForm.sortOrder === sortOrder)) {
|
|
228
|
+
dispatch({
|
|
229
|
+
action: "mutateTableForm",
|
|
230
|
+
data: {
|
|
231
|
+
...formState.tableForm,
|
|
232
|
+
sortBy: id,
|
|
233
|
+
sortOrder: desc ? "DESC" : "ASC",
|
|
234
|
+
},
|
|
235
|
+
checkPathName,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const propsForInboxTable = SupervisorInboxTableConfig({
|
|
242
|
+
...{
|
|
243
|
+
onPageSizeChange,
|
|
244
|
+
formState,
|
|
245
|
+
totalCount: totalRecords,
|
|
246
|
+
table: filteredData,
|
|
247
|
+
dispatch,
|
|
248
|
+
onSortingByData,
|
|
249
|
+
tenantId,
|
|
250
|
+
checkPathName,
|
|
251
|
+
inboxStyles: { overflowX: "scroll", overflowY: "hidden" },
|
|
252
|
+
tableStyle: { width: "70%" },
|
|
253
|
+
},
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
const isInboxLoading = isLoading || isSearchLoading;
|
|
257
|
+
|
|
258
|
+
const cards = [
|
|
259
|
+
{
|
|
260
|
+
label: "TOTAL_EKYC_APPLICATIONS",
|
|
261
|
+
count: 364,
|
|
262
|
+
color: "#0B2559",
|
|
263
|
+
filter: null,
|
|
264
|
+
active: true,
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
label: "UNASSIGNED_APPLICATIONS",
|
|
268
|
+
count: 28,
|
|
269
|
+
color: "#F59E0B",
|
|
270
|
+
filter: ["UNASSIGNED"],
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
label: "ASSIGNED_TO_SURVEYOR",
|
|
274
|
+
count: 120,
|
|
275
|
+
color: "#3B82F6",
|
|
276
|
+
filter: ["ASSIGNED"],
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
label: "IN_PROGRESS",
|
|
280
|
+
count: 54,
|
|
281
|
+
color: "#A855F7",
|
|
282
|
+
filter: ["IN_PROGRESS"],
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
label: "EKYC_COMPLETED",
|
|
286
|
+
count: 140,
|
|
287
|
+
color: "#10B981",
|
|
288
|
+
filter: ["COMPLETED"],
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
label: "REJECTED_APPLICATIONS",
|
|
292
|
+
count: 22,
|
|
293
|
+
color: "#EF4444",
|
|
294
|
+
filter: ["REJECTED"],
|
|
295
|
+
},
|
|
296
|
+
];
|
|
297
|
+
return (
|
|
298
|
+
<div className="app-container">
|
|
299
|
+
<InboxComposer
|
|
300
|
+
{...{
|
|
301
|
+
isInboxLoading,
|
|
302
|
+
PropsForInboxLinks,
|
|
303
|
+
...propsForSearchForm,
|
|
304
|
+
...propsForFilterForm,
|
|
305
|
+
// ...propsForMobileSortForm,
|
|
306
|
+
propsForInboxTable,
|
|
307
|
+
// propsForInboxMobileCards,
|
|
308
|
+
formState,
|
|
309
|
+
countData: dashboardData?.dashboardInfo,
|
|
310
|
+
cards,
|
|
311
|
+
}}
|
|
312
|
+
/>
|
|
313
|
+
</div>
|
|
314
|
+
);
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
export default AssignEkyc;
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import React, { useMemo, useState } from "react";
|
|
2
|
+
import { Modal, Close } from "@djb25/digit-ui-react-components";
|
|
3
|
+
|
|
4
|
+
const AssignEkycModal = ({ surveyor, closeModal }) => {
|
|
5
|
+
const [selectedKnos, setSelectedKnos] = useState([]);
|
|
6
|
+
|
|
7
|
+
const [filters, setFilters] = useState({
|
|
8
|
+
pincode: "",
|
|
9
|
+
locality: "",
|
|
10
|
+
status: "",
|
|
11
|
+
route: "",
|
|
12
|
+
search: "",
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
16
|
+
const knoList = [
|
|
17
|
+
{
|
|
18
|
+
kno: "1029384756",
|
|
19
|
+
consumerName: "Rahul Sharma",
|
|
20
|
+
locality: "Rohini",
|
|
21
|
+
pincode: "110085",
|
|
22
|
+
status: "PENDING",
|
|
23
|
+
route: "R1",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
kno: "9283746555",
|
|
27
|
+
consumerName: "Amit Kumar",
|
|
28
|
+
locality: "Pitampura",
|
|
29
|
+
pincode: "110034",
|
|
30
|
+
status: "VERIFIED",
|
|
31
|
+
route: "R2",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
kno: "8473625147",
|
|
35
|
+
consumerName: "Neha Verma",
|
|
36
|
+
locality: "Dwarka",
|
|
37
|
+
pincode: "110075",
|
|
38
|
+
status: "PENDING",
|
|
39
|
+
route: "R3",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
kno: "5647382910",
|
|
43
|
+
consumerName: "Sanjay Singh",
|
|
44
|
+
locality: "Janakpuri",
|
|
45
|
+
pincode: "110058",
|
|
46
|
+
status: "ASSIGNED",
|
|
47
|
+
route: "R1",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
kno: "9182736450",
|
|
51
|
+
consumerName: "Priya Mehta",
|
|
52
|
+
locality: "Laxmi Nagar",
|
|
53
|
+
pincode: "110092",
|
|
54
|
+
status: "PENDING",
|
|
55
|
+
route: "R4",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
kno: "7463829105",
|
|
59
|
+
consumerName: "Vikas Gupta",
|
|
60
|
+
locality: "Karol Bagh",
|
|
61
|
+
pincode: "110005",
|
|
62
|
+
status: "VERIFIED",
|
|
63
|
+
route: "R2",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
kno: "1122334455",
|
|
67
|
+
consumerName: "Anjali Kapoor",
|
|
68
|
+
locality: "Saket",
|
|
69
|
+
pincode: "110017",
|
|
70
|
+
status: "PENDING",
|
|
71
|
+
route: "R5",
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
kno: "6677889900",
|
|
75
|
+
consumerName: "Rohit Yadav",
|
|
76
|
+
locality: "Uttam Nagar",
|
|
77
|
+
pincode: "110059",
|
|
78
|
+
status: "ASSIGNED",
|
|
79
|
+
route: "R3",
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
kno: "8899776655",
|
|
83
|
+
consumerName: "Deepak Chauhan",
|
|
84
|
+
locality: "Burari",
|
|
85
|
+
pincode: "110084",
|
|
86
|
+
status: "PENDING",
|
|
87
|
+
route: "R6",
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
kno: "5544332211",
|
|
91
|
+
consumerName: "Sneha Arora",
|
|
92
|
+
locality: "Shahdara",
|
|
93
|
+
pincode: "110032",
|
|
94
|
+
status: "VERIFIED",
|
|
95
|
+
route: "R4",
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
kno: "3344556677",
|
|
99
|
+
consumerName: "Karan Malhotra",
|
|
100
|
+
locality: "Mayur Vihar",
|
|
101
|
+
pincode: "110091",
|
|
102
|
+
status: "PENDING",
|
|
103
|
+
route: "R7",
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
kno: "9988776654",
|
|
107
|
+
consumerName: "Pooja Bansal",
|
|
108
|
+
locality: "Patel Nagar",
|
|
109
|
+
pincode: "110008",
|
|
110
|
+
status: "ASSIGNED",
|
|
111
|
+
route: "R5",
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
kno: "7766554433",
|
|
115
|
+
consumerName: "Harsh Jain",
|
|
116
|
+
locality: "Punjabi Bagh",
|
|
117
|
+
pincode: "110026",
|
|
118
|
+
status: "PENDING",
|
|
119
|
+
route: "R8",
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
kno: "2233445566",
|
|
123
|
+
consumerName: "Nitin Sharma",
|
|
124
|
+
locality: "Rajouri Garden",
|
|
125
|
+
pincode: "110027",
|
|
126
|
+
status: "VERIFIED",
|
|
127
|
+
route: "R1",
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
kno: "4433221100",
|
|
131
|
+
consumerName: "Megha Sethi",
|
|
132
|
+
locality: "Ashok Vihar",
|
|
133
|
+
pincode: "110052",
|
|
134
|
+
status: "PENDING",
|
|
135
|
+
route: "R9",
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
kno: "1010101010",
|
|
139
|
+
consumerName: "Aditya Rana",
|
|
140
|
+
locality: "Model Town",
|
|
141
|
+
pincode: "110009",
|
|
142
|
+
status: "ASSIGNED",
|
|
143
|
+
route: "R10",
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
kno: "2020202020",
|
|
147
|
+
consumerName: "Simran Kaur",
|
|
148
|
+
locality: "Tilak Nagar",
|
|
149
|
+
pincode: "110018",
|
|
150
|
+
status: "PENDING",
|
|
151
|
+
route: "R11",
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
kno: "3030303030",
|
|
155
|
+
consumerName: "Mohit Saini",
|
|
156
|
+
locality: "Narela",
|
|
157
|
+
pincode: "110040",
|
|
158
|
+
status: "VERIFIED",
|
|
159
|
+
route: "R6",
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
kno: "4040404040",
|
|
163
|
+
consumerName: "Ritika Sharma",
|
|
164
|
+
locality: "Bawana",
|
|
165
|
+
pincode: "110039",
|
|
166
|
+
status: "PENDING",
|
|
167
|
+
route: "R7",
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
kno: "5050505050",
|
|
171
|
+
consumerName: "Yash Aggarwal",
|
|
172
|
+
locality: "Okhla",
|
|
173
|
+
pincode: "110020",
|
|
174
|
+
status: "ASSIGNED",
|
|
175
|
+
route: "R8",
|
|
176
|
+
},
|
|
177
|
+
];
|
|
178
|
+
|
|
179
|
+
const filteredKnos = useMemo(() => {
|
|
180
|
+
return knoList.filter((item) => {
|
|
181
|
+
const matchesPincode = filters.pincode ? item.pincode.includes(filters.pincode) : true;
|
|
182
|
+
|
|
183
|
+
const matchesLocality = filters.locality ? item.locality.toLowerCase().includes(filters.locality.toLowerCase()) : true;
|
|
184
|
+
|
|
185
|
+
const matchesStatus = filters.status ? item.status === filters.status : true;
|
|
186
|
+
|
|
187
|
+
const matchesRoute = filters.route ? item.route.toLowerCase().includes(filters.route.toLowerCase()) : true;
|
|
188
|
+
|
|
189
|
+
const matchesSearch = filters.search
|
|
190
|
+
? item.kno.includes(filters.search) || item.consumerName.toLowerCase().includes(filters.search.toLowerCase())
|
|
191
|
+
: true;
|
|
192
|
+
|
|
193
|
+
return matchesPincode && matchesLocality && matchesStatus && matchesRoute && matchesSearch;
|
|
194
|
+
});
|
|
195
|
+
}, [filters, knoList]);
|
|
196
|
+
|
|
197
|
+
const handleSelect = (kno) => {
|
|
198
|
+
setSelectedKnos((prev) => (prev.includes(kno) ? prev.filter((item) => item !== kno) : [...prev, kno]));
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const handleSelectAll = () => {
|
|
202
|
+
const visibleKnos = filteredKnos.map((item) => item.kno);
|
|
203
|
+
|
|
204
|
+
const allSelected = visibleKnos.every((kno) => selectedKnos.includes(kno));
|
|
205
|
+
|
|
206
|
+
if (allSelected) {
|
|
207
|
+
setSelectedKnos((prev) => prev.filter((kno) => !visibleKnos.includes(kno)));
|
|
208
|
+
} else {
|
|
209
|
+
setSelectedKnos((prev) => [...new Set([...prev, ...visibleKnos])]);
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
const handleAssign = () => {
|
|
214
|
+
const payload = {
|
|
215
|
+
surveyorId: surveyor?.uuid,
|
|
216
|
+
knos: selectedKnos,
|
|
217
|
+
filters,
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
console.log(payload);
|
|
221
|
+
|
|
222
|
+
closeModal();
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
return (
|
|
226
|
+
<Modal
|
|
227
|
+
headerBarMain={`Assign KNOs to ${surveyor?.name}`}
|
|
228
|
+
headerBarEnd={<Close onClick={closeModal} />}
|
|
229
|
+
actionCancelLabel="Cancel"
|
|
230
|
+
actionCancelOnSubmit={closeModal}
|
|
231
|
+
actionSaveLabel={`Assign ${selectedKnos.length} KNOs`}
|
|
232
|
+
actionSaveOnSubmit={handleAssign}
|
|
233
|
+
>
|
|
234
|
+
<div className="assign-knos-modal">
|
|
235
|
+
{/* Filters */}
|
|
236
|
+
<div className="filters-grid">
|
|
237
|
+
<input
|
|
238
|
+
className="form-control"
|
|
239
|
+
placeholder="Search by KNO / Consumer"
|
|
240
|
+
value={filters.search}
|
|
241
|
+
onChange={(e) =>
|
|
242
|
+
setFilters({
|
|
243
|
+
...filters,
|
|
244
|
+
search: e.target.value,
|
|
245
|
+
})
|
|
246
|
+
}
|
|
247
|
+
/>
|
|
248
|
+
|
|
249
|
+
<input
|
|
250
|
+
className="form-control"
|
|
251
|
+
placeholder="Pincode"
|
|
252
|
+
value={filters.pincode}
|
|
253
|
+
onChange={(e) =>
|
|
254
|
+
setFilters({
|
|
255
|
+
...filters,
|
|
256
|
+
pincode: e.target.value,
|
|
257
|
+
})
|
|
258
|
+
}
|
|
259
|
+
/>
|
|
260
|
+
|
|
261
|
+
<input
|
|
262
|
+
className="form-control"
|
|
263
|
+
placeholder="Locality"
|
|
264
|
+
value={filters.locality}
|
|
265
|
+
onChange={(e) =>
|
|
266
|
+
setFilters({
|
|
267
|
+
...filters,
|
|
268
|
+
locality: e.target.value,
|
|
269
|
+
})
|
|
270
|
+
}
|
|
271
|
+
/>
|
|
272
|
+
|
|
273
|
+
<input
|
|
274
|
+
className="form-control"
|
|
275
|
+
placeholder="Route"
|
|
276
|
+
value={filters.route}
|
|
277
|
+
onChange={(e) =>
|
|
278
|
+
setFilters({
|
|
279
|
+
...filters,
|
|
280
|
+
route: e.target.value,
|
|
281
|
+
})
|
|
282
|
+
}
|
|
283
|
+
/>
|
|
284
|
+
|
|
285
|
+
<select
|
|
286
|
+
className="form-control"
|
|
287
|
+
value={filters.status}
|
|
288
|
+
onChange={(e) =>
|
|
289
|
+
setFilters({
|
|
290
|
+
...filters,
|
|
291
|
+
status: e.target.value,
|
|
292
|
+
})
|
|
293
|
+
}
|
|
294
|
+
>
|
|
295
|
+
<option value="">All Status</option>
|
|
296
|
+
<option value="PENDING">Pending</option>
|
|
297
|
+
<option value="VERIFIED">Verified</option>
|
|
298
|
+
<option value="ASSIGNED">Assigned</option>
|
|
299
|
+
</select>
|
|
300
|
+
</div>
|
|
301
|
+
|
|
302
|
+
{/* Summary */}
|
|
303
|
+
<div className="summary-bar">
|
|
304
|
+
<div>Total Records: {filteredKnos.length}</div>
|
|
305
|
+
<div>Selected KNOs: {selectedKnos.length}</div>
|
|
306
|
+
</div>
|
|
307
|
+
|
|
308
|
+
{/* Table */}
|
|
309
|
+
<div className="table-wrapper">
|
|
310
|
+
{/* Header */}
|
|
311
|
+
<div className="table-header">
|
|
312
|
+
<div>
|
|
313
|
+
<input
|
|
314
|
+
type="checkbox"
|
|
315
|
+
checked={filteredKnos.length > 0 && filteredKnos.every((item) => selectedKnos.includes(item.kno))}
|
|
316
|
+
onChange={handleSelectAll}
|
|
317
|
+
/>
|
|
318
|
+
</div>
|
|
319
|
+
|
|
320
|
+
<div>KNO</div>
|
|
321
|
+
<div>Consumer Name</div>
|
|
322
|
+
<div>Locality</div>
|
|
323
|
+
<div>Pincode</div>
|
|
324
|
+
<div>Status</div>
|
|
325
|
+
<div>Route</div>
|
|
326
|
+
</div>
|
|
327
|
+
|
|
328
|
+
{/* Rows */}
|
|
329
|
+
<div className="table-body">
|
|
330
|
+
{filteredKnos.length > 0 ? (
|
|
331
|
+
filteredKnos.map((item, index) => (
|
|
332
|
+
<div key={item.kno} className={`table-row ${index % 2 === 0 ? "even" : "odd"}`}>
|
|
333
|
+
<div>
|
|
334
|
+
<input type="checkbox" checked={selectedKnos.includes(item.kno)} onChange={() => handleSelect(item.kno)} />
|
|
335
|
+
</div>
|
|
336
|
+
|
|
337
|
+
<div className="kno-value">{item.kno}</div>
|
|
338
|
+
|
|
339
|
+
<div>{item.consumerName}</div>
|
|
340
|
+
<div>{item.locality}</div>
|
|
341
|
+
<div>{item.pincode}</div>
|
|
342
|
+
|
|
343
|
+
<div>
|
|
344
|
+
<span className={`status-badge ${item.status === "PENDING" ? "pending" : item.status === "VERIFIED" ? "verified" : "assigned"}`}>
|
|
345
|
+
{item.status}
|
|
346
|
+
</span>
|
|
347
|
+
</div>
|
|
348
|
+
|
|
349
|
+
<div>{item.route}</div>
|
|
350
|
+
</div>
|
|
351
|
+
))
|
|
352
|
+
) : (
|
|
353
|
+
<div className="empty-state">No KNO records found</div>
|
|
354
|
+
)}
|
|
355
|
+
</div>
|
|
356
|
+
</div>
|
|
357
|
+
</div>
|
|
358
|
+
</Modal>
|
|
359
|
+
);
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
export default AssignEkycModal;
|
|
@@ -36,10 +36,12 @@ const EKYCCard = () => {
|
|
|
36
36
|
label: t("CEO_M.F_DOR_FINANCE_VIEW"),
|
|
37
37
|
link: `/digit-ui/employee/ekyc/ceo-dashboard`,
|
|
38
38
|
},
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
|
|
40
|
+
// {
|
|
41
|
+
// label: t("EKYC_MAPPING"),
|
|
42
|
+
// link: `/digit-ui/employee/ekyc/mapping`,
|
|
43
|
+
// },
|
|
44
|
+
|
|
43
45
|
{
|
|
44
46
|
label: t("EKYC_ASSIGN"),
|
|
45
47
|
link: `/digit-ui/employee/ekyc/assign`,
|