@djb25/digit-ui-module-ekyc 1.0.4 → 1.0.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djb25/digit-ui-module-ekyc",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Digit UI Module for Ekyc",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.modern.js",
@@ -44,11 +44,11 @@ const DesktopInbox = ({ tableConfig, filterComponent, ...props }) => {
44
44
  accessor: "citizenName",
45
45
  Cell: ({ row }) => <span>{row.original?.citizenName || "NA"}</span>,
46
46
  },
47
- {
48
- Header: t("EKYC_MOBILE_NO"),
49
- accessor: "mobileNumber",
50
- Cell: ({ row }) => <span>{row.original?.mobileNumber || "NA"}</span>,
51
- },
47
+ // {
48
+ // Header: t("EKYC_MOBILE_NO"),
49
+ // accessor: "mobileNumber",
50
+ // Cell: ({ row }) => <span>{row.original?.mobileNumber || "NA"}</span>,
51
+ // },
52
52
  {
53
53
  Header: t("EKYC_STATUS"),
54
54
  accessor: "status",
@@ -88,7 +88,8 @@ const SearchConsumer = ({ onSearch, searchParams, FilterComponent, children, ...
88
88
  />
89
89
  </div>
90
90
  </div>
91
-
91
+ </div>
92
+ <div style={{ display: "flex", justifyContent: "flex-end", marginTop: "20px" }}>
92
93
  <div style={{ display: "flex", gap: "12px", alignItems: "center" }}>
93
94
  <button
94
95
  type="button"
@@ -105,10 +106,18 @@ const SearchConsumer = ({ onSearch, searchParams, FilterComponent, children, ...
105
106
  >
106
107
  {t("ES_COMMON_CLEAR")}
107
108
  </button>
109
+
108
110
  <SubmitBar
109
111
  label={t("ES_COMMON_SEARCH")}
110
112
  onSubmit={onSubmit}
111
- style={{ margin: 0, borderRadius: "8px", height: "44px", padding: "0 32px", marginTop: "-55px" }}
113
+ style={{
114
+ margin: 0,
115
+ borderRadius: "8px",
116
+ height: "44px",
117
+ padding: "0 32px",
118
+ // ❌ remove this (it breaks alignment)
119
+ // marginTop: "-55px"
120
+ }}
112
121
  />
113
122
  </div>
114
123
  </div>
@@ -129,8 +129,8 @@ const RadioToggleRow = ({ label, selected, onSelect, t, options }) => (
129
129
  selectedOption={selected}
130
130
  onSelect={onSelect}
131
131
  t={t}
132
- innerStyles={{ display: "flex", gap: "20px" }}
133
- style={{ marginBottom: 0 }}
132
+ innerStyles={{ display: "flex", gap: "20px", alignItems: "center" }}
133
+ style={{ display: "flex", gap: "20px", marginBottom: 0 }}
134
134
  />
135
135
  </div>
136
136
  );
@@ -257,7 +257,7 @@ const AadhaarVerification = () => {
257
257
  display: "grid",
258
258
  gridTemplateColumns: "1fr 1fr",
259
259
  gap: "14px",
260
- marginBottom: "4px",
260
+ marginBottom: "20px",
261
261
  },
262
262
  optionalTag: {
263
263
  display: "inline-block",
@@ -364,7 +364,7 @@ const AadhaarVerification = () => {
364
364
  if (val.length <= 12 && /^\d*$/.test(val)) setAadhaarLastFour(val);
365
365
  }}
366
366
  placeholder={t("EKYC_ENTER_LAST_4_DIGIT") || "Enter 12 digits"}
367
- maxLength={4}
367
+ maxLength={12}
368
368
  disabled={isAadhaarVerified}
369
369
  inputStyle={isAadhaarVerified ? styles.verifiedInput : {}}
370
370
  />
@@ -428,12 +428,14 @@ const AadhaarVerification = () => {
428
428
  selected={nameCorrect}
429
429
  onSelect={setNameCorrect}
430
430
  options={yesNoOptions}
431
+ sty
431
432
  t={t}
432
433
  />
433
434
  <LabelFieldPair>
434
435
  <div className="field">
435
436
  <IconInput
436
437
  icon={<UserIcon size={15} color={nameCorrect.code === "YES" ? "#64748b" : "#94a3b8"} />}
438
+ style={{ marginBottom: "12px" }}
437
439
  value={userName}
438
440
  onChange={(e) => setUserName(e.target.value)}
439
441
  placeholder={t("EKYC_ENTER_NAME_PLACEHOLDER") || "Enter full name"}
@@ -454,6 +456,7 @@ const AadhaarVerification = () => {
454
456
  <div className="field">
455
457
  <IconInput
456
458
  icon={<PhoneIcon size={15} color={mobileChange.code === "YES" ? "#64748b" : "#94a3b8"} />}
459
+ style={{ marginBottom: "12px" }}
457
460
  value={mobileNumber}
458
461
  onChange={(e) => setMobileNumber(e.target.value)}
459
462
  placeholder="+91 XXXXX XXXXX"
@@ -1,4 +1,4 @@
1
- import React, { useState, useRef, Fragment } from "react";
1
+ import React, { useState, useRef, Fragment, useEffect } from "react";
2
2
  import {
3
3
  Card,
4
4
  LabelFieldPair,
@@ -14,6 +14,8 @@ import {
14
14
  HomeIcon,
15
15
  ConnectingCheckPoints,
16
16
  CheckPoint,
17
+ Dropdown,
18
+ Loader,
17
19
  } from "@djb25/digit-ui-react-components";
18
20
  import { useTranslation } from "react-i18next";
19
21
  import { useHistory, useLocation } from "react-router-dom";
@@ -164,6 +166,71 @@ const AddressDetails = ({ isSection = false, onComplete, parentState }) => {
164
166
  const [isLocationFetching, setIsLocationFetching] = useState(false);
165
167
  const fileInputRef = useRef(null);
166
168
 
169
+ const tenantId = Digit.ULBService.getCurrentTenantId();
170
+ const { data: mdmsData, isLoading: isMdmsLoading } = Digit.Hooks.useCommonMDMS(
171
+ tenantId,
172
+ "egov-location",
173
+ ["TenantBoundary"]
174
+ );
175
+
176
+ const mdmsRes = mdmsData?.MdmsRes || mdmsData;
177
+ const adminHierarchy = mdmsRes?.["egov-location"]?.TenantBoundary?.find(h => h.hierarchyType.code === "ADMIN")
178
+ || mdmsRes?.["egov-location"]?.TenantBoundary?.[0];
179
+
180
+ const rootBoundary = adminHierarchy?.boundary;
181
+
182
+ const getAssemblies = (boundaries) => {
183
+ if (!boundaries) return [];
184
+ let assemblies = [];
185
+ const targetLabel = "assembly constituency";
186
+ for (const boundary of boundaries) {
187
+ const label = (boundary.label || boundary.name || "").toLowerCase().replace(/_/g, " ");
188
+ if (label === targetLabel || label === "assemblyconstituency") {
189
+ assemblies.push({ code: boundary.code, name: boundary.name, children: boundary.children });
190
+ }
191
+ if (boundary.children?.length) {
192
+ assemblies.push(...getAssemblies(boundary.children));
193
+ }
194
+ }
195
+ return assemblies;
196
+ };
197
+
198
+ const getBlocks = (children) => {
199
+ if (!children) return [];
200
+ let blocks = [];
201
+ const targetLabel = "block";
202
+ for (const child of children) {
203
+ const label = (child.label || child.name || "").toLowerCase().replace(/_/g, " ");
204
+ if (label === targetLabel) {
205
+ blocks.push({ code: child.code, name: child.name });
206
+ }
207
+ if (child.children?.length) {
208
+ blocks.push(...getBlocks(child.children));
209
+ }
210
+ }
211
+ return blocks;
212
+ };
213
+
214
+ const assemblies = getAssemblies(Array.isArray(rootBoundary) ? rootBoundary : rootBoundary ? [rootBoundary] : []);
215
+
216
+ const [assembly, setAssembly] = useState(addrDetails.assembly ? { name: addrDetails.assembly } : null);
217
+ const [ward, setWard] = useState(addrDetails.ward ? { name: addrDetails.ward } : null);
218
+
219
+ useEffect(() => {
220
+ if (mdmsRes && addrDetails.assembly && !assembly?.code) {
221
+ const foundAssembly = assemblies.find((a) => a.name === addrDetails.assembly || a.code === addrDetails.assembly);
222
+ if (foundAssembly) setAssembly(foundAssembly);
223
+ }
224
+ }, [mdmsRes, assemblies]);
225
+
226
+ const blocks = assembly ? getBlocks(assembly.children) : [];
227
+
228
+ useEffect(() => {
229
+ if (assembly && ward && !blocks.find((b) => b.name === ward.name)) {
230
+ setWard(null);
231
+ }
232
+ }, [assembly]);
233
+
167
234
  const addressOptions = [
168
235
  { code: "AADHAAR", name: "EKYC_AADHAAR_ADDRESS" },
169
236
  { code: "OLD", name: "EKYC_OLD_ADDRESS" },
@@ -175,7 +242,17 @@ const AddressDetails = ({ isSection = false, onComplete, parentState }) => {
175
242
  ];
176
243
 
177
244
  const handleCompleteVerification = () => {
178
- const payload = { addressType, fullAddress, flatNo, building, landmark, pincode, doorPhoto };
245
+ const payload = {
246
+ addressType,
247
+ fullAddress,
248
+ flatNo,
249
+ building,
250
+ landmark,
251
+ pincode,
252
+ doorPhoto,
253
+ assembly: assembly?.name,
254
+ ward: ward?.name
255
+ };
179
256
  if (onComplete) {
180
257
  onComplete(payload);
181
258
  } else {
@@ -418,24 +495,35 @@ const AddressDetails = ({ isSection = false, onComplete, parentState }) => {
418
495
  label={t("EKYC_ADMINISTRATIVE_DIVISION") || "Administrative Division"}
419
496
  />
420
497
 
421
- <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "14px", marginBottom: "24px" }}>
422
- <AdminCard
423
- bgColor="#E1F5EE"
424
- iconBg="#9FE1CB"
425
- icon={<FlagIcon size={18} />}
426
- labelColor="#0F6E56"
427
- label={t("EKYC_ASSEMBLY") || "Assembly"}
428
- value={addrDetails.assembly || "AC-12 Chandni Chowk"}
429
- />
430
- <AdminCard
431
- bgColor="#E6F1FB"
432
- iconBg="#B5D4F4"
433
- icon={<IdCardIcon size={18} />}
434
- labelColor="#185FA5"
435
- label={t("EKYC_WARD") || "Ward"}
436
- value={addrDetails.ward || "WARD-45 Civil Lines"}
437
- />
438
- </div>
498
+ {isMdmsLoading ? <Loader /> : (
499
+ <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "14px", marginBottom: "24px" }}>
500
+ <div>
501
+ <div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
502
+ {t("EKYC_ASSEMBLY") || "Assembly Constituency"}
503
+ </div>
504
+ <Dropdown
505
+ option={assemblies}
506
+ optionKey="name"
507
+ selected={assembly}
508
+ select={(val) => { setAssembly(val); setWard(null); }}
509
+ t={t}
510
+ />
511
+ </div>
512
+ <div>
513
+ <div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
514
+ {t("EKYC_WARD") || "Block"}
515
+ </div>
516
+ <Dropdown
517
+ option={blocks}
518
+ optionKey="name"
519
+ selected={ward}
520
+ select={setWard}
521
+ disabled={!assembly}
522
+ t={t}
523
+ />
524
+ </div>
525
+ </div>
526
+ )}
439
527
 
440
528
  <hr style={{ margin: "24px 0", border: 0, borderTop: "1px solid #EAECF0" }} />
441
529
 
@@ -4,13 +4,7 @@ import DesktopInbox from "../../components/DesktopInbox";
4
4
  import MobileInbox from "../../components/MobileInbox";
5
5
  import Filter from "../../components/Filter";
6
6
 
7
- const MOCK_DATA_ITEMS = [
8
- { applicationNumber: "EKYC-2024-001", citizenName: "Rahul Sharma", mobileNumber: "9876543210", status: "COMPLETED" },
9
- { applicationNumber: "EKYC-2024-002", citizenName: "Anjali Devi", mobileNumber: "9123456789", status: "PENDING" },
10
- { applicationNumber: "EKYC-2024-003", citizenName: "Amit Kumar", mobileNumber: "8888888888", status: "REJECTED" },
11
- { applicationNumber: "EKYC-2024-004", citizenName: "Priya Singh", mobileNumber: "7777777777", status: "COMPLETED" },
12
- { applicationNumber: "EKYC-2024-005", citizenName: "Suresh Gupta", mobileNumber: "6666666666", status: "PENDING" },
13
- ];
7
+ // Mock data removed in favor of API integration
14
8
 
15
9
  const Inbox = ({
16
10
  parentRoute,
@@ -33,28 +27,40 @@ const Inbox = ({
33
27
  // Maintain the full search objects for the Search component
34
28
  const [searchParams, setSearchParams] = useState(initialStates.searchParams || { status: defaultStatusOption });
35
29
 
36
- // 2. Local Filtering Logic for Static Data
37
- const filteredStaticData = useMemo(() => {
38
- return MOCK_DATA_ITEMS.filter((item) => {
39
- let match = true;
40
- // Extract the string value from the status object if it exists
41
- const currentStatus = searchParams.status?.value !== undefined ? searchParams.status.value : searchParams.status;
42
-
43
- if (currentStatus && item.status !== currentStatus) {
44
- match = false;
45
- }
46
- return match;
47
- });
48
- }, [searchParams]);
49
-
50
- const staticCountData = useMemo(() => {
30
+ // 2. API Data Fetching
31
+ const { isLoading, data: dashboardData, isFetching } = Digit.Hooks.ekyc.useEkycSurveyorDashboard(
32
+ {},
33
+ {
34
+ tenantId,
35
+ offset: pageOffset,
36
+ limit: pageSize,
37
+ status: searchParams.status?.value || ""
38
+ },
39
+ {
40
+ enabled: !!tenantId,
41
+ }
42
+ );
43
+
44
+ const filteredData = useMemo(() => {
45
+ const items = dashboardData?.dashboardInfo?.consumerList || [];
46
+ return items.map(item => ({
47
+ ...item,
48
+ applicationNumber: item.kno || item.applicationNumber,
49
+ citizenName: item.consumerName || item.citizenName,
50
+ }));
51
+ }, [dashboardData]);
52
+
53
+ const countData = useMemo(() => {
54
+ const info = dashboardData?.dashboardInfo || {};
51
55
  return {
52
- total: MOCK_DATA_ITEMS.length,
53
- completed: MOCK_DATA_ITEMS.filter(i => i.status === "COMPLETED").length,
54
- pending: MOCK_DATA_ITEMS.filter(i => i.status === "PENDING").length,
55
- rejected: MOCK_DATA_ITEMS.filter(i => i.status === "REJECTED").length
56
+ total: info.total || 0,
57
+ completed: info.completed || 0,
58
+ pending: info.pending || 0,
59
+ rejected: info.rejected || 0
56
60
  };
57
- }, []);
61
+ }, [dashboardData]);
62
+
63
+ const totalRecords = dashboardData?.dashboardInfo?.totalRecords || dashboardData?.totalCount || 0;
58
64
 
59
65
  // 3. Handlers
60
66
  const handleSearch = useCallback((filterParam) => {
@@ -98,19 +104,19 @@ const Inbox = ({
98
104
  <div className="inbox-main-container">
99
105
  {Digit.Utils.browser.isMobile() ? (
100
106
  <MobileInbox
101
- data={{ items: filteredStaticData, totalCount: filteredStaticData.length }}
102
- isLoading={false}
107
+ data={{ items: filteredData, totalCount: totalRecords }}
108
+ isLoading={isLoading || isFetching}
103
109
  onSearch={handleSearch}
104
110
  searchFields={searchFields}
105
111
  searchParams={searchParams}
106
112
  parentRoute={parentRoute}
107
- countData={staticCountData}
113
+ countData={countData}
108
114
  />
109
115
  ) : (
110
116
  <DesktopInbox
111
117
  businessService={businessService}
112
- data={{ items: filteredStaticData, totalCount: filteredStaticData.length }}
113
- isLoading={false}
118
+ data={{ items: filteredData, totalCount: totalRecords }}
119
+ isLoading={isLoading || isFetching}
114
120
  searchFields={searchFields}
115
121
  onSearch={handleSearch}
116
122
  onSort={handleSort}
@@ -122,8 +128,8 @@ const Inbox = ({
122
128
  parentRoute={parentRoute}
123
129
  searchParams={searchParams}
124
130
  sortParams={sortParams}
125
- totalRecords={filteredStaticData.length}
126
- countData={staticCountData}
131
+ totalRecords={totalRecords}
132
+ countData={countData}
127
133
  filterComponent="EKYC_INBOX_FILTER"
128
134
  />
129
135
  )}