@djb25/digit-ui-module-ekyc 1.0.8 → 1.0.10

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.
@@ -1,585 +1,313 @@
1
- import React, { Fragment, useState, useEffect } from "react";
1
+ import React, { useState, Fragment, useEffect } from "react";
2
2
  import {
3
3
  Card,
4
4
  CardHeader,
5
+ CardSubHeader,
6
+ StatusTable,
7
+ Row,
5
8
  SubmitBar,
6
- HomeIcon,
9
+ Loader,
7
10
  ActionBar,
8
- Toast,
11
+ CheckBox,
12
+ LinkButton,
13
+ EditIcon,
14
+ GenericFileIcon,
9
15
  } from "@djb25/digit-ui-react-components";
10
16
  import { useTranslation } from "react-i18next";
11
17
  import { useHistory, useLocation } from "react-router-dom";
12
- import { getPayloadDiff, getSavedData } from "../../utils";
13
-
14
- // ─── Icons ────────────────────────────────────────────────────────────────────
15
-
16
- const CheckIcon = ({ size = 11, color = "#fff" }) => (
17
- <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="3" strokeLinecap="round">
18
- <polyline points="20 6 9 17 4 12" />
19
- </svg>
20
- );
21
-
22
- const PersonIcon = ({ size = 16 }) => (
23
- <svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor">
24
- <path d="M12 12c2.7 0 4.8-2.1 4.8-4.8S14.7 2.4 12 2.4 7.2 4.5 7.2 7.2 9.3 12 12 12zm0 2.4c-3.2 0-9.6 1.6-9.6 4.8v2.4h19.2v-2.4c0-3.2-6.4-4.8-9.6-4.8z" />
25
- </svg>
26
- );
27
-
28
- const LocationIcon2 = ({ size = 16 }) => (
29
- <svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor">
30
- <path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z" />
31
- </svg>
32
- );
33
-
34
- const BuildingIcon = ({ size = 16 }) => (
35
- <svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor">
36
- <path d="M12 7V3H2v18h20V7H12zM6 19H4v-2h2v2zm0-4H4v-2h2v2zm0-4H4V9h2v2zm0-4H4V5h2v2zm4 12H8v-2h2v2zm0-4H8v-2h2v2zm0-4H8V9h2v2zm0-4H8V5h2v2zm10 12h-8V9h8v10zm-2-8h-4v2h4v-2zm0 4h-4v2h4v-2z" />
37
- </svg>
38
- );
39
-
40
- const EditIcon = ({ size = 14 }) => (
41
- <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
42
- <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
43
- <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
44
- </svg>
45
- );
46
-
47
- // ─── Reusable: Section heading with inline rule ───────────────────────────────
48
-
49
- const SectionHead = ({ icon, label }) => (
50
- <div style={{
51
- display: "flex", alignItems: "center", gap: "8px",
52
- marginBottom: "16px", marginTop: "4px",
53
- }}>
54
- <div style={{ opacity: 0.5, display: "flex" }}>{icon}</div>
55
- <span style={{ fontSize: "15px", fontWeight: "600", color: "#0B0C0C", whiteSpace: "nowrap" }}>
56
- {label}
57
- </span>
58
- <div style={{ flex: 1, height: "1px", background: "#EAECF0" }} />
59
- </div>
60
- );
61
-
62
- // ─── Reusable: Review section card ───────────────────────────────────────────
63
-
64
- const ReviewCard = ({ icon, title, onEdit, editLabel, rows, t }) => (
65
- <div style={{
66
- border: "0.5px solid #EAECF0",
67
- borderRadius: "10px",
68
- overflow: "hidden",
69
- marginBottom: "16px",
70
- animation: "fadeSlideIn 0.3s ease",
71
- }}>
72
- {/* Card header */}
73
- <div style={{
74
- display: "flex", justifyContent: "space-between", alignItems: "center",
75
- padding: "14px 16px",
76
- background: "#F9FAFB",
77
- borderBottom: "0.5px solid #EAECF0",
78
- }}>
79
- <div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
80
- <div style={{ opacity: 0.5, display: "flex" }}>{icon}</div>
81
- <span style={{ fontSize: "14px", fontWeight: "600", color: "#0B0C0C" }}>{title}</span>
82
- </div>
83
- <button
84
- onClick={onEdit}
85
- style={{
86
- display: "flex", alignItems: "center", gap: "5px",
87
- background: "none", border: "0.5px solid #D0D5DD",
88
- borderRadius: "6px", padding: "5px 12px",
89
- fontSize: "12px", fontWeight: "600", color: "#185FA5",
90
- cursor: "pointer",
91
- }}
92
- >
93
- <EditIcon size={12} />
94
- {editLabel}
95
- </button>
96
- </div>
97
18
 
98
- {/* Rows */}
99
- <div style={{ padding: "4px 0" }}>
100
- {rows.map((row, i) => (
101
- row.value ? (
102
- <div key={i} style={{
103
- display: "flex", alignItems: "flex-start",
104
- padding: "10px 16px",
105
- borderBottom: i < rows.length - 1 ? "0.5px solid #F2F4F7" : "none",
106
- }}>
107
- <div style={{
108
- flex: "0 0 180px", fontSize: "12px", fontWeight: "600",
109
- color: "#667085", textTransform: "uppercase",
110
- letterSpacing: "0.04em", paddingTop: "1px",
111
- }}>
112
- {row.label}
113
- </div>
114
- <div style={{ flex: 1, fontSize: "14px", color: "#101828", fontWeight: "500", wordBreak: "break-word", display: "flex", alignItems: "center", gap: "8px" }}>
115
- {row.value}
116
- {row.isModified && (
117
- <span style={{
118
- fontSize: "10px",
119
- background: "#FFF4ED",
120
- color: "#B45309",
121
- border: "0.5px solid #FDE68A",
122
- borderRadius: "4px",
123
- padding: "2px 6px",
124
- fontWeight: "600",
125
- textTransform: "uppercase"
126
- }}>
127
- {t("EKYC_MODIFIED") || "Modified"}
128
- </span>
129
- )}
130
- </div>
131
- </div>
132
- ) : null
133
- ))}
134
- </div>
135
- </div>
136
- );
19
+ // ─── Constants ───────────────────────────────────────────────────────────────
20
+
21
+ const ActionButton = ({ jumpTo, state }) => {
22
+ const { t } = useTranslation();
23
+ const history = useHistory();
24
+ function routeTo() {
25
+ history.push(jumpTo, { ...state, isEditing: true });
26
+ }
27
+ return (
28
+ <LinkButton
29
+ label={<EditIcon style={{ marginTop: "-30px", float: "right", position: "relative", bottom: "32px" }} />}
30
+ className="check-page-link-button"
31
+ onClick={routeTo}
32
+ />
33
+ );
34
+ };
35
+
36
+ const checkForNA = (value) => (value !== null && value !== undefined && value !== "") ? value : "N/A";
37
+
38
+ const boolToYesNo = (value, t) => {
39
+ if (value === true || value === "true" || String(value).toLowerCase() === "yes") return t("CORE_COMMON_YES");
40
+ if (value === false || value === "false" || String(value).toLowerCase() === "no") return t("CORE_COMMON_NO");
41
+ return "N/A";
42
+ };
137
43
 
138
- // ─── Main Component ───────────────────────────────────────────────────────────
44
+ /**
45
+ * Robust data extraction based on the screenshot provided.
46
+ * The API returns { applicationReview: { newData: { ...flatFields } } }
47
+ */
48
+ const extractActiveData = (searchData, flowState) => {
49
+ const rawData = (searchData && Object.keys(searchData).length > 0) ? searchData : flowState?.reviewData || {};
50
+
51
+ // Navigate through applicationReview -> newData
52
+ const reviewWrapper = rawData?.applicationReview || rawData;
53
+ const applicationData = (Array.isArray(reviewWrapper) ? reviewWrapper[0] : reviewWrapper) || {};
54
+ return applicationData?.newData || applicationData;
55
+ };
139
56
 
140
57
  const Review = () => {
141
58
  const { t } = useTranslation();
142
59
  const history = useHistory();
143
60
  const location = useLocation();
144
61
 
145
- // ── Restore State Logic ──
146
- const state = location.state || {};
147
- const initialData = state.initialData || getSavedData("EKYC_INITIAL_DATA", {});
148
- const kNumber = state.kNumber || sessionStorage.getItem("EKYC_K_NUMBER") || "EKYC-1234567890";
149
-
150
- // Reconstruct nested objects if state is lost on refresh
151
- const aadhaarDetails = state.aadhaarDetails || {
152
- userName: sessionStorage.getItem("EKYC_USER_NAME"),
153
- mobileNumber: sessionStorage.getItem("EKYC_MOBILE_NUMBER"),
154
- whatsappNumber: sessionStorage.getItem("EKYC_WHATSAPP_NUMBER"),
155
- email: sessionStorage.getItem("EKYC_EMAIL"),
156
- noOfPersons: sessionStorage.getItem("EKYC_NO_OF_PERSONS"),
157
- };
62
+ const [agree, setAgree] = useState(false);
63
+ const [isSubmitting, setIsSubmitting] = useState(false);
158
64
 
159
- const addressDetails = state.addressDetails || {
160
- fullAddress: sessionStorage.getItem("EKYC_FULL_ADDRESS"),
161
- flatNo: sessionStorage.getItem("EKYC_FLAT_NO"),
162
- building: sessionStorage.getItem("EKYC_BUILDING"),
163
- landmark: sessionStorage.getItem("EKYC_LANDMARK"),
164
- pincode: sessionStorage.getItem("EKYC_PINCODE"),
165
- assembly: getSavedData("EKYC_ASSEMBLY_DATA")?.name,
166
- ward: getSavedData("EKYC_WARD_DATA")?.name,
167
- doorPhoto: sessionStorage.getItem("EKYC_DOOR_PHOTO"),
168
- doorPhotoFileStoreId: sessionStorage.getItem("EKYC_DOOR_PHOTO_FILESTORE_ID"),
169
- };
65
+ const flowState = location.state || {};
66
+ const { kNumber, kno, edits = {} } = flowState;
67
+ const activeKno = kNumber || kno;
170
68
 
171
- const propertyDetails = state.propertyDetails || {
172
- ownerType: sessionStorage.getItem("EKYC_OWNER_TYPE"),
173
- pidNumber: sessionStorage.getItem("EKYC_PID_NUMBER"),
174
- userType: getSavedData("EKYC_USER_TYPE_DATA"),
175
- noOfFloors: getSavedData("EKYC_NO_OF_FLOORS_DATA"),
176
- propertyDocument: sessionStorage.getItem("EKYC_PROPERTY_DOC"),
177
- propertyDocumentFileStoreId: sessionStorage.getItem("EKYC_PROPERTY_DOC_FILESTORE_ID"),
178
- buildingPhoto: sessionStorage.getItem("EKYC_BUILDING_PHOTO"),
179
- buildingPhotoFileStoreId: sessionStorage.getItem("EKYC_BUILDING_PHOTO_FILESTORE_ID"),
180
- };
69
+ const { aadhaarData = {}, addressDetails: editedAddress = {}, propertyDetails: editedProperty = {}, meterDetails: editedMeter = {} } = edits;
181
70
 
182
- const meterDetails = state.meterDetails || {
183
- meterStatus: getSavedData("EKYC_METER_STATUS_DATA"),
184
- workingStatus: getSavedData("EKYC_METER_WORKING_STATUS_DATA"),
185
- meterLocation: sessionStorage.getItem("EKYC_METER_LOCATION"),
186
- lastBillRaised: getSavedData("EKYC_LAST_BILL_RAISED_DATA"),
187
- noBillReason: sessionStorage.getItem("EKYC_REASON_FOR_NO_BILL"),
188
- sewerConnection: getSavedData("EKYC_SEWER_CONNECTION_DATA"),
189
- connectionCategory: getSavedData("EKYC_TYPE_OF_CONNECTION_DATA"),
190
- connectionType: getSavedData("EKYC_CONNECTION_CATEGORY_DATA"),
191
- meterPhoto: sessionStorage.getItem("EKYC_METER_PHOTO"),
192
- meterPhotoFileStoreId: sessionStorage.getItem("EKYC_METER_PHOTO_FILESTORE_ID"),
193
- };
71
+ const tenantId = Digit.ULBService.getCurrentTenantId();
194
72
 
195
- useEffect(() => {
196
- sessionStorage.setItem("EKYC_CURRENT_STEP", "REVIEW");
197
- }, []);
73
+ const { data: searchData, isLoading: isSearchLoading } = Digit.Hooks.ekyc.useEkycSearchReview(
74
+ { kno: activeKno, fetchType: "REVIEW" },
75
+ tenantId,
76
+ { enabled: !!activeKno }
77
+ );
198
78
 
199
- // Helper to check if a field is modified
200
- const isFieldModified = (key, currentVal) => {
201
- const initialVal = initialData[key];
202
- if (initialVal === undefined) return false;
203
- return JSON.stringify(initialVal) !== JSON.stringify(currentVal);
79
+ // ── Data Consolidation ──────────────────────────────────────────────────
80
+ const activeData = extractActiveData(searchData, flowState);
81
+
82
+ // Support both structured (connectionDetails.x) and flat (x) formats
83
+ const apiConn = activeData?.connectionDetails || activeData || {};
84
+ const apiAddr = activeData?.addressDetails || activeData || {};
85
+ const apiProp = activeData?.propertyInfo || activeData || {};
86
+ const apiMeter = activeData?.meterDetails || activeData || {};
87
+
88
+ const connectionData = {
89
+ consumerName: aadhaarData?.name || apiConn?.consumerName,
90
+ address: apiConn?.address || apiConn?.addressRaw,
91
+ connectionType: apiConn?.connectionType || apiConn?.connectionCategory,
92
+ meterNumber: apiConn?.meterNumber || apiConn?.meterNo,
93
+ phoneNumber: aadhaarData?.mobileNumber || apiConn?.phoneNumber || apiConn?.mobileNo,
94
+ email: apiConn?.email,
95
+ statusflag: apiConn?.statusflag || apiConn?.statusFlag,
96
+ ekycStatus: apiConn?.ekycStatus,
97
+ knumber: apiConn?.knumber || apiConn?.kno || activeKno,
204
98
  };
205
99
 
206
- const [toast, setToast] = useState(null);
207
- const tenantId = Digit.ULBService.getCurrentTenantId() || "dl";
208
- const { mutate, isLoading: isMutationLoading } = Digit.Hooks.ekyc.useEkycApplicationUpdate(tenantId);
209
- const isSubmitting = isMutationLoading;
210
-
211
- // ── Helper: upload a File object to Filestore ──────────────────────────────
212
- const uploadFile = async (file, tenantId) => {
213
- if (!file) return null;
214
- const res = await Digit.UploadServices.Filestorage("EKYC", file, tenantId);
215
- return res?.data?.files?.[0]?.fileStoreId || null;
100
+ const addressData = {
101
+ fullAddress: editedAddress?.fullAddress || apiAddr?.fullAddress || apiAddr?.addressRaw,
102
+ flatHouseNumber: editedAddress?.flatHouseNumber || editedAddress?.flatNo || apiAddr?.flatHouseNumber,
103
+ buildingTower: editedAddress?.buildingTower || editedAddress?.building || apiAddr?.buildingTower,
104
+ landmark: editedAddress?.landmark || apiAddr?.landmark,
105
+ pinCode: editedAddress?.pinCode || editedAddress?.pincode || apiAddr?.pinCode || apiAddr?.pincode,
106
+ ward: editedAddress?.ward || apiAddr?.ward || apiAddr?.locality,
107
+ assembly: editedAddress?.assembly || apiAddr?.assembly,
108
+ gpsValid: editedAddress?.gpsValid !== undefined ? editedAddress.gpsValid : apiAddr?.gpsValid,
109
+ latitude: editedAddress?.latitude || apiAddr?.latitude,
110
+ longitude: editedAddress?.longitude || apiAddr?.longitude,
111
+ mobileNo: editedAddress?.mobileNo || aadhaarData?.mobileNumber || apiAddr?.mobileNo,
112
+ whatsappNo: editedAddress?.whatsappNo || aadhaarData?.whatsappNumber || apiAddr?.whatsappNo,
113
+ email: editedAddress?.email || apiAddr?.email,
114
+ noOfPerson: editedAddress?.noOfPerson || aadhaarData?.noOfPersons || apiAddr?.noOfPerson,
115
+ knumber: editedAddress?.knumber || apiAddr?.knumber || apiAddr?.kno || activeKno,
116
+ doorPhotoFilestoreId: editedAddress?.doorPhotoFileStoreId || apiAddr?.doorPhotoFilestoreId,
216
117
  };
217
118
 
218
- // ── Helper: convert a data-URL (base64 string) to a File blob ─────────────
219
- const dataUrlToFile = (dataUrl, filename) => {
220
- const arr = dataUrl.split(",");
221
- const mime = arr[0].match(/:(.*?);/)[1];
222
- const bstr = atob(arr[1]);
223
- let n = bstr.length;
224
- const u8arr = new Uint8Array(n);
225
- while (n--) u8arr[n] = bstr.charCodeAt(n);
226
- return new File([u8arr], filename, { type: mime });
119
+ const propertyData = {
120
+ kno: apiProp?.kno || activeKno,
121
+ pidNumber: editedProperty?.pidNumber || apiProp?.pidNumber,
122
+ typeOfConnection: editedProperty?.connectionTypeData?.label || apiProp?.typeOfConnection,
123
+ connectionCategory: editedProperty?.connectionCategoryData?.label || apiProp?.connectionCategory,
124
+ userType: editedProperty?.userTypeData?.label || apiProp?.userType,
125
+ numberOfFloors: editedProperty?.noOfFloorsData?.label || apiProp?.numberOfFloors,
126
+ tenantName: apiProp?.tenantName,
127
+ tenantMobile: apiProp?.tenantMobile,
128
+ ekycStatus: apiProp?.ekycStatus,
129
+ propertyDocumentFileStoreId: editedProperty?.propertyDocumentFileStoreId || apiProp?.propertyDocumentFileStoreId,
130
+ buildingImageFileStoreId: apiProp?.buildingImageFileStoreId,
227
131
  };
228
132
 
229
- const handleSubmit = async () => {
230
- setToast(null);
231
- try {
232
- const userInfo = Digit.UserService.getUser()?.info || {};
233
-
234
- // ── 1. Upload property document ──────────────────────────────────────
235
- let propertyDocFileStoreId = propertyDetails.propertyDocumentFileStoreId || null;
236
- if (!propertyDocFileStoreId && propertyDetails.propertyDocument instanceof File) {
237
- propertyDocFileStoreId = await uploadFile(propertyDetails.propertyDocument, tenantId);
238
- }
239
-
240
- // ── 2. Upload building photo ──────────────────────────────────────────
241
- let buildingImageFileStoreId = propertyDetails.buildingPhotoFileStoreId || null;
242
- if (!buildingImageFileStoreId && propertyDetails.buildingPhoto) {
243
- // Fallback if we only have the dataURL
244
- const photoFile = dataUrlToFile(propertyDetails.buildingPhoto, "building_photo.jpg");
245
- buildingImageFileStoreId = await uploadFile(photoFile, tenantId);
246
- }
247
-
248
- // ── 3. Upload door photo ──────────────────────────────────────────────
249
- let doorPhotoFileStoreId = addressDetails.doorPhotoFileStoreId || null;
250
- if (!doorPhotoFileStoreId && addressDetails.doorPhoto) {
251
- const doorFile = dataUrlToFile(addressDetails.doorPhoto, "door_photo.jpg");
252
- doorPhotoFileStoreId = await uploadFile(doorFile, tenantId);
253
- }
254
-
255
- // ── 4. Upload meter photo ──────────────────────────────────────────────
256
- let meterImageFileStoreId = meterDetails.meterPhotoFileStoreId || null;
257
- if (!meterImageFileStoreId && meterDetails.meterPhoto) {
258
- const meterFile = dataUrlToFile(meterDetails.meterPhoto, "meter_photo.jpg");
259
- meterImageFileStoreId = await uploadFile(meterFile, tenantId);
260
- }
261
-
262
- // ── 4. Build optimized request payload ────────────────────────────────
263
- // Note: RequestInfo is added automatically by the Digit Request utility
264
- const requestBody = {
265
- updateType: "PROPERTY",
266
- kno: kNumber,
267
- pidNumber: propertyDetails.pidNumber || null,
268
- propertyDocumentFileStoreId: propertyDocFileStoreId,
269
- buildingImageFileStoreId: buildingImageFileStoreId,
270
- userType: propertyDetails.userType?.value || null,
271
- noOfFloor: propertyDetails.noOfFloors?.value ? parseInt(propertyDetails.noOfFloors.value, 10) : null,
272
- typeOfConnection: propertyDetails.connectionCategory?.value || null,
273
- connectionCategory: propertyDetails.connectionType?.value || null,
274
- modifiedBy: userInfo.name || userInfo.userName || null,
275
- mobileNumber: aadhaarDetails.mobileNumber || null,
276
- email: aadhaarDetails.email || null,
277
- userName: aadhaarDetails.userName || null,
278
- noOfPersons: aadhaarDetails.noOfPersons || null,
279
- doorPhotoFileStoreId: doorPhotoFileStoreId,
280
- fullAddress: addressDetails.fullAddress || null,
281
- flatNo: addressDetails.flatNo || null,
282
- building: addressDetails.building || null,
283
- landmark: addressDetails.landmark || null,
284
- pincode: addressDetails.pincode || null,
285
- assembly: addressDetails.assembly || null,
286
- ward: addressDetails.ward || null,
287
- // Meter Details
288
- meterStatus: meterDetails.meterStatus?.value || null,
289
- meterWorkingStatus: meterDetails.workingStatus?.value || null,
290
- meterLocation: meterDetails.meterLocation || null,
291
- lastBillRaised: meterDetails.lastBillRaised?.value || null,
292
- noBillReason: meterDetails.noBillReason || null,
293
- sewerConnection: meterDetails.sewerConnection?.value || null,
294
- typeOfConnection: meterDetails.connectionCategory?.value || null,
295
- connectionCategory: meterDetails.connectionType?.value || null,
296
- meterImageFileStoreId: meterImageFileStoreId,
297
- };
298
-
299
- // ── 4. Call the update API using the new Hook ──────────────────────────
300
- mutate(requestBody, {
301
- onSuccess: (res) => {
302
- setToast({ type: "success", message: t("EKYC_SUBMIT_SUCCESS") || "Application submitted successfully!" });
133
+ const meterData = {
134
+ kno: editedMeter?.kno || apiMeter?.kno || activeKno,
135
+ metered: editedMeter?.meterStatusData?.value === "Metered" || apiMeter?.metered,
136
+ meterNumber: apiMeter?.meterNumber || apiMeter?.meterNo,
137
+ meterMake: editedMeter?.meterMake || apiMeter?.meterMake,
138
+ meterLocationAddress: editedMeter?.meterLocation || apiMeter?.meterLocationAddress,
139
+ meterLatitude: apiMeter?.meterLatitude,
140
+ meterLongitude: apiMeter?.meterLongitude,
141
+ workingStatus: editedMeter?.workingStatusData?.value === "Working" || apiMeter?.workingStatus,
142
+ lastBillRaised: editedMeter?.lastBillRaisedData?.value === "Yes" || apiMeter?.lastBillRaised,
143
+ systemMeterId: apiMeter?.systemMeterId,
144
+ meterPhotoFileStoreId: editedMeter?.meterPhotoFileStoreId || apiMeter?.meterPhotoFileStoreId,
145
+ };
303
146
 
304
- // Cleanup sessionStorage on success
305
- Object.keys(sessionStorage).forEach(key => {
306
- if (key.startsWith("EKYC_")) sessionStorage.removeItem(key);
307
- });
147
+ const handleDeclaration = () => setAgree(!agree);
308
148
 
309
- setTimeout(() => {
310
- history.push("/digit-ui/employee/ekyc/dashboard");
311
- }, 1800);
149
+ const handleFinalSubmit = async () => {
150
+ setIsSubmitting(true);
151
+ try {
152
+ const payload = {
153
+ kno: activeKno,
154
+ tenantId: tenantId,
155
+ newData: {
156
+ connectionDetails: connectionData,
157
+ addressDetails: addressData,
158
+ propertyInfo: propertyData,
159
+ meterDetails: meterData,
312
160
  },
313
- onError: (err) => {
314
- console.error("eKYC Submit Error:", err);
315
- setToast({
316
- type: "error",
317
- message: err?.response?.data?.Errors?.[0]?.message ||
318
- t("EKYC_SUBMIT_ERROR") || "Submission failed. Please try again.",
319
- });
320
- }
321
- });
161
+ };
322
162
 
163
+ const result = await Digit.EkycService.application_update(payload, tenantId);
164
+ if (result) {
165
+ history.push("/digit-ui/employee/ekyc/response", { success: true, result });
166
+ }
323
167
  } catch (err) {
324
- console.error("eKYC Frontend Error:", err);
325
- setToast({
326
- type: "error",
327
- message: t("EKYC_SUBMIT_ERROR") || "An error occurred during submission.",
328
- });
168
+ console.error("Submit Error:", err);
169
+ } finally {
170
+ setIsSubmitting(false);
329
171
  }
330
172
  };
331
173
 
332
- const handleEditAadhaar = () => {
333
- history.push("/digit-ui/employee/ekyc/aadhaar-verification", location.state);
334
- };
335
-
336
- const handleEditAddress = () => {
337
- history.push("/digit-ui/employee/ekyc/address-details", location.state);
338
- };
339
-
340
- const handleEditProperty = () => {
341
- history.push("/digit-ui/employee/ekyc/property-info", location.state);
342
- };
174
+ if (isSearchLoading || isSubmitting) return <Loader />;
343
175
 
344
- const handleEditMeter = () => {
345
- history.push("/digit-ui/employee/ekyc/meter-details", location.state);
346
- };
176
+ const baseUrl = "/digit-ui/employee/ekyc";
347
177
 
348
178
  return (
349
- <Fragment>
350
- <div className="inbox-container">
351
- <style>{`
352
- @keyframes fadeSlideIn {
353
- from { opacity: 0; transform: translateY(8px); }
354
- to { opacity: 1; transform: translateY(0); }
355
- }
356
- `}</style>
357
-
358
- {/* ── Sidebar ── */}
359
- <div className="filters-container">
360
- <Card style={{ display: "flex", alignItems: "center", padding: "12px 16px", marginBottom: "12px", borderRadius: "8px" }}>
361
- <div style={{ color: "#185FA5", marginRight: "10px", display: "flex" }}>
362
- <HomeIcon style={{ width: "20px", height: "20px" }} />
363
- </div>
364
- <div style={{ fontWeight: "600", fontSize: "15px", color: "#0B0C0C" }}>
365
- {t("EKYC_PROCESS") || "eKYC Process"}
366
- </div>
367
- </Card>
368
-
369
- <div style={{ background: "#fff", padding: "16px 14px", borderRadius: "8px", border: "1px solid #EAECF0" }}>
370
- {[
371
- { label: t("EKYC_STEP_AADHAAR") || "Aadhaar", done: true, active: false },
372
- { label: t("EKYC_STEP_ADDRESS") || "Address", done: true, active: false },
373
- { label: t("EKYC_STEP_PROPERTY") || "Property", done: true, active: false },
374
- { label: t("EKYC_STEP_METER") || "Meter", done: true, active: false },
375
- { label: t("EKYC_STEP_REVIEW") || "Review", done: false, active: true },
376
- ].map((step, i) => (
377
- <div key={i} style={{
378
- display: "flex", gap: "10px", alignItems: "flex-start",
379
- position: "relative", paddingBottom: i < 4 ? "18px" : 0,
380
- }}>
381
- {i < 4 && (
382
- <div style={{
383
- position: "absolute", left: "10px", top: "22px",
384
- width: "1px", height: "calc(100% - 10px)", background: "#EAECF0",
385
- }} />
386
- )}
387
- <div style={{
388
- width: "20px", height: "20px", borderRadius: "50%", flexShrink: 0, marginTop: "1px",
389
- border: step.done ? "none" : step.active ? "1.5px solid #185FA5" : "1.5px solid #D0D5DD",
390
- background: step.done ? "#0F6E56" : step.active ? "#E6F1FB" : "#fff",
391
- display: "flex", alignItems: "center", justifyContent: "center",
392
- fontSize: "10px", fontWeight: "500",
393
- color: step.done ? "#fff" : step.active ? "#185FA5" : "#98A2B3",
394
- }}>
395
- {step.done ? <CheckIcon size={11} color="#fff" /> : i + 1}
396
- </div>
397
- <div style={{
398
- fontSize: "12px", paddingTop: "2px",
399
- color: step.done ? "#0F6E56" : step.active ? "#0B0C0C" : "#667085",
400
- fontWeight: step.done || step.active ? "600" : "400",
401
- }}>
402
- {step.label}
403
- </div>
404
- </div>
405
- ))}
406
- </div>
407
- </div>
408
-
409
- {/* ── Main Content ── */}
410
- <div style={{ flex: 1, marginLeft: "16px" }}>
411
- <Card>
412
-
413
- {/* Page header */}
414
- <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "20px" }}>
415
- <CardHeader style={{ margin: 0, fontSize: "18px" }}>
416
- {t("EKYC_REVIEW_DETAILS") || "Review Details"}
417
- </CardHeader>
418
- <div style={{
419
- background: "#F9FAFB", border: "0.5px solid #EAECF0",
420
- borderRadius: "20px", padding: "4px 14px",
421
- fontSize: "12px", color: "#667085",
422
- }}>
423
- {t("EKYC_K_NUMBER") || "K Number"}:{" "}
424
- <span style={{ color: "#0B0C0C", fontWeight: "600" }}>{kNumber}</span>
425
- </div>
426
- </div>
427
-
428
- {/* Confirmation banner */}
429
- <div style={{
430
- backgroundColor: "#E1F5EE", border: "0.5px solid #5DCAA5",
431
- borderRadius: "8px", padding: "12px 16px",
432
- display: "flex", alignItems: "center", gap: "10px",
433
- marginBottom: "24px",
434
- }}>
435
- <div style={{ backgroundColor: "#9FE1CB", padding: "5px", borderRadius: "6px", display: "flex", flexShrink: 0 }}>
436
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#085041" strokeWidth="3" strokeLinecap="round">
437
- <polyline points="20 6 9 17 4 12" />
438
- </svg>
439
- </div>
440
- <div style={{ fontSize: "13px", color: "#04342C", fontWeight: "500" }}>
441
- {t("EKYC_REVIEW_NOTICE") || "Please review all details carefully before submitting. You can edit any section by clicking Edit."}
442
- </div>
443
- </div>
444
-
445
- <div style={{ animation: "fadeSlideIn 0.3s ease" }}>
446
-
447
- {/* ── Aadhaar section head ── */}
448
- <SectionHead
449
- icon={<PersonIcon size={16} />}
450
- label={t("EKYC_AADHAAR_VERIFICATION_HEADER") || "Aadhaar details"}
451
- />
452
-
453
- <ReviewCard
454
- icon={<PersonIcon size={16} />}
455
- title={t("EKYC_AADHAAR_VERIFICATION_HEADER") || "Aadhaar details"}
456
- onEdit={handleEditAadhaar}
457
- editLabel={t("CS_COMMON_EDIT") || "Edit"}
458
- t={t}
459
- rows={[
460
- { label: t("EKYC_NAME") || "Name", value: aadhaarDetails.userName || "Rajesh Kumar Singh", isModified: isFieldModified("userName", aadhaarDetails.userName) },
461
- { label: t("EKYC_AADHAAR") || "Aadhaar no.", value: aadhaarDetails.aadhaarLastFour ? `${aadhaarDetails.aadhaarLastFour}` : "XXXX XXXX 1234" },
462
- { label: t("EKYC_MOBILE_NO") || "Mobile no.", value: aadhaarDetails.mobileNumber || "XXXXXXXXXX", isModified: isFieldModified("mobileNumber", aadhaarDetails.mobileNumber) },
463
- { label: t("EKYC_EMAIL_ADDRESS") || "Email", value: aadhaarDetails.email || null, isModified: isFieldModified("email", aadhaarDetails.email) },
464
- ]}
465
- />
466
-
467
- <hr style={{ margin: "20px 0", border: 0, borderTop: "1px solid #EAECF0" }} />
468
-
469
- {/* ── Address section head ── */}
470
- <SectionHead
471
- icon={<LocationIcon2 size={16} />}
472
- label={t("EKYC_ADDRESS_DETAILS_HEADER") || "Address details"}
473
- />
474
-
475
- <ReviewCard
476
- icon={<LocationIcon2 size={16} />}
477
- title={t("EKYC_ADDRESS_DETAILS_HEADER") || "Address details"}
478
- onEdit={handleEditAddress}
479
- editLabel={t("CS_COMMON_EDIT") || "Edit"}
480
- t={t}
481
- rows={[
482
- { label: t("EKYC_FULL_ADDRESS") || "Full address", value: addressDetails.fullAddress || "H.No. 123, Sector 15, Rohini, Delhi – 110085", isModified: isFieldModified("fullAddress", addressDetails.fullAddress) },
483
- { label: t("EKYC_FLAT_HOUSE_NUMBER") || "Flat / House no.", value: addressDetails.flatNo || null, isModified: isFieldModified("flatNo", addressDetails.flatNo) },
484
- { label: t("EKYC_BUILDING_TOWER") || "Building", value: addressDetails.building || null, isModified: isFieldModified("building", addressDetails.building) },
485
- { label: t("EKYC_LANDMARK") || "Landmark", value: addressDetails.landmark || null, isModified: isFieldModified("landmark", addressDetails.landmark) },
486
- { label: t("EKYC_PINCODE") || "Pincode", value: addressDetails.pincode || "110085", isModified: isFieldModified("pincode", addressDetails.pincode) },
487
- { label: t("EKYC_ASSEMBLY") || "Assembly", value: addressDetails.assembly || "AC-12 Chandni Chowk", isModified: isFieldModified("assembly", addressDetails.assembly) },
488
- { label: t("EKYC_WARD") || "Ward", value: addressDetails.ward || "WARD-45 Civil Lines", isModified: isFieldModified("ward", addressDetails.ward) },
489
- ]}
490
- />
491
-
492
- <hr style={{ margin: "20px 0", border: 0, borderTop: "1px solid #EAECF0" }} />
493
-
494
- {/* ── Property section head ── */}
495
- <SectionHead
496
- icon={<BuildingIcon size={16} />}
497
- label={t("EKYC_PROPERTY_INFO") || "Property details"}
498
- />
499
-
500
- <ReviewCard
501
- icon={<BuildingIcon size={16} />}
502
- title={t("EKYC_PROPERTY_INFO") || "Property details"}
503
- onEdit={handleEditProperty}
504
- editLabel={t("CS_COMMON_EDIT") || "Edit"}
505
- t={t}
506
- rows={[
507
- { label: t("EKYC_PROPERTY_OWNER") || "Property owner", value: propertyDetails.ownerType || "Owner" },
508
- { label: t("EKYC_PID_NUMBER") || "PID number", value: propertyDetails.pidNumber || null, isModified: isFieldModified("pidNumber", propertyDetails.pidNumber) },
509
- { label: t("EKYC_TYPE_OF_CONNECTION") || "Type of connection", value: propertyDetails.connectionCategory?.label || null, isModified: isFieldModified("typeOfConnection", propertyDetails.connectionCategory?.value) },
510
- { label: t("EKYC_CONNECTION_CATEGORY") || "Connection category", value: propertyDetails.connectionType?.label || null, isModified: isFieldModified("connectionCategory", propertyDetails.connectionType?.value) },
511
- { label: t("EKYC_USER_TYPE") || "User type", value: propertyDetails.userType?.label || null, isModified: isFieldModified("userType", propertyDetails.userType?.value) },
512
- { label: t("EKYC_NO_OF_FLOORS") || "No. of floors", value: propertyDetails.noOfFloors?.label || null, isModified: isFieldModified("noOfFloor", propertyDetails.noOfFloors?.value) },
513
- ]}
514
- />
515
-
516
- <hr style={{ margin: "20px 0", border: 0, borderTop: "1px solid #EAECF0" }} />
517
-
518
- {/* ── Meter section head ── */}
519
- <SectionHead
520
- icon={<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67V7z" /></svg>}
521
- label={t("EKYC_METER_DETAILS_HEADER") || "Meter details"}
522
- />
523
-
524
- <ReviewCard
525
- icon={<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67V7z" /></svg>}
526
- title={t("EKYC_METER_DETAILS_HEADER") || "Meter details"}
527
- onEdit={handleEditMeter}
528
- editLabel={t("CS_COMMON_EDIT") || "Edit"}
529
- t={t}
530
- rows={[
531
- { label: t("EKYC_METER_STATUS") || "Meter status", value: meterDetails.meterStatus?.label || null, isModified: isFieldModified("meterStatus", meterDetails.meterStatus?.value) },
532
- { label: t("EKYC_METER_WORKING_STATUS") || "Meter working status", value: meterDetails.workingStatus?.label || null, isModified: isFieldModified("meterWorkingStatus", meterDetails.workingStatus?.value) },
533
- { label: t("EKYC_METER_LOCATION") || "Meter location", value: meterDetails.meterLocation || null, isModified: isFieldModified("meterLocation", meterDetails.meterLocation) },
534
- { label: t("EKYC_LAST_BILL_RAISED") || "Last bill raised", value: meterDetails.lastBillRaised?.label || null, isModified: isFieldModified("lastBillRaised", meterDetails.lastBillRaised?.value) },
535
- { label: t("EKYC_REASON_FOR_NO_BILL") || "Reason for no bill", value: meterDetails.noBillReason || null, isModified: isFieldModified("noBillReason", meterDetails.noBillReason) },
536
- { label: t("EKYC_SEWER_CONNECTION") || "Sewer connection", value: meterDetails.sewerConnection?.label || null, isModified: isFieldModified("sewerConnection", meterDetails.sewerConnection?.value) },
537
- { label: t("EKYC_TYPE_OF_CONNECTION") || "Type of connection", value: meterDetails.connectionCategory?.label || null, isModified: isFieldModified("typeOfConnection", meterDetails.connectionCategory?.value) },
538
- { label: t("EKYC_CONNECTION_CATEGORY") || "Connection category", value: meterDetails.connectionType?.label || null, isModified: isFieldModified("connectionCategory", meterDetails.connectionType?.value) },
539
- ]}
540
- />
541
-
542
- </div>
543
-
544
- {/* Submit (Non-sticky, at form end) */}
545
- <div style={{ marginTop: "24px" }}>
546
- <SubmitBar
547
- label={isSubmitting
548
- ? (t("EKYC_SUBMITTING") || "Submitting...")
549
- : (t("ES_COMMON_SUBMIT") || "Submit")
550
- }
551
- onSubmit={handleSubmit}
552
- disabled={isSubmitting}
553
- />
554
- </div>
555
-
556
- {/* Secure notice */}
557
- <div style={{
558
- display: "flex", alignItems: "center", justifyContent: "center",
559
- gap: "5px", marginTop: "16px",
560
- fontSize: "11px", color: "#98A2B3",
561
- }}>
562
- <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
563
- <rect x="3" y="11" width="18" height="11" rx="2" />
564
- <path d="M7 11V7a5 5 0 0 1 10 0v4" />
565
- </svg>
566
- {t("EKYC_SECURE_DATA_NOTICE") || "Your data is encrypted and secure"}
567
- </div>
568
-
569
- </Card>
179
+ <div className="review-container">
180
+ <Card>
181
+ {/* ── Header ───────────────────────────────────────────────────── */}
182
+ <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "20px" }}>
183
+ <CardHeader style={{ margin: 0 }}>{t("EKYC_REVIEW_APPLICATION")}</CardHeader>
184
+ <div style={{
185
+ background: "#F9FAFB", border: "0.5px solid #EAECF0",
186
+ borderRadius: "20px", padding: "4px 14px",
187
+ fontSize: "12px", color: "#667085",
188
+ }}>
189
+ {t("EKYC_K_NUMBER")}: <span style={{ color: "#0B0C0C", fontWeight: "600" }}>{activeKno}</span>
570
190
  </div>
571
191
  </div>
572
192
 
573
- {/* Toast notification */}
574
- {toast && (
575
- <Toast
576
- label={toast.message}
577
- error={toast.type === "error"}
578
- success={toast.type === "success"}
579
- onClose={() => setToast(null)}
193
+ {/* ── 1. Connection Details ────────────────────────────────────── */}
194
+ <CardSubHeader>{t("EKYC_CONNECTION_DETAILS")}</CardSubHeader>
195
+ <StatusTable style={{ marginTop: "20px", marginBottom: "30px" }}>
196
+ <Row label={t("EKYC_K_NUMBER")} text={checkForNA(connectionData.knumber)} />
197
+ <Row label={t("EKYC_CONSUMER_NAME")} text={checkForNA(connectionData.consumerName)} />
198
+ <Row label={t("EKYC_ADDRESS")} text={checkForNA(connectionData.address)} />
199
+ <Row label={t("EKYC_CONNECTION_TYPE")} text={checkForNA(connectionData.connectionType)} />
200
+ <Row label={t("EKYC_METER_NO")} text={checkForNA(connectionData.meterNumber)} />
201
+ <Row label={t("EKYC_MOBILE_NO")} text={checkForNA(connectionData.phoneNumber)} />
202
+ <Row label={t("EKYC_EMAIL")} text={checkForNA(connectionData.email)} />
203
+ <Row label={t("EKYC_STATUS_FLAG")} text={checkForNA(connectionData.statusflag)} />
204
+ <Row label={t("EKYC_STATUS")} text={checkForNA(connectionData.ekycStatus)} />
205
+ </StatusTable>
206
+
207
+ {/* ── 2. Address Details ──────────────────────────────────────── */}
208
+ <CardSubHeader>{t("EKYC_ADDRESS_DETAILS")}</CardSubHeader>
209
+ <StatusTable style={{ marginTop: "20px", marginBottom: "30px" }}>
210
+ <Row
211
+ label={t("EKYC_FULL_ADDRESS")}
212
+ text={checkForNA(addressData.fullAddress)}
213
+ actionButton={<ActionButton jumpTo={`${baseUrl}/address-details`} state={{ ...flowState, reviewData: searchData, edits }} />}
214
+ />
215
+ <Row label={t("EKYC_FLAT_HOUSE_NO")} text={checkForNA(addressData.flatHouseNumber)} />
216
+ <Row label={t("EKYC_BUILDING_TOWER")} text={checkForNA(addressData.buildingTower)} />
217
+ <Row label={t("EKYC_LANDMARK")} text={checkForNA(addressData.landmark)} />
218
+ <Row label={t("EKYC_PINCODE")} text={checkForNA(addressData.pinCode)} />
219
+ <Row label={t("EKYC_LOCALITY")} text={checkForNA(addressData.ward)} />
220
+ <Row label={t("EKYC_ASSEMBLY")} text={checkForNA(addressData.assembly)} />
221
+ <Row label={t("EKYC_GPS_VALID")} text={boolToYesNo(addressData.gpsValid, t)} />
222
+ <Row label={t("EKYC_LATITUDE")} text={checkForNA(addressData.latitude)} />
223
+ <Row label={t("EKYC_LONGITUDE")} text={checkForNA(addressData.longitude)} />
224
+ <Row label={t("EKYC_MOBILE_NO")} text={checkForNA(addressData.mobileNo)} />
225
+ <Row label={t("EKYC_WHATSAPP_NO")} text={checkForNA(addressData.whatsappNo)} />
226
+ <Row label={t("EKYC_EMAIL")} text={checkForNA(addressData.email)} />
227
+ <Row label={t("EKYC_NO_OF_PERSONS")} text={checkForNA(addressData.noOfPerson)} />
228
+ <Row label={t("EKYC_K_NUMBER")} text={checkForNA(addressData.knumber)} />
229
+ </StatusTable>
230
+
231
+ {/* ── 3. Property Info ────────────────────────────────────────── */}
232
+ <CardSubHeader>{t("EKYC_PROPERTY_INFO")}</CardSubHeader>
233
+ <StatusTable style={{ marginTop: "20px", marginBottom: "30px" }}>
234
+ <Row
235
+ label={t("EKYC_CONNECTION_CATEGORY")}
236
+ text={checkForNA(propertyData.connectionCategory)}
237
+ actionButton={<ActionButton jumpTo={`${baseUrl}/property-info`} state={{ ...flowState, reviewData: searchData, edits }} />}
580
238
  />
581
- )}
582
- </Fragment>
239
+ {/* <Row label={t("EKYC_KNO")} text={checkForNA(propertyData.kno)} /> */}
240
+ <Row label={t("EKYC_PID_NUMBER")} text={checkForNA(propertyData.pidNumber)} />
241
+ <Row label={t("EKYC_TYPE_OF_CONNECTION")} text={checkForNA(propertyData.typeOfConnection)} />
242
+ <Row label={t("EKYC_USER_TYPE")} text={checkForNA(propertyData.userType)} />
243
+ <Row label={t("EKYC_FLOOR_COUNT")} text={checkForNA(propertyData.numberOfFloors)} />
244
+ <Row label={t("EKYC_TENANT_NAME")} text={checkForNA(propertyData.tenantName)} />
245
+ <Row label={t("EKYC_TENANT_MOBILE")} text={checkForNA(propertyData.tenantMobile)} />
246
+ <Row label={t("EKYC_STATUS")} text={checkForNA(propertyData.ekycStatus)} />
247
+ </StatusTable>
248
+
249
+ {/* ── 4. Meter Details ────────────────────────────────────────── */}
250
+ <CardSubHeader>{t("EKYC_METER_DETAILS")}</CardSubHeader>
251
+ <StatusTable style={{ marginTop: "20px", marginBottom: "30px" }}>
252
+ <Row
253
+ label={t("EKYC_METERED")}
254
+ text={boolToYesNo(meterData.metered, t)}
255
+ actionButton={<ActionButton jumpTo={`${baseUrl}/meter-details`} state={{ ...flowState, reviewData: searchData, edits }} />}
256
+ />
257
+ {/* <Row label={t("EKYC_KNO")} text={checkForNA(meterData.kno)} /> */}
258
+ <Row label={t("EKYC_METER_NO")} text={checkForNA(meterData.meterNumber)} />
259
+ <Row label={t("EKYC_METER_MAKE")} text={checkForNA(meterData.meterMake)} />
260
+ <Row label={t("EKYC_METER_LOCATION_ADDRESS")} text={checkForNA(meterData.meterLocationAddress)} />
261
+ <Row label={t("EKYC_METER_LATITUDE")} text={checkForNA(meterData.meterLatitude)} />
262
+ <Row label={t("EKYC_METER_LONGITUDE")} text={checkForNA(meterData.meterLongitude)} />
263
+ <Row label={t("EKYC_WORKING_STATUS")} text={boolToYesNo(meterData.workingStatus, t)} />
264
+ <Row label={t("EKYC_LAST_BILL_RAISED")} text={boolToYesNo(meterData.lastBillRaised, t)} />
265
+ <Row label={t("EKYC_SYSTEM_METER_ID")} text={checkForNA(meterData.systemMeterId)} />
266
+ </StatusTable>
267
+
268
+ {/* ── 5. Documents ────────────────────────────────────────────── */}
269
+ <CardSubHeader>{t("EKYC_DOCUMENTS")}</CardSubHeader>
270
+ <StatusTable style={{ marginTop: "20px", marginBottom: "30px" }}>
271
+ <Row
272
+ label={t("EKYC_DOOR_PHOTO")}
273
+ text={addressData.doorPhotoFilestoreId ? t("EKYC_PHOTO_AVAILABLE") : t("CS_NA")}
274
+ actionButton={addressData.doorPhotoFilestoreId && <GenericFileIcon style={{ cursor: "pointer" }} />}
275
+ />
276
+ <Row
277
+ label={t("EKYC_METER_PHOTO")}
278
+ text={meterData.meterPhotoFileStoreId ? t("EKYC_PHOTO_AVAILABLE") : t("CS_NA")}
279
+ actionButton={meterData.meterPhotoFileStoreId && <GenericFileIcon style={{ cursor: "pointer" }} />}
280
+ />
281
+ <Row
282
+ label={t("EKYC_BUILDING_IMAGE")}
283
+ text={propertyData.buildingImageFileStoreId ? t("EKYC_PHOTO_AVAILABLE") : t("CS_NA")}
284
+ actionButton={propertyData.buildingImageFileStoreId && <GenericFileIcon style={{ cursor: "pointer" }} />}
285
+ />
286
+ <Row
287
+ label={t("EKYC_PROPERTY_DOCUMENTS")}
288
+ text={propertyData.propertyDocumentFileStoreId ? t("EKYC_DOCS_AVAILABLE") : t("CS_NA")}
289
+ actionButton={propertyData.propertyDocumentFileStoreId && <GenericFileIcon style={{ cursor: "pointer" }} />}
290
+ />
291
+ </StatusTable>
292
+
293
+ <CheckBox
294
+ id="agreeDeclaration"
295
+ name="agreeDeclaration"
296
+ label={t("EKYC_FINAL_DECLARATION")}
297
+ onChange={handleDeclaration}
298
+ checked={agree}
299
+ style={{ marginTop: "20px" }}
300
+ />
301
+ </Card>
302
+
303
+ <ActionBar style={{ position: "static", marginTop: "24px" }}>
304
+ <SubmitBar
305
+ label={t("EKYC_SUBMIT_APPLICATION")}
306
+ onSubmit={handleFinalSubmit}
307
+ disabled={!agree}
308
+ />
309
+ </ActionBar>
310
+ </div>
583
311
  );
584
312
  };
585
313