@djb25/digit-ui-module-ekyc 1.0.6 → 1.0.8
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 +1969 -737
- package/dist/index.modern.js.map +1 -1
- package/package.json +4 -2
- package/src/Module.js +17 -1
- package/src/components/ConnectionDetailsView.js +180 -59
- package/src/components/DesktopInbox.js +153 -7
- package/src/components/EKYCCard.js +4 -0
- package/src/components/SearchConsumer.js +104 -94
- package/src/components/StatusCards.js +145 -16
- package/src/pages/citizen/index.js +90 -0
- package/src/pages/employee/AadhaarVerification.js +324 -281
- package/src/pages/employee/AddressDetails.js +127 -102
- package/src/pages/employee/Create.js +10 -0
- package/src/pages/employee/Inbox.js +11 -4
- package/src/pages/employee/Mapping.js +11 -0
- package/src/pages/employee/MeterDetails.js +486 -0
- package/src/pages/employee/PropertyInfo.js +387 -323
- package/src/pages/employee/Review.js +371 -227
- package/src/pages/employee/index.js +14 -1
- package/src/utils/index.js +46 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { Fragment, useState } from "react";
|
|
1
|
+
import React, { Fragment, useState, useEffect } from "react";
|
|
2
2
|
import {
|
|
3
3
|
Card,
|
|
4
4
|
CardHeader,
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
} from "@djb25/digit-ui-react-components";
|
|
10
10
|
import { useTranslation } from "react-i18next";
|
|
11
11
|
import { useHistory, useLocation } from "react-router-dom";
|
|
12
|
+
import { getPayloadDiff, getSavedData } from "../../utils";
|
|
12
13
|
|
|
13
14
|
// ─── Icons ────────────────────────────────────────────────────────────────────
|
|
14
15
|
|
|
@@ -60,7 +61,7 @@ const SectionHead = ({ icon, label }) => (
|
|
|
60
61
|
|
|
61
62
|
// ─── Reusable: Review section card ───────────────────────────────────────────
|
|
62
63
|
|
|
63
|
-
const ReviewCard = ({ icon, title, onEdit, editLabel, rows }) => (
|
|
64
|
+
const ReviewCard = ({ icon, title, onEdit, editLabel, rows, t }) => (
|
|
64
65
|
<div style={{
|
|
65
66
|
border: "0.5px solid #EAECF0",
|
|
66
67
|
borderRadius: "10px",
|
|
@@ -110,8 +111,22 @@ const ReviewCard = ({ icon, title, onEdit, editLabel, rows }) => (
|
|
|
110
111
|
}}>
|
|
111
112
|
{row.label}
|
|
112
113
|
</div>
|
|
113
|
-
<div style={{ flex: 1, fontSize: "14px", color: "#101828", fontWeight: "500", wordBreak: "break-word" }}>
|
|
114
|
+
<div style={{ flex: 1, fontSize: "14px", color: "#101828", fontWeight: "500", wordBreak: "break-word", display: "flex", alignItems: "center", gap: "8px" }}>
|
|
114
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
|
+
)}
|
|
115
130
|
</div>
|
|
116
131
|
</div>
|
|
117
132
|
) : null
|
|
@@ -127,15 +142,71 @@ const Review = () => {
|
|
|
127
142
|
const history = useHistory();
|
|
128
143
|
const location = useLocation();
|
|
129
144
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
+
};
|
|
158
|
+
|
|
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
|
+
};
|
|
170
|
+
|
|
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
|
+
};
|
|
181
|
+
|
|
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
|
+
};
|
|
194
|
+
|
|
195
|
+
useEffect(() => {
|
|
196
|
+
sessionStorage.setItem("EKYC_CURRENT_STEP", "REVIEW");
|
|
197
|
+
}, []);
|
|
198
|
+
|
|
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);
|
|
204
|
+
};
|
|
136
205
|
|
|
137
|
-
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
138
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;
|
|
139
210
|
|
|
140
211
|
// ── Helper: upload a File object to Filestore ──────────────────────────────
|
|
141
212
|
const uploadFile = async (file, tenantId) => {
|
|
@@ -156,32 +227,41 @@ const Review = () => {
|
|
|
156
227
|
};
|
|
157
228
|
|
|
158
229
|
const handleSubmit = async () => {
|
|
159
|
-
setIsSubmitting(true);
|
|
160
230
|
setToast(null);
|
|
161
231
|
try {
|
|
162
|
-
const tenantId = Digit.ULBService.getCurrentTenantId() || "dl.djb";
|
|
163
232
|
const userInfo = Digit.UserService.getUser()?.info || {};
|
|
164
233
|
|
|
165
|
-
// ── 1. Upload property document
|
|
166
|
-
|
|
167
|
-
|
|
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
|
+
}
|
|
168
239
|
|
|
169
|
-
// ── 2. Upload building photo
|
|
170
|
-
let buildingImageFileStoreId = null;
|
|
171
|
-
if (propertyDetails.buildingPhoto) {
|
|
240
|
+
// ── 2. Upload building photo ──────────────────────────────────────────
|
|
241
|
+
let buildingImageFileStoreId = propertyDetails.buildingPhotoFileStoreId || null;
|
|
242
|
+
if (!buildingImageFileStoreId && propertyDetails.buildingPhoto) {
|
|
243
|
+
// Fallback if we only have the dataURL
|
|
172
244
|
const photoFile = dataUrlToFile(propertyDetails.buildingPhoto, "building_photo.jpg");
|
|
173
245
|
buildingImageFileStoreId = await uploadFile(photoFile, tenantId);
|
|
174
246
|
}
|
|
175
247
|
|
|
176
|
-
// ── 3.
|
|
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
|
|
177
264
|
const requestBody = {
|
|
178
|
-
RequestInfo: {
|
|
179
|
-
apiId: "Rainmaker",
|
|
180
|
-
ver: "1.0",
|
|
181
|
-
msgId: `${Date.now()}|${navigator.language || "en_IN"}`,
|
|
182
|
-
tenantId,
|
|
183
|
-
authToken: userInfo.access_token || Digit.UserService.getUser()?.access_token || "",
|
|
184
|
-
},
|
|
185
265
|
updateType: "PROPERTY",
|
|
186
266
|
kno: kNumber,
|
|
187
267
|
pidNumber: propertyDetails.pidNumber || null,
|
|
@@ -192,30 +272,60 @@ const Review = () => {
|
|
|
192
272
|
typeOfConnection: propertyDetails.connectionCategory?.value || null,
|
|
193
273
|
connectionCategory: propertyDetails.connectionType?.value || null,
|
|
194
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,
|
|
195
297
|
};
|
|
196
298
|
|
|
197
|
-
// ── 4. Call the update API
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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!" });
|
|
303
|
+
|
|
304
|
+
// Cleanup sessionStorage on success
|
|
305
|
+
Object.keys(sessionStorage).forEach(key => {
|
|
306
|
+
if (key.startsWith("EKYC_")) sessionStorage.removeItem(key);
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
setTimeout(() => {
|
|
310
|
+
history.push("/digit-ui/employee/ekyc/dashboard");
|
|
311
|
+
}, 1800);
|
|
312
|
+
},
|
|
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
|
+
}
|
|
204
321
|
});
|
|
205
322
|
|
|
206
|
-
setToast({ type: "success", message: t("EKYC_SUBMIT_SUCCESS") || "Application submitted successfully!" });
|
|
207
|
-
setTimeout(() => {
|
|
208
|
-
history.push("/digit-ui/employee/ekyc/dashboard");
|
|
209
|
-
}, 1800);
|
|
210
323
|
} catch (err) {
|
|
211
|
-
console.error("eKYC
|
|
324
|
+
console.error("eKYC Frontend Error:", err);
|
|
212
325
|
setToast({
|
|
213
326
|
type: "error",
|
|
214
|
-
message:
|
|
215
|
-
t("EKYC_SUBMIT_ERROR") || "Submission failed. Please try again.",
|
|
327
|
+
message: t("EKYC_SUBMIT_ERROR") || "An error occurred during submission.",
|
|
216
328
|
});
|
|
217
|
-
} finally {
|
|
218
|
-
setIsSubmitting(false);
|
|
219
329
|
}
|
|
220
330
|
};
|
|
221
331
|
|
|
@@ -231,211 +341,245 @@ const Review = () => {
|
|
|
231
341
|
history.push("/digit-ui/employee/ekyc/property-info", location.state);
|
|
232
342
|
};
|
|
233
343
|
|
|
344
|
+
const handleEditMeter = () => {
|
|
345
|
+
history.push("/digit-ui/employee/ekyc/meter-details", location.state);
|
|
346
|
+
};
|
|
347
|
+
|
|
234
348
|
return (
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
349
|
+
<Fragment>
|
|
350
|
+
<div className="inbox-container">
|
|
351
|
+
<style>{`
|
|
238
352
|
@keyframes fadeSlideIn {
|
|
239
353
|
from { opacity: 0; transform: translateY(8px); }
|
|
240
354
|
to { opacity: 1; transform: translateY(0); }
|
|
241
355
|
}
|
|
242
356
|
`}</style>
|
|
243
357
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
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>
|
|
252
407
|
</div>
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
display: "flex", gap: "10px", alignItems: "flex-start",
|
|
264
|
-
position: "relative", paddingBottom: i < 3 ? "18px" : 0,
|
|
265
|
-
}}>
|
|
266
|
-
{i < 3 && (
|
|
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>
|
|
267
418
|
<div style={{
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
background: step.done ? "#0F6E56" : step.active ? "#E6F1FB" : "#fff",
|
|
276
|
-
display: "flex", alignItems: "center", justifyContent: "center",
|
|
277
|
-
fontSize: "10px", fontWeight: "500",
|
|
278
|
-
color: step.done ? "#fff" : step.active ? "#185FA5" : "#98A2B3",
|
|
279
|
-
}}>
|
|
280
|
-
{step.done ? <CheckIcon size={11} color="#fff" /> : i + 1}
|
|
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>
|
|
281
426
|
</div>
|
|
427
|
+
|
|
428
|
+
{/* Confirmation banner */}
|
|
282
429
|
<div style={{
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
430
|
+
backgroundColor: "#E1F5EE", border: "0.5px solid #5DCAA5",
|
|
431
|
+
borderRadius: "8px", padding: "12px 16px",
|
|
432
|
+
display: "flex", alignItems: "center", gap: "10px",
|
|
433
|
+
marginBottom: "24px",
|
|
286
434
|
}}>
|
|
287
|
-
{
|
|
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>
|
|
288
443
|
</div>
|
|
289
|
-
</div>
|
|
290
|
-
))}
|
|
291
|
-
</div>
|
|
292
|
-
</div>
|
|
293
|
-
|
|
294
|
-
{/* ── Main Content ── */}
|
|
295
|
-
<div style={{ flex: 1, marginLeft: "16px" }}>
|
|
296
|
-
<Card>
|
|
297
444
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
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
|
+
/>
|
|
329
541
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
{/* ── Aadhaar section head ── */}
|
|
333
|
-
<SectionHead
|
|
334
|
-
icon={<PersonIcon size={16} />}
|
|
335
|
-
label={t("EKYC_AADHAAR_VERIFICATION_HEADER") || "Aadhaar details"}
|
|
336
|
-
/>
|
|
337
|
-
|
|
338
|
-
<ReviewCard
|
|
339
|
-
icon={<PersonIcon size={16} />}
|
|
340
|
-
title={t("EKYC_AADHAAR_VERIFICATION_HEADER") || "Aadhaar details"}
|
|
341
|
-
onEdit={handleEditAadhaar}
|
|
342
|
-
editLabel={t("CS_COMMON_EDIT") || "Edit"}
|
|
343
|
-
rows={[
|
|
344
|
-
{ label: t("EKYC_NAME") || "Name", value: aadhaarDetails.userName || "Rajesh Kumar Singh" },
|
|
345
|
-
{ label: t("EKYC_AADHAAR") || "Aadhaar no.", value: aadhaarDetails.aadhaarLastFour ? `${aadhaarDetails.aadhaarLastFour}` : "XXXX XXXX 1234" },
|
|
346
|
-
{ label: t("EKYC_MOBILE_NO") || "Mobile no.", value: aadhaarDetails.mobileNumber || "XXXXXXXXXX" },
|
|
347
|
-
{ label: t("EKYC_EMAIL_ADDRESS") || "Email", value: aadhaarDetails.email || null },
|
|
348
|
-
]}
|
|
349
|
-
/>
|
|
350
|
-
|
|
351
|
-
<hr style={{ margin: "20px 0", border: 0, borderTop: "1px solid #EAECF0" }} />
|
|
352
|
-
|
|
353
|
-
{/* ── Address section head ── */}
|
|
354
|
-
<SectionHead
|
|
355
|
-
icon={<LocationIcon2 size={16} />}
|
|
356
|
-
label={t("EKYC_ADDRESS_DETAILS_HEADER") || "Address details"}
|
|
357
|
-
/>
|
|
358
|
-
|
|
359
|
-
<ReviewCard
|
|
360
|
-
icon={<LocationIcon2 size={16} />}
|
|
361
|
-
title={t("EKYC_ADDRESS_DETAILS_HEADER") || "Address details"}
|
|
362
|
-
onEdit={handleEditAddress}
|
|
363
|
-
editLabel={t("CS_COMMON_EDIT") || "Edit"}
|
|
364
|
-
rows={[
|
|
365
|
-
{ label: t("EKYC_FULL_ADDRESS") || "Full address", value: addressDetails.fullAddress || "H.No. 123, Sector 15, Rohini, Delhi – 110085" },
|
|
366
|
-
{ label: t("EKYC_FLAT_HOUSE_NUMBER") || "Flat / House no.", value: addressDetails.flatNo || null },
|
|
367
|
-
{ label: t("EKYC_BUILDING_TOWER") || "Building", value: addressDetails.building || null },
|
|
368
|
-
{ label: t("EKYC_LANDMARK") || "Landmark", value: addressDetails.landmark || null },
|
|
369
|
-
{ label: t("EKYC_PINCODE") || "Pincode", value: addressDetails.pincode || "110085" },
|
|
370
|
-
{ label: t("EKYC_ASSEMBLY") || "Assembly", value: addressDetails.assembly || "AC-12 Chandni Chowk" },
|
|
371
|
-
{ label: t("EKYC_WARD") || "Ward", value: addressDetails.ward || "WARD-45 Civil Lines" },
|
|
372
|
-
]}
|
|
373
|
-
/>
|
|
374
|
-
|
|
375
|
-
<hr style={{ margin: "20px 0", border: 0, borderTop: "1px solid #EAECF0" }} />
|
|
376
|
-
|
|
377
|
-
{/* ── Property section head ── */}
|
|
378
|
-
<SectionHead
|
|
379
|
-
icon={<BuildingIcon size={16} />}
|
|
380
|
-
label={t("EKYC_PROPERTY_INFO") || "Property details"}
|
|
381
|
-
/>
|
|
382
|
-
|
|
383
|
-
<ReviewCard
|
|
384
|
-
icon={<BuildingIcon size={16} />}
|
|
385
|
-
title={t("EKYC_PROPERTY_INFO") || "Property details"}
|
|
386
|
-
onEdit={handleEditProperty}
|
|
387
|
-
editLabel={t("CS_COMMON_EDIT") || "Edit"}
|
|
388
|
-
rows={[
|
|
389
|
-
{ label: t("EKYC_PROPERTY_OWNER") || "Property owner", value: propertyDetails.ownerType || "Owner" },
|
|
390
|
-
{ label: t("EKYC_PID_NUMBER") || "PID number", value: propertyDetails.pidNumber || null },
|
|
391
|
-
{ label: t("EKYC_TYPE_OF_CONNECTION") || "Type of connection", value: propertyDetails.connectionCategory?.label || null },
|
|
392
|
-
{ label: t("EKYC_CONNECTION_CATEGORY") || "Connection category", value: propertyDetails.connectionType?.label || null },
|
|
393
|
-
{ label: t("EKYC_USER_TYPE") || "User type", value: propertyDetails.userType?.label || null },
|
|
394
|
-
{ label: t("EKYC_NO_OF_FLOORS") || "No. of floors", value: propertyDetails.noOfFloors?.label || null },
|
|
395
|
-
]}
|
|
396
|
-
/>
|
|
542
|
+
</div>
|
|
397
543
|
|
|
398
|
-
|
|
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>
|
|
399
555
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
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>
|
|
411
568
|
|
|
412
|
-
|
|
413
|
-
<div style={{
|
|
414
|
-
display: "flex", alignItems: "center", justifyContent: "center",
|
|
415
|
-
gap: "5px", marginTop: "16px",
|
|
416
|
-
fontSize: "11px", color: "#98A2B3",
|
|
417
|
-
}}>
|
|
418
|
-
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
419
|
-
<rect x="3" y="11" width="18" height="11" rx="2" />
|
|
420
|
-
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
|
|
421
|
-
</svg>
|
|
422
|
-
{t("EKYC_SECURE_DATA_NOTICE") || "Your data is encrypted and secure"}
|
|
569
|
+
</Card>
|
|
423
570
|
</div>
|
|
571
|
+
</div>
|
|
424
572
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
onClose={() => setToast(null)}
|
|
436
|
-
/>
|
|
437
|
-
)}
|
|
438
|
-
</Fragment>
|
|
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)}
|
|
580
|
+
/>
|
|
581
|
+
)}
|
|
582
|
+
</Fragment>
|
|
439
583
|
);
|
|
440
584
|
};
|
|
441
585
|
|