@djb25/digit-ui-module-ekyc 1.0.7 → 1.0.9
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 +3513 -3789
- package/dist/index.modern.js.map +1 -1
- package/package.json +1 -1
- package/src/Module.js +49 -22
- package/src/components/ConnectionDetailsView.js +183 -60
- package/src/components/DesktopInbox.js +47 -165
- package/src/components/EKYCCard.js +35 -23
- package/src/components/Filter.js +48 -53
- package/src/components/SearchConsumer.js +104 -94
- package/src/components/SearchFormFieldsComponent.js +55 -0
- package/src/components/StatusCards.js +100 -118
- package/src/config/config.js +69 -0
- package/src/hook/useInboxTableConfig.js +134 -0
- package/src/pages/citizen/index.js +90 -0
- package/src/pages/employee/AadhaarVerification.js +473 -609
- package/src/pages/employee/AddressDetails.js +508 -732
- package/src/pages/employee/ConsumerDetails.js +512 -0
- package/src/pages/employee/Create.js +24 -22
- package/src/pages/employee/Dashboard.js +43 -0
- package/src/pages/employee/EKYCForm.js +117 -0
- package/src/pages/employee/Inbox.js +248 -140
- package/src/pages/employee/Mapping.js +645 -0
- package/src/pages/employee/MeterDetails.js +496 -0
- package/src/pages/employee/PropertyInfo.js +471 -560
- package/src/pages/employee/Review.js +268 -484
- package/src/pages/employee/Update.js +9 -0
- package/src/pages/employee/index.js +60 -82
package/package.json
CHANGED
package/src/Module.js
CHANGED
|
@@ -1,40 +1,67 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
2
3
|
import { useRouteMatch } from "react-router-dom";
|
|
4
|
+
import { CitizenHomeCard, DocumentIcon } from "@djb25/digit-ui-react-components";
|
|
3
5
|
import EKYCCard from "./components/EKYCCard";
|
|
4
|
-
import Inbox from "./pages/employee/
|
|
6
|
+
import Inbox from "./pages/employee/Dashboard";
|
|
5
7
|
import DesktopInbox from "./components/DesktopInbox";
|
|
6
8
|
import MobileInbox from "./components/MobileInbox";
|
|
7
9
|
import Filter from "./components/Filter";
|
|
8
10
|
import EmployeeApp from "./pages/employee";
|
|
9
|
-
|
|
11
|
+
import CitizenApp from "./pages/citizen";
|
|
12
|
+
import AadhaarVerification from "./pages/employee/AadhaarVerification";
|
|
13
|
+
import AddressDetails from "./pages/employee/AddressDetails";
|
|
14
|
+
import PropertyInfo from "./pages/employee/PropertyInfo";
|
|
15
|
+
import MeterDetails from "./pages/employee/MeterDetails";
|
|
10
16
|
export const EkycModule = ({ stateCode, userType, tenants }) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
const { path, url } = useRouteMatch();
|
|
18
|
+
const moduleCode = "EKYC";
|
|
19
|
+
const language = Digit.StoreData.getCurrentLanguage();
|
|
20
|
+
const { isLoading, data: store } = Digit.Services.useStore({ stateCode, moduleCode, language });
|
|
21
|
+
Digit.SessionStorage.set("EKYC_TENANTS", tenants);
|
|
22
|
+
|
|
23
|
+
if (isLoading) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
if (userType === "employee") {
|
|
27
|
+
return <EmployeeApp path={path} url={url} userType={userType} tenants={tenants} />;
|
|
28
|
+
} else return <CitizenApp />;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const EkycLinks = ({ matchPath, userType }) => {
|
|
32
|
+
const { t } = useTranslation();
|
|
33
|
+
const links = [
|
|
34
|
+
{
|
|
35
|
+
link: `${matchPath}/create-kyc`,
|
|
36
|
+
i18nKey: t("EKYC_CREATE_KYC"),
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
link: `${matchPath}/update-kyc`,
|
|
40
|
+
i18nKey: t("EKYC_UPDATE_KYC"),
|
|
41
|
+
},
|
|
42
|
+
];
|
|
16
43
|
|
|
17
|
-
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
if (userType === "employee") {
|
|
21
|
-
return <EmployeeApp path={path} url={url} userType={userType} tenants={tenants} />;
|
|
22
|
-
} else return null;
|
|
44
|
+
return <CitizenHomeCard header={t("EKYC_MODULE_NAME")} links={links} Icon={() => <DocumentIcon className="fill-path-primary-main" />} />;
|
|
23
45
|
};
|
|
24
46
|
|
|
25
47
|
const componentsToRegister = {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
48
|
+
EKYCModule: EkycModule,
|
|
49
|
+
EKYCCard,
|
|
50
|
+
EKYCInbox: Inbox,
|
|
51
|
+
EKYCDesktopInbox: DesktopInbox,
|
|
52
|
+
EKYCMobileInbox: MobileInbox,
|
|
53
|
+
EKYC_INBOX_FILTER: (props) => <Filter {...props} />,
|
|
54
|
+
EkycLinks,
|
|
55
|
+
AadhaarVerification,
|
|
56
|
+
AddressDetails,
|
|
57
|
+
PropertyInfo,
|
|
58
|
+
MeterDetails,
|
|
32
59
|
};
|
|
33
60
|
|
|
34
61
|
export const initEkycComponents = () => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
62
|
+
Object.entries(componentsToRegister).forEach(([key, value]) => {
|
|
63
|
+
Digit.ComponentRegistryService.setComponent(key, value);
|
|
64
|
+
});
|
|
38
65
|
};
|
|
39
66
|
|
|
40
67
|
export default EkycModule;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useState } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { Loader, Modal, RadioButtons } from "@djb25/digit-ui-react-components";
|
|
3
3
|
import { useTranslation } from "react-i18next";
|
|
4
4
|
import { useHistory, useRouteMatch } from "react-router-dom";
|
|
5
5
|
|
|
@@ -16,75 +16,197 @@ const ConnectionDetailsView = ({ kNumber, kName, connectionDetails, isLoading })
|
|
|
16
16
|
{ code: "OTHER", name: "EKYC_OTHER" },
|
|
17
17
|
];
|
|
18
18
|
|
|
19
|
-
const handleStartVerification = () =>
|
|
20
|
-
setShowModal(true);
|
|
21
|
-
};
|
|
19
|
+
const handleStartVerification = () => setShowModal(true);
|
|
22
20
|
|
|
23
21
|
const onModalConfirm = () => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
const parentPath = path.includes("/create-kyc")
|
|
23
|
+
? path.replace("/create-kyc", "")
|
|
24
|
+
: path.replace("/k-details", "");
|
|
25
|
+
history.push(`${parentPath}/consumer-details`, { kNumber, selectedOption, connectionDetails });
|
|
27
26
|
setShowModal(false);
|
|
28
27
|
};
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
if (isLoading) {
|
|
35
|
-
return <Loader />;
|
|
36
|
-
}
|
|
29
|
+
if (isLoading) return <Loader />;
|
|
30
|
+
if (!connectionDetails) return null;
|
|
37
31
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
const details = connectionDetails?.connectionDetails || {};
|
|
33
|
+
const statusFlag = details.statusflag || "";
|
|
34
|
+
const isActive = statusFlag?.toLowerCase() === "active" || statusFlag === "A";
|
|
41
35
|
|
|
42
36
|
return (
|
|
43
37
|
<React.Fragment>
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
38
|
+
<div className="ekyc-employee-container">
|
|
39
|
+
{/* Main Card */}
|
|
40
|
+
<div className="connection-details-card">
|
|
41
|
+
{/* Card Header */}
|
|
42
|
+
<div className="details-card-header">
|
|
43
|
+
<div className="header-title-wrapper">
|
|
44
|
+
<div className="header-icon-bg">
|
|
45
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#3A7BD5" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
46
|
+
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
|
|
47
|
+
<circle cx="12" cy="7" r="4" />
|
|
48
|
+
</svg>
|
|
49
|
+
</div>
|
|
50
|
+
<span className="header-title-text">
|
|
51
|
+
{t("EKYC_K_NUMBER_DETAILS") || "Consumer Identity Details"}
|
|
52
|
+
</span>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
{/* Status Badge */}
|
|
56
|
+
<span className={`status-badge ${isActive ? "active" : "inactive"}`}>
|
|
57
|
+
{isActive ? (t("EKYC_ACTIVE_CONNECTION") || "Active Connection") : (statusFlag || t("CS_NA"))}
|
|
58
|
+
</span>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
{/* Card Body */}
|
|
62
|
+
<div className="details-card-body">
|
|
63
|
+
<div className="body-content-row">
|
|
64
|
+
{/* Left: Verification Parameters */}
|
|
65
|
+
<div className="detail-section">
|
|
66
|
+
<div className="section-title">
|
|
67
|
+
{t("EKYC_VERIFICATION_PARAMETERS") || "Verification Parameters"}
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<div className="data-grid">
|
|
71
|
+
{/* Consumer Name */}
|
|
72
|
+
<div className="data-item">
|
|
73
|
+
<div className="data-label">
|
|
74
|
+
{t("EKYC_CONSUMER_NAME") || "Consumer Name"}
|
|
75
|
+
</div>
|
|
76
|
+
<div className="data-value">
|
|
77
|
+
{details.consumerName || kName || t("CS_NA")}
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
{/* K Number */}
|
|
82
|
+
<div className="data-item">
|
|
83
|
+
<div className="data-label">
|
|
84
|
+
{t("EKYC_K_NUMBER") || "K Number"}
|
|
85
|
+
</div>
|
|
86
|
+
<div className="data-value blue">
|
|
87
|
+
{kNumber || t("CS_NA")}
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
{/* Meter Serial No */}
|
|
92
|
+
<div className="data-item">
|
|
93
|
+
<div className="data-label">
|
|
94
|
+
{t("EKYC_METER_NO") || "Meter Serial No."}
|
|
95
|
+
</div>
|
|
96
|
+
<div className="data-value">
|
|
97
|
+
{details.meterNumber || t("CS_NA")}
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
{/* Connection Type */}
|
|
102
|
+
<div className="data-item">
|
|
103
|
+
<div className="data-label">
|
|
104
|
+
{t("EKYC_CONNECTION_TYPE") || "Connection Type"}
|
|
105
|
+
</div>
|
|
106
|
+
<div className="data-value">
|
|
107
|
+
{details.connectionType || t("CS_NA")}
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
|
|
113
|
+
{/* Divider */}
|
|
114
|
+
<div className="vertical-divider" />
|
|
115
|
+
|
|
116
|
+
{/* Right: Address & Contact */}
|
|
117
|
+
<div className="detail-section">
|
|
118
|
+
<div className="section-title">
|
|
119
|
+
{t("EKYC_ADDRESS_AND_CONTACT") || "Address & Contact"}
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
{/* Service Address */}
|
|
123
|
+
<div className="address-block">
|
|
124
|
+
<div className="icon-wrapper-small">
|
|
125
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#6B7B8E" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
126
|
+
<path d="M21 10c0 7-9 13-9 13S3 17 3 10a9 9 0 0 1 18 0z" />
|
|
127
|
+
<circle cx="12" cy="10" r="3" />
|
|
128
|
+
</svg>
|
|
129
|
+
</div>
|
|
130
|
+
<div>
|
|
131
|
+
<div className="data-label">
|
|
132
|
+
{t("EKYC_ADDRESS") || "Service Address"}
|
|
133
|
+
</div>
|
|
134
|
+
<div className="address-text">
|
|
135
|
+
{details.address || t("CS_NA")}
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
{/* Contact + Email row */}
|
|
141
|
+
<div className="contact-row">
|
|
142
|
+
{/* Contact */}
|
|
143
|
+
<div className="contact-item">
|
|
144
|
+
<div className="icon-wrapper-small">
|
|
145
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#6B7B8E" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
146
|
+
<rect x="5" y="2" width="14" height="20" rx="2" ry="2" />
|
|
147
|
+
<line x1="12" y1="18" x2="12.01" y2="18" />
|
|
148
|
+
</svg>
|
|
149
|
+
</div>
|
|
150
|
+
<div>
|
|
151
|
+
<div className="data-label">
|
|
152
|
+
{t("EKYC_PHONE_NO") || "Contact"}
|
|
153
|
+
</div>
|
|
154
|
+
<div className="address-text">
|
|
155
|
+
{details.phoneNumber || t("CS_NA")}
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
|
|
160
|
+
{/* Email */}
|
|
161
|
+
<div className="contact-item">
|
|
162
|
+
<div className="icon-wrapper-small">
|
|
163
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#6B7B8E" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
164
|
+
<circle cx="12" cy="12" r="4" />
|
|
165
|
+
<path d="M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-3.92 7.94" />
|
|
166
|
+
</svg>
|
|
167
|
+
</div>
|
|
168
|
+
<div>
|
|
169
|
+
<div className="data-label">
|
|
170
|
+
{t("EKYC_EMAIL") || "Email Address"}
|
|
171
|
+
</div>
|
|
172
|
+
<div className="address-text">
|
|
173
|
+
{details.email || t("CS_NA")}
|
|
174
|
+
</div>
|
|
175
|
+
</div>
|
|
176
|
+
</div>
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
|
|
182
|
+
{/* Card Footer */}
|
|
183
|
+
<div className="details-card-footer">
|
|
184
|
+
{/* Last Verified */}
|
|
185
|
+
<div className="footer-meta-text">
|
|
186
|
+
{connectionDetails?.lastVerified
|
|
187
|
+
? `${t("EKYC_LAST_VERIFIED") || "Last verified:"} ${connectionDetails.lastVerified}`
|
|
188
|
+
: ""}
|
|
189
|
+
</div>
|
|
190
|
+
|
|
191
|
+
{/* Action Buttons */}
|
|
192
|
+
<div className="action-btns-container" style={{ fontSize: "12px" }}>
|
|
193
|
+
<button
|
|
194
|
+
onClick={handleStartVerification}
|
|
195
|
+
className="primary-action-btn"
|
|
196
|
+
style={{ fontSize: "12px" }}
|
|
197
|
+
>
|
|
198
|
+
{t("EKYC_START_REVIEW") || "Start Review"}
|
|
199
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
|
|
200
|
+
<line x1="5" y1="12" x2="19" y2="12" />
|
|
201
|
+
<polyline points="12 5 19 12 12 19" />
|
|
202
|
+
</svg>
|
|
203
|
+
</button>
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
68
206
|
</div>
|
|
69
|
-
|
|
70
|
-
className="submit-bar"
|
|
71
|
-
style={{
|
|
72
|
-
marginLeft: "10px",
|
|
73
|
-
background: "#3A8DCC",
|
|
74
|
-
border: "none",
|
|
75
|
-
color: "#fff",
|
|
76
|
-
padding: "10px 24px",
|
|
77
|
-
borderRadius: "12px",
|
|
78
|
-
fontWeight: "600",
|
|
79
|
-
cursor: "pointer",
|
|
80
|
-
boxShadow: "0 2px 4px rgba(0,0,0,0.1)"
|
|
81
|
-
}}
|
|
82
|
-
onClick={handleRaiseCorrection}
|
|
83
|
-
>
|
|
84
|
-
{t("EKYC_RAISE_CORRECTION")}
|
|
85
|
-
</button> */}
|
|
86
|
-
</Card>
|
|
207
|
+
</div>
|
|
87
208
|
|
|
209
|
+
{/* Modal */}
|
|
88
210
|
{showModal && (
|
|
89
211
|
<Modal
|
|
90
212
|
headerBarMain={t("EKYC_SELECT_VERIFICATION_TYPE")}
|
|
@@ -101,6 +223,7 @@ const ConnectionDetailsView = ({ kNumber, kName, connectionDetails, isLoading })
|
|
|
101
223
|
>
|
|
102
224
|
<div style={{ padding: "24px" }}>
|
|
103
225
|
<RadioButtons
|
|
226
|
+
name="verificationType"
|
|
104
227
|
options={options}
|
|
105
228
|
optionsKey="name"
|
|
106
229
|
selectedOption={selectedOption}
|
|
@@ -115,4 +238,4 @@ const ConnectionDetailsView = ({ kNumber, kName, connectionDetails, isLoading })
|
|
|
115
238
|
);
|
|
116
239
|
};
|
|
117
240
|
|
|
118
|
-
export default ConnectionDetailsView;
|
|
241
|
+
export default ConnectionDetailsView;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useMemo, useState } from "react";
|
|
2
2
|
import { useTranslation } from "react-i18next";
|
|
3
|
-
import { Table,
|
|
4
|
-
import {
|
|
3
|
+
import { Table, Card, Loader, InboxLinks } from "@djb25/digit-ui-react-components";
|
|
4
|
+
import { useHistory } from "react-router-dom";
|
|
5
5
|
import StatusCards from "./StatusCards";
|
|
6
6
|
|
|
7
7
|
const DesktopInbox = ({ tableConfig, filterComponent, ...props }) => {
|
|
@@ -19,137 +19,27 @@ const DesktopInbox = ({ tableConfig, filterComponent, ...props }) => {
|
|
|
19
19
|
sortParams,
|
|
20
20
|
totalRecords,
|
|
21
21
|
countData,
|
|
22
|
-
onSearch,
|
|
23
|
-
searchFields,
|
|
24
22
|
} = props;
|
|
25
23
|
const { t } = useTranslation();
|
|
24
|
+
const history = useHistory();
|
|
26
25
|
const tenantId = Digit.ULBService.getCurrentTenantId();
|
|
27
|
-
const
|
|
26
|
+
const FilterComponent = Digit.ComponentRegistryService?.getComponent(filterComponent);
|
|
28
27
|
|
|
29
28
|
// State for Review Modal
|
|
30
|
-
const [showReviewModal, setShowReviewModal] = useState(false);
|
|
31
|
-
const [reviewHtml, setReviewHtml] = useState("");
|
|
32
29
|
const [selectedKno, setSelectedKno] = useState("");
|
|
33
|
-
|
|
34
|
-
const generateReviewHtml = (info) => {
|
|
35
|
-
if (!info) return "<h3>No data found</h3>";
|
|
36
|
-
|
|
37
|
-
// Helper to format labels
|
|
38
|
-
const formatLabel = (str) => str.replace(/([A-Z])/g, ' $1').replace(/^./, (s) => s.toUpperCase());
|
|
39
|
-
|
|
40
|
-
return `
|
|
41
|
-
<!DOCTYPE html>
|
|
42
|
-
<html>
|
|
43
|
-
<head>
|
|
44
|
-
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
45
|
-
<style>
|
|
46
|
-
body { font-family: 'Inter', sans-serif; padding: 30px; color: #101828; line-height: 1.5; background: #fff; }
|
|
47
|
-
.header { display: flex; justify-content: space-between; align-items: flex-start; border-bottom: 2px solid #185FA5; padding-bottom: 20px; margin-bottom: 30px; }
|
|
48
|
-
.title { margin: 0; color: #185FA5; font-size: 24px; font-weight: 700; }
|
|
49
|
-
.subtitle { margin: 5px 0 0; color: #667085; font-size: 14px; }
|
|
50
|
-
.section { margin-bottom: 30px; border: 1px solid #EAECF0; border-radius: 12px; overflow: hidden; }
|
|
51
|
-
.section-header { background: #F9FAFB; padding: 12px 20px; border-bottom: 1px solid #EAECF0; font-weight: 700; font-size: 14px; color: #344054; text-transform: uppercase; letter-spacing: 0.05em; }
|
|
52
|
-
.grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0; }
|
|
53
|
-
.item { padding: 16px 20px; border-bottom: 1px solid #F2F4F7; }
|
|
54
|
-
.item:nth-last-child(-n+2) { border-bottom: none; }
|
|
55
|
-
.label { font-size: 11px; color: #667085; text-transform: uppercase; font-weight: 600; letter-spacing: 0.02em; margin-bottom: 4px; }
|
|
56
|
-
.value { font-size: 14px; font-weight: 500; color: #1D2939; }
|
|
57
|
-
.badge { display: inline-block; padding: 4px 12px; border-radius: 16px; font-size: 12px; font-weight: 600; }
|
|
58
|
-
.badge-success { background: #ECFDF3; color: #027A48; }
|
|
59
|
-
.badge-warning { background: #FFFAEB; color: #B54708; }
|
|
60
|
-
.print-btn { background: #185FA5; color: #fff; padding: 10px 20px; border: none; border-radius: 8px; cursor: pointer; font-weight: 600; font-size: 14px; display: block; margin: 20px auto; }
|
|
61
|
-
@media print { .print-btn { display: none; } body { padding: 0; } }
|
|
62
|
-
</style>
|
|
63
|
-
</head>
|
|
64
|
-
<body>
|
|
65
|
-
<div class="header">
|
|
66
|
-
<div>
|
|
67
|
-
<h1 class="title">Delhi Jal Board</h1>
|
|
68
|
-
<p class="subtitle">EKYC Application Review Summary</p>
|
|
69
|
-
</div>
|
|
70
|
-
<div style="text-align: right">
|
|
71
|
-
<span class="badge ${info.statusFlag === 'ACTIVE' ? 'badge-success' : 'badge-warning'}">${info.statusFlag || 'N/A'}</span>
|
|
72
|
-
<p class="subtitle" style="margin-top: 8px">Generated on: ${new Date().toLocaleDateString()}</p>
|
|
73
|
-
</div>
|
|
74
|
-
</div>
|
|
75
|
-
|
|
76
|
-
<div class="section">
|
|
77
|
-
<div class="section-header">Basic Details</div>
|
|
78
|
-
<div class="grid">
|
|
79
|
-
<div class="item"><div class="label">KNO Number</div><div class="value">${info.kno || 'N/A'}</div></div>
|
|
80
|
-
<div class="item"><div class="label">Consumer Name</div><div class="value">${info.consumerName || 'N/A'}</div></div>
|
|
81
|
-
<div class="item"><div class="label">Mobile Number</div><div class="value">${info.mobileNo || 'N/A'}</div></div>
|
|
82
|
-
<div class="item"><div class="label">Email Address</div><div class="value">${info.email || 'N/A'}</div></div>
|
|
83
|
-
<div class="item"><div class="label">Connection Type</div><div class="value">${info.typeOfConnection || 'N/A'}</div></div>
|
|
84
|
-
<div class="item"><div class="label">Category</div><div class="value">${info.connectionCategory || 'N/A'}</div></div>
|
|
85
|
-
</div>
|
|
86
|
-
</div>
|
|
87
|
-
|
|
88
|
-
<div class="section">
|
|
89
|
-
<div class="section-header">Location & Property Information</div>
|
|
90
|
-
<div class="grid">
|
|
91
|
-
<div class="item"><div class="label">Address</div><div class="value">${info.addressRaw || 'N/A'}</div></div>
|
|
92
|
-
<div class="item"><div class="label">Locality</div><div class="value">${info.locality || 'N/A'}</div></div>
|
|
93
|
-
<div class="item"><div class="label">City - Pincode</div><div class="value">${info.city || 'N/A'} - ${info.pincode || 'N/A'}</div></div>
|
|
94
|
-
<div class="item"><div class="label">PID Number</div><div class="value">${info.pidNumber || 'N/A'}</div></div>
|
|
95
|
-
<div class="item"><div class="label">No. of Floors</div><div class="value">${info.noOfFloor || 'N/A'}</div></div>
|
|
96
|
-
<div class="item"><div class="label">Verification Status</div><div class="value"><span class="badge ${info.verificationStatus === 'SUCCESSFUL' ? 'badge-success' : 'badge-warning'}">${info.verificationStatus || 'PENDING'}</span></div></div>
|
|
97
|
-
</div>
|
|
98
|
-
</div>
|
|
99
|
-
|
|
100
|
-
<div class="section">
|
|
101
|
-
<div class="section-header">Meter Information</div>
|
|
102
|
-
<div class="grid">
|
|
103
|
-
<div class="item"><div class="label">Meter Number</div><div class="value">${info.meterNumber || 'N/A'}</div></div>
|
|
104
|
-
<div class="item"><div class="label">Meter Make</div><div class="value">${info.meterMake || 'N/A'}</div></div>
|
|
105
|
-
<div class="item"><div class="label">Meter Location</div><div class="value">${info.meterLocationAddress || 'N/A'}</div></div>
|
|
106
|
-
<div class="item"><div class="label">Working Status</div><div class="value">${info.workingStatus ? 'Working' : 'Not Working'}</div></div>
|
|
107
|
-
</div>
|
|
108
|
-
</div>
|
|
109
|
-
|
|
110
|
-
<button class="print-btn" onclick="window.print()">Print This Review</button>
|
|
111
|
-
</body>
|
|
112
|
-
</html>
|
|
113
|
-
`;
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
// Use the library hook if available, otherwise fallback to local definition
|
|
117
|
-
// This is a safety measure to handle stale library builds in dev environment
|
|
118
|
-
const useReviewHook = Digit.Hooks.ekyc?.useEkycApplicationReview || ((p, config) => {
|
|
119
|
-
return Digit.Hooks.useMutation((data) => Digit.EkycService.application_review(data, p), config);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
const { mutate: getReview, isLoading: isReviewLoading } = useReviewHook(
|
|
123
|
-
{ tenantId },
|
|
124
|
-
{
|
|
125
|
-
onSuccess: (res) => {
|
|
126
|
-
if (res?.applicationReviewInfo) {
|
|
127
|
-
const html = generateReviewHtml(res.applicationReviewInfo);
|
|
128
|
-
setReviewHtml(html);
|
|
129
|
-
setShowReviewModal(true);
|
|
130
|
-
} else {
|
|
131
|
-
// Fallback to URL method if the API is updated later to return a URL
|
|
132
|
-
const url = res?.acknowledgementURL || res?.reviewUrl || res?.url;
|
|
133
|
-
if (url) {
|
|
134
|
-
setReviewHtml(""); // Clear HTML so iframe uses URL
|
|
135
|
-
setReviewUrl(url);
|
|
136
|
-
setShowReviewModal(true);
|
|
137
|
-
} else {
|
|
138
|
-
alert(t("EKYC_REVIEW_INFO_NOT_FOUND"));
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
},
|
|
142
|
-
onError: (err) => {
|
|
143
|
-
alert(err?.message || t("ERR_FAILED_TO_FETCH_REVIEW"));
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
);
|
|
147
|
-
|
|
30
|
+
const { data: reviewData, getReview } = Digit.Hooks.ekyc.useEkycAPI("review", tenantId);
|
|
148
31
|
const handleReview = (kno) => {
|
|
149
32
|
setSelectedKno(kno);
|
|
150
33
|
getReview({ kno });
|
|
151
34
|
};
|
|
152
35
|
|
|
36
|
+
React.useEffect(() => {
|
|
37
|
+
if (reviewData) {
|
|
38
|
+
history.push("/digit-ui/employee/ekyc/review", { kNumber: selectedKno, aadhaarData: reviewData?.aadhaarData, reviewData });
|
|
39
|
+
}
|
|
40
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
41
|
+
}, [reviewData]);
|
|
42
|
+
|
|
153
43
|
const columns = useMemo(
|
|
154
44
|
() => [
|
|
155
45
|
{
|
|
@@ -180,13 +70,30 @@ const DesktopInbox = ({ tableConfig, filterComponent, ...props }) => {
|
|
|
180
70
|
// },
|
|
181
71
|
{
|
|
182
72
|
Header: t("EKYC_STATUS"),
|
|
183
|
-
accessor: "
|
|
73
|
+
accessor: "actionStatus",
|
|
184
74
|
Cell: ({ row }) => {
|
|
185
75
|
const status = row.original?.status || "DEFAULT";
|
|
186
76
|
return <span className={`ekyc-status-tag ${status}`}>{t(`${status}`)}</span>;
|
|
187
77
|
},
|
|
188
78
|
},
|
|
79
|
+
{
|
|
80
|
+
Header: t("EKYC_ACTION"),
|
|
81
|
+
accessor: "status",
|
|
82
|
+
Cell: ({ row }) => {
|
|
83
|
+
const kno = row.original?.kno || row.original?.applicationNumber || "NA";
|
|
84
|
+
return (
|
|
85
|
+
<span
|
|
86
|
+
className="ekyc-application-link"
|
|
87
|
+
style={{ color: "#add8f7", cursor: "pointer", fontWeight: "bold" }}
|
|
88
|
+
onClick={() => handleReview(kno)}
|
|
89
|
+
>
|
|
90
|
+
{t("EKYC_REVIEW")}
|
|
91
|
+
</span>
|
|
92
|
+
);
|
|
93
|
+
},
|
|
94
|
+
},
|
|
189
95
|
],
|
|
96
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
190
97
|
[t, parentRoute]
|
|
191
98
|
);
|
|
192
99
|
|
|
@@ -195,51 +102,26 @@ const DesktopInbox = ({ tableConfig, filterComponent, ...props }) => {
|
|
|
195
102
|
}, [data]);
|
|
196
103
|
|
|
197
104
|
return (
|
|
198
|
-
<div className="
|
|
199
|
-
<div className="inbox-container"
|
|
200
|
-
{
|
|
201
|
-
|
|
202
|
-
headerBarMain={t("EKYC_APPLICATION_REVIEW") + (selectedKno ? ` - ${selectedKno}` : "")}
|
|
203
|
-
headerBarEnd={<div style={{ cursor: "pointer", padding: "5px 10px", background: "#F2F4F7", borderRadius: "4px" }} onClick={() => setShowReviewModal(false)}>{t("CLOSE")}</div>}
|
|
204
|
-
hideSubmit={true}
|
|
205
|
-
popupStyles={{ width: "90%", height: "90%", maxWidth: "1000px" }}
|
|
206
|
-
popupModuleMianStyles={{ height: "calc(100% - 60px)", padding: 0 }}
|
|
207
|
-
>
|
|
208
|
-
<iframe
|
|
209
|
-
srcDoc={reviewHtml}
|
|
210
|
-
src={!reviewHtml ? reviewUrl : undefined}
|
|
211
|
-
title="Application Review"
|
|
212
|
-
style={{ width: "100%", height: "100%", border: "none" }}
|
|
213
|
-
/>
|
|
214
|
-
</Modal>
|
|
215
|
-
)}
|
|
216
|
-
{(isLoading || isReviewLoading) && <Loader />}
|
|
217
|
-
<div className="filters-container">
|
|
105
|
+
<div className="app-container">
|
|
106
|
+
<div className="inbox-container">
|
|
107
|
+
{isLoading && <Loader />}
|
|
108
|
+
<div className="side-panel-item">
|
|
218
109
|
{/* Sidebar Title Card */}
|
|
219
|
-
<Card
|
|
220
|
-
className="sidebar-title-card"
|
|
221
|
-
style={{ display: "flex", alignItems: "center", padding: "16px", marginBottom: "16px", borderRadius: "4px" }}
|
|
222
|
-
>
|
|
223
|
-
<div className="icon-container" style={{ color: "#3A8DCC", marginRight: "12px" }}>
|
|
224
|
-
<HomeIcon style={{ width: "24px", height: "24px" }} />
|
|
225
|
-
</div>
|
|
226
|
-
<div style={{ fontWeight: "700", fontSize: "18px", color: "#0B0C0C" }}>{t("ACTION_TEST_EKYC")}</div>
|
|
227
|
-
</Card>
|
|
228
110
|
|
|
229
|
-
<
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
111
|
+
<InboxLinks headerText={props.moduleCode} />
|
|
112
|
+
|
|
113
|
+
{FilterComponent && (
|
|
114
|
+
<FilterComponent
|
|
115
|
+
defaultSearchParams={props.defaultSearchParams}
|
|
116
|
+
onFilterChange={props.onSearch}
|
|
117
|
+
searchParams={searchParams}
|
|
118
|
+
type="desktop"
|
|
119
|
+
moduleCode="EKYC"
|
|
120
|
+
/>
|
|
121
|
+
)}
|
|
240
122
|
</div>
|
|
241
123
|
|
|
242
|
-
<div style={{ flex: 1
|
|
124
|
+
<div className="employee-form-content" style={{ flex: 1 }}>
|
|
243
125
|
{/* Header Section (retaining for context/actions) */}
|
|
244
126
|
{/* <div className="ekyc-header-container module-header" style={{ marginBottom: "16px", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
|
|
245
127
|
<Header className="title" style={{ margin: 0 }}>{t("EKYC_INBOX_HEADER")}</Header>
|
|
@@ -249,7 +131,7 @@ const DesktopInbox = ({ tableConfig, filterComponent, ...props }) => {
|
|
|
249
131
|
</div> */}
|
|
250
132
|
|
|
251
133
|
{/* Metrics Section (The Card) */}
|
|
252
|
-
<Card className="ekyc-metrics-card"
|
|
134
|
+
<Card className="ekyc-metrics-card">
|
|
253
135
|
<StatusCards countData={countData} />
|
|
254
136
|
</Card>
|
|
255
137
|
|