@djb25/digit-ui-module-ekyc 1.0.5 → 1.0.7
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 +1142 -497
- package/dist/index.modern.js.map +1 -1
- package/package.json +4 -2
- package/src/components/DesktopInbox.js +208 -60
- package/src/components/Filter.js +5 -4
- package/src/components/StatusCards.js +167 -16
- package/src/pages/employee/AadhaarVerification.js +341 -249
- package/src/pages/employee/AddressDetails.js +148 -124
- package/src/pages/employee/Create.js +31 -19
- package/src/pages/employee/Inbox.js +14 -8
- package/src/pages/employee/PropertyInfo.js +382 -302
- package/src/pages/employee/Review.js +365 -179
- package/src/utils/index.js +46 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useRef, Fragment } from "react";
|
|
1
|
+
import React, { useState, useRef, Fragment, useEffect } from "react";
|
|
2
2
|
import {
|
|
3
3
|
Card,
|
|
4
4
|
CardLabel,
|
|
@@ -9,9 +9,12 @@ import {
|
|
|
9
9
|
Dropdown,
|
|
10
10
|
InfoBannerIcon,
|
|
11
11
|
HomeIcon,
|
|
12
|
+
UploadFile,
|
|
13
|
+
Toast,
|
|
12
14
|
} from "@djb25/digit-ui-react-components";
|
|
13
15
|
import { useTranslation } from "react-i18next";
|
|
14
16
|
import { useHistory, useLocation } from "react-router-dom";
|
|
17
|
+
import { getPayloadDiff, getSavedData } from "../../utils";
|
|
15
18
|
|
|
16
19
|
// ─── Icons ────────────────────────────────────────────────────────────────────
|
|
17
20
|
|
|
@@ -98,8 +101,12 @@ const PropertyInfo = () => {
|
|
|
98
101
|
const history = useHistory();
|
|
99
102
|
const location = useLocation();
|
|
100
103
|
|
|
101
|
-
const flowState = location.state || {
|
|
104
|
+
const flowState = location.state || {
|
|
105
|
+
kNumber: sessionStorage.getItem("EKYC_K_NUMBER") || "EKYC-1234567890",
|
|
106
|
+
initialData: getSavedData("EKYC_INITIAL_DATA", {})
|
|
107
|
+
};
|
|
102
108
|
const { kNumber } = flowState;
|
|
109
|
+
const initialData = flowState.initialData || getSavedData("EKYC_INITIAL_DATA", {});
|
|
103
110
|
|
|
104
111
|
const tenantId = Digit.ULBService.getCurrentTenantId();
|
|
105
112
|
const { data: dataV0 } = Digit.Hooks.ekyc.useGetPropertyType(tenantId);
|
|
@@ -107,14 +114,120 @@ const PropertyInfo = () => {
|
|
|
107
114
|
const { data: dataV1 } = Digit.Hooks.ekyc.useGetUserType(tenantId);
|
|
108
115
|
const { data: dataV2 } = Digit.Hooks.ekyc.useGetFloorCount(tenantId);
|
|
109
116
|
|
|
110
|
-
const [ownerType, setOwnerType] = useState("OWNER");
|
|
111
|
-
const [pidNumber, setPidNumber] = useState("");
|
|
112
|
-
const [connectionCategory, setConnectionCategory] = useState(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const [
|
|
116
|
-
|
|
117
|
-
|
|
117
|
+
const [ownerType, setOwnerType] = useState(() => sessionStorage.getItem("EKYC_OWNER_TYPE") || initialData.ownerType || "OWNER");
|
|
118
|
+
const [pidNumber, setPidNumber] = useState(() => sessionStorage.getItem("EKYC_PID_NUMBER") || initialData.pidNumber || "");
|
|
119
|
+
const [connectionCategory, setConnectionCategory] = useState(() =>
|
|
120
|
+
getSavedData("EKYC_TYPE_OF_CONNECTION_DATA", initialData.typeOfConnection ? { label: t(initialData.typeOfConnection), value: initialData.typeOfConnection } : null)
|
|
121
|
+
);
|
|
122
|
+
const [connectionType, setConnectionType] = useState(() =>
|
|
123
|
+
getSavedData("EKYC_CONNECTION_CATEGORY_DATA", initialData.connectionCategory ? { label: t(initialData.connectionCategory), value: initialData.connectionCategory } : null)
|
|
124
|
+
);
|
|
125
|
+
const [userType, setUserType] = useState(() =>
|
|
126
|
+
getSavedData("EKYC_USER_TYPE_DATA", initialData.userType ? { label: t(initialData.userType), value: initialData.userType } : null)
|
|
127
|
+
);
|
|
128
|
+
const [noOfFloors, setNoOfFloors] = useState(() =>
|
|
129
|
+
getSavedData("EKYC_NO_OF_FLOORS_DATA", initialData.noOfFloor ? { label: t(initialData.noOfFloor), value: initialData.noOfFloor } : null)
|
|
130
|
+
);
|
|
131
|
+
const [propertyDocument, setPropertyDocument] = useState(() => sessionStorage.getItem("EKYC_PROPERTY_DOC") || null);
|
|
132
|
+
const [propertyDocumentFileStoreId, setPropertyDocumentFileStoreId] = useState(() => sessionStorage.getItem("EKYC_PROPERTY_DOC_FILESTORE_ID") || null);
|
|
133
|
+
const [buildingPhoto, setBuildingPhoto] = useState(() => sessionStorage.getItem("EKYC_BUILDING_PHOTO") || null);
|
|
134
|
+
const [buildingPhotoFileStoreId, setBuildingPhotoFileStoreId] = useState(() => sessionStorage.getItem("EKYC_BUILDING_PHOTO_FILESTORE_ID") || null);
|
|
135
|
+
|
|
136
|
+
const [filepdf, setFilepdf] = useState(null);
|
|
137
|
+
const [filephoto, setFilephoto] = useState(null);
|
|
138
|
+
const [error, setError] = useState(null);
|
|
139
|
+
const [toast, setToast] = useState(null);
|
|
140
|
+
|
|
141
|
+
// Sync property state to sessionStorage
|
|
142
|
+
useEffect(() => {
|
|
143
|
+
sessionStorage.setItem("EKYC_OWNER_TYPE", ownerType);
|
|
144
|
+
sessionStorage.setItem("EKYC_PID_NUMBER", pidNumber);
|
|
145
|
+
sessionStorage.setItem("EKYC_TYPE_OF_CONNECTION_DATA", JSON.stringify(connectionCategory));
|
|
146
|
+
sessionStorage.setItem("EKYC_CONNECTION_CATEGORY_DATA", JSON.stringify(connectionType));
|
|
147
|
+
sessionStorage.setItem("EKYC_USER_TYPE_DATA", JSON.stringify(userType));
|
|
148
|
+
sessionStorage.setItem("EKYC_NO_OF_FLOORS_DATA", JSON.stringify(noOfFloors));
|
|
149
|
+
if (propertyDocument) sessionStorage.setItem("EKYC_PROPERTY_DOC", propertyDocument);
|
|
150
|
+
if (propertyDocumentFileStoreId) sessionStorage.setItem("EKYC_PROPERTY_DOC_FILESTORE_ID", propertyDocumentFileStoreId);
|
|
151
|
+
if (buildingPhoto) sessionStorage.setItem("EKYC_BUILDING_PHOTO", buildingPhoto);
|
|
152
|
+
if (buildingPhotoFileStoreId) sessionStorage.setItem("EKYC_BUILDING_PHOTO_FILESTORE_ID", buildingPhotoFileStoreId);
|
|
153
|
+
sessionStorage.setItem("EKYC_CURRENT_STEP", "PROPERTY");
|
|
154
|
+
}, [ownerType, pidNumber, connectionCategory, connectionType, userType, noOfFloors, propertyDocument, propertyDocumentFileStoreId, buildingPhoto, buildingPhotoFileStoreId]);
|
|
155
|
+
|
|
156
|
+
const uploadFile = async (file, tenantId) => {
|
|
157
|
+
if (!file) return null;
|
|
158
|
+
const res = await Digit.UploadServices.Filestorage("EKYC", file, tenantId);
|
|
159
|
+
return res?.data?.files?.[0]?.fileStoreId || null;
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const dataUrlToFile = (dataUrl, filename) => {
|
|
163
|
+
const arr = dataUrl.split(",");
|
|
164
|
+
const mime = arr[0].match(/:(.*?);/)[1];
|
|
165
|
+
const bstr = atob(arr[1]);
|
|
166
|
+
let n = bstr.length;
|
|
167
|
+
const u8arr = new Uint8Array(n);
|
|
168
|
+
while (n--) u8arr[n] = bstr.charCodeAt(n);
|
|
169
|
+
return new File([u8arr], filename, { type: mime });
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
// useEffect hooks for automatic upload (WT-style)
|
|
173
|
+
useEffect(() => {
|
|
174
|
+
(async () => {
|
|
175
|
+
setError(null);
|
|
176
|
+
if (filepdf) {
|
|
177
|
+
if (filepdf.size >= 5000000) {
|
|
178
|
+
setError(t("EKYC_MAXIMUM_UPLOAD_SIZE_EXCEEDED"));
|
|
179
|
+
setToast({ type: "error", message: t("EKYC_MAXIMUM_UPLOAD_SIZE_EXCEEDED") });
|
|
180
|
+
} else {
|
|
181
|
+
try {
|
|
182
|
+
setToast({ type: "info", message: t("EKYC_UPLOADING") });
|
|
183
|
+
const fileStoreId = await uploadFile(filepdf, tenantId);
|
|
184
|
+
if (fileStoreId) {
|
|
185
|
+
setPropertyDocumentFileStoreId(fileStoreId);
|
|
186
|
+
setPropertyDocument(filepdf.name);
|
|
187
|
+
setToast({ type: "success", message: t("EKYC_UPLOAD_SUCCESS") });
|
|
188
|
+
} else {
|
|
189
|
+
setError(t("EKYC_FILE_UPLOAD_ERROR"));
|
|
190
|
+
setToast({ type: "error", message: t("EKYC_FILE_UPLOAD_ERROR") });
|
|
191
|
+
}
|
|
192
|
+
} catch (err) {
|
|
193
|
+
setError(t("EKYC_FILE_UPLOAD_ERROR"));
|
|
194
|
+
setToast({ type: "error", message: t("EKYC_FILE_UPLOAD_ERROR") });
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
})();
|
|
199
|
+
}, [filepdf]);
|
|
200
|
+
|
|
201
|
+
useEffect(() => {
|
|
202
|
+
(async () => {
|
|
203
|
+
setError(null);
|
|
204
|
+
if (filephoto) {
|
|
205
|
+
if (filephoto.size >= 2000000) {
|
|
206
|
+
setError(t("EKYC_MAXIMUM_UPLOAD_SIZE_EXCEEDED"));
|
|
207
|
+
setToast({ type: "error", message: t("EKYC_MAXIMUM_UPLOAD_SIZE_EXCEEDED") });
|
|
208
|
+
} else {
|
|
209
|
+
try {
|
|
210
|
+
setToast({ type: "info", message: t("EKYC_UPLOADING") });
|
|
211
|
+
const fileStoreId = await uploadFile(filephoto, tenantId);
|
|
212
|
+
if (fileStoreId) {
|
|
213
|
+
setBuildingPhotoFileStoreId(fileStoreId);
|
|
214
|
+
// Also store as dataURL for preview if needed, but for WT style we just need the fileStoreId
|
|
215
|
+
const reader = new FileReader();
|
|
216
|
+
reader.onloadend = () => setBuildingPhoto(reader.result);
|
|
217
|
+
reader.readAsDataURL(filephoto);
|
|
218
|
+
setToast({ type: "success", message: t("EKYC_UPLOAD_SUCCESS") });
|
|
219
|
+
} else {
|
|
220
|
+
setError(t("EKYC_FILE_UPLOAD_ERROR"));
|
|
221
|
+
setToast({ type: "error", message: t("EKYC_FILE_UPLOAD_ERROR") });
|
|
222
|
+
}
|
|
223
|
+
} catch (err) {
|
|
224
|
+
setError(t("EKYC_FILE_UPLOAD_ERROR"));
|
|
225
|
+
setToast({ type: "error", message: t("EKYC_FILE_UPLOAD_ERROR") });
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
})();
|
|
230
|
+
}, [filephoto]);
|
|
118
231
|
|
|
119
232
|
const fileRef = useRef(null);
|
|
120
233
|
const cameraRef = useRef(null);
|
|
@@ -125,24 +238,22 @@ const PropertyInfo = () => {
|
|
|
125
238
|
propertyDetails: {
|
|
126
239
|
ownerType, pidNumber, connectionType,
|
|
127
240
|
connectionCategory, userType, noOfFloors,
|
|
128
|
-
propertyDocument,
|
|
241
|
+
propertyDocument, propertyDocumentFileStoreId,
|
|
242
|
+
buildingPhoto, buildingPhotoFileStoreId,
|
|
129
243
|
},
|
|
244
|
+
initialData,
|
|
130
245
|
});
|
|
131
246
|
};
|
|
132
247
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
};
|
|
248
|
+
function selectpdf(e) {
|
|
249
|
+
setPropertyDocumentFileStoreId(null);
|
|
250
|
+
setFilepdf(e.target.files[0]);
|
|
251
|
+
}
|
|
138
252
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
reader.onloadend = () => setBuildingPhoto(reader.result);
|
|
144
|
-
reader.readAsDataURL(file);
|
|
145
|
-
};
|
|
253
|
+
function selectphoto(e) {
|
|
254
|
+
setBuildingPhotoFileStoreId(null);
|
|
255
|
+
setFilephoto(e.target.files[0]);
|
|
256
|
+
}
|
|
146
257
|
|
|
147
258
|
const connectionCategoryOptions =
|
|
148
259
|
dataV0?.["ws-services-calculation"]?.propertyTypeV2?.map((item) => ({
|
|
@@ -165,332 +276,301 @@ const PropertyInfo = () => {
|
|
|
165
276
|
})) || [];
|
|
166
277
|
|
|
167
278
|
return (
|
|
168
|
-
<div
|
|
169
|
-
<
|
|
279
|
+
<div class="ground-container employee-app-container form-container">
|
|
280
|
+
<div className="inbox-container">
|
|
281
|
+
<style>{`
|
|
170
282
|
@keyframes fadeSlideIn {
|
|
171
283
|
from { opacity: 0; transform: translateY(8px); }
|
|
172
284
|
to { opacity: 1; transform: translateY(0); }
|
|
173
285
|
}
|
|
174
286
|
`}</style>
|
|
175
287
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
288
|
+
{/* ── Sidebar ── */}
|
|
289
|
+
<div className="filters-container">
|
|
290
|
+
<Card style={{ display: "flex", alignItems: "center", padding: "12px 16px", marginBottom: "12px", borderRadius: "8px" }}>
|
|
291
|
+
<div style={{ color: "#185FA5", marginRight: "10px", display: "flex" }}>
|
|
292
|
+
<HomeIcon style={{ width: "20px", height: "20px" }} />
|
|
293
|
+
</div>
|
|
294
|
+
<div style={{ fontWeight: "600", fontSize: "15px", color: "#0B0C0C" }}>
|
|
295
|
+
{t("EKYC_PROCESS") || "eKYC Process"}
|
|
296
|
+
</div>
|
|
297
|
+
</Card>
|
|
298
|
+
|
|
299
|
+
<div style={{ background: "#fff", padding: "16px 14px", borderRadius: "8px", border: "1px solid #EAECF0" }}>
|
|
300
|
+
{[
|
|
301
|
+
{ label: t("EKYC_STEP_AADHAAR") || "Aadhaar", done: true, active: false },
|
|
302
|
+
{ label: t("EKYC_STEP_ADDRESS") || "Address", done: true, active: false },
|
|
303
|
+
{ label: t("EKYC_STEP_PROPERTY") || "Property", done: false, active: true },
|
|
304
|
+
{ label: t("EKYC_STEP_REVIEW") || "Review", done: false, active: false },
|
|
305
|
+
].map((step, i) => (
|
|
306
|
+
<div key={i} style={{ display: "flex", gap: "10px", alignItems: "flex-start", position: "relative", paddingBottom: i < 3 ? "18px" : 0 }}>
|
|
307
|
+
{i < 3 && (
|
|
308
|
+
<div style={{ position: "absolute", left: "10px", top: "22px", width: "1px", height: "calc(100% - 10px)", background: "#EAECF0" }} />
|
|
309
|
+
)}
|
|
310
|
+
<div style={{
|
|
311
|
+
width: "20px", height: "20px", borderRadius: "50%", flexShrink: 0, marginTop: "1px",
|
|
312
|
+
border: step.done ? "none" : step.active ? "1.5px solid #185FA5" : "1.5px solid #D0D5DD",
|
|
313
|
+
background: step.done ? "#0F6E56" : step.active ? "#E6F1FB" : "#fff",
|
|
314
|
+
display: "flex", alignItems: "center", justifyContent: "center",
|
|
315
|
+
fontSize: "10px", fontWeight: "500",
|
|
316
|
+
color: step.done ? "#fff" : step.active ? "#185FA5" : "#98A2B3",
|
|
317
|
+
}}>
|
|
318
|
+
{step.done ? <CheckIcon size={11} color="#fff" /> : i + 1}
|
|
319
|
+
</div>
|
|
320
|
+
<div style={{
|
|
321
|
+
fontSize: "12px", paddingTop: "2px",
|
|
322
|
+
color: step.done ? "#0F6E56" : step.active ? "#0B0C0C" : "#667085",
|
|
323
|
+
fontWeight: step.done || step.active ? "600" : "400",
|
|
324
|
+
}}>
|
|
325
|
+
{step.label}
|
|
326
|
+
</div>
|
|
207
327
|
</div>
|
|
328
|
+
))}
|
|
329
|
+
</div>
|
|
330
|
+
</div>
|
|
331
|
+
|
|
332
|
+
{/* ── Main Content ── */}
|
|
333
|
+
<div style={{ flex: 1, marginLeft: "16px" }}>
|
|
334
|
+
<Card>
|
|
335
|
+
{/* Header */}
|
|
336
|
+
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "20px" }}>
|
|
337
|
+
<CardHeader style={{ margin: 0, fontSize: "18px" }}>
|
|
338
|
+
{t("EKYC_PROPERTY_DETAILS_HEADER") || "Property Details"}
|
|
339
|
+
</CardHeader>
|
|
208
340
|
<div style={{
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
341
|
+
background: "#F9FAFB", border: "0.5px solid #EAECF0",
|
|
342
|
+
borderRadius: "20px", padding: "4px 14px",
|
|
343
|
+
fontSize: "12px", color: "#667085",
|
|
212
344
|
}}>
|
|
213
|
-
{
|
|
345
|
+
{t("EKYC_K_NUMBER") || "K Number"}:{" "}
|
|
346
|
+
<span style={{ color: "#0B0C0C", fontWeight: "600" }}>{kNumber}</span>
|
|
214
347
|
</div>
|
|
215
348
|
</div>
|
|
216
|
-
))}
|
|
217
|
-
</div>
|
|
218
|
-
</div>
|
|
219
349
|
|
|
220
|
-
|
|
221
|
-
<div style={{ flex: 1, marginLeft: "16px" }}>
|
|
222
|
-
<Card>
|
|
223
|
-
{/* Header */}
|
|
224
|
-
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "20px" }}>
|
|
225
|
-
<CardHeader style={{ margin: 0, fontSize: "18px" }}>
|
|
226
|
-
{t("EKYC_PROPERTY_DETAILS_HEADER") || "Property Details"}
|
|
227
|
-
</CardHeader>
|
|
228
|
-
<div style={{
|
|
229
|
-
background: "#F9FAFB", border: "0.5px solid #EAECF0",
|
|
230
|
-
borderRadius: "20px", padding: "4px 14px",
|
|
231
|
-
fontSize: "12px", color: "#667085",
|
|
232
|
-
}}>
|
|
233
|
-
{t("EKYC_K_NUMBER") || "K Number"}:{" "}
|
|
234
|
-
<span style={{ color: "#0B0C0C", fontWeight: "600" }}>{kNumber}</span>
|
|
235
|
-
</div>
|
|
236
|
-
</div>
|
|
237
|
-
|
|
238
|
-
<div style={{ animation: "fadeSlideIn 0.3s ease" }}>
|
|
350
|
+
<div style={{ animation: "fadeSlideIn 0.3s ease" }}>
|
|
239
351
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
352
|
+
{/* ── Property Details Section ── */}
|
|
353
|
+
<SectionHead
|
|
354
|
+
icon={<BriefcaseIcon size={16} />}
|
|
355
|
+
label={t("EKYC_PROPERTY_DETAILS") || "Property details"}
|
|
356
|
+
/>
|
|
245
357
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
358
|
+
{/* Owner / Tenant Toggle */}
|
|
359
|
+
<div style={{ marginBottom: "20px" }}>
|
|
360
|
+
<div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "8px" }}>
|
|
361
|
+
{t("EKYC_PROPERTY_OWNER") || "Property owner"}
|
|
362
|
+
</div>
|
|
363
|
+
<div style={{ display: "flex", backgroundColor: "#F2F4F7", padding: "4px", borderRadius: "10px", gap: "4px" }}>
|
|
364
|
+
{["OWNER", "TENANT"].map((type) => (
|
|
365
|
+
<button
|
|
366
|
+
key={type}
|
|
367
|
+
onClick={() => setOwnerType(type)}
|
|
368
|
+
style={{
|
|
369
|
+
flex: 1, padding: "9px 12px", borderRadius: "7px", border: "none", cursor: "pointer",
|
|
370
|
+
fontSize: "13px", fontWeight: "600", transition: "all 0.15s",
|
|
371
|
+
background: ownerType === type ? "#185FA5" : "transparent",
|
|
372
|
+
color: ownerType === type ? "#fff" : "#667085",
|
|
373
|
+
}}
|
|
374
|
+
>
|
|
375
|
+
{t(`EKYC_${type}`) || (type === "OWNER" ? "Owner" : "Tenant")}
|
|
376
|
+
</button>
|
|
377
|
+
))}
|
|
378
|
+
</div>
|
|
266
379
|
</div>
|
|
267
|
-
</div>
|
|
268
380
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
381
|
+
{/* PID Number */}
|
|
382
|
+
<div style={{ marginBottom: "20px" }}>
|
|
383
|
+
<div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
|
|
384
|
+
{t("EKYC_PID_NUMBER") || "PID number"}{" "}
|
|
385
|
+
<span style={{ fontStyle: "italic", fontWeight: "400", textTransform: "none", color: "#98A2B3" }}>
|
|
386
|
+
— {t("EKYC_OPTIONAL") || "optional"}
|
|
387
|
+
</span>
|
|
388
|
+
</div>
|
|
389
|
+
<IconInput
|
|
390
|
+
icon={<PidIcon size={15} />}
|
|
391
|
+
value={pidNumber}
|
|
392
|
+
onChange={(e) => setPidNumber(e.target.value)}
|
|
393
|
+
placeholder={t("EKYC_ENTER_PID_NUMBER") || "Enter PID number"}
|
|
394
|
+
/>
|
|
276
395
|
</div>
|
|
277
|
-
<IconInput
|
|
278
|
-
icon={<PidIcon size={15} />}
|
|
279
|
-
value={pidNumber}
|
|
280
|
-
onChange={(e) => setPidNumber(e.target.value)}
|
|
281
|
-
placeholder={t("EKYC_ENTER_PID_NUMBER") || "Enter PID number"}
|
|
282
|
-
/>
|
|
283
|
-
</div>
|
|
284
396
|
|
|
285
|
-
|
|
397
|
+
<hr style={{ margin: "24px 0", border: 0, borderTop: "1px solid #EAECF0" }} />
|
|
286
398
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
399
|
+
{/* ── Building Info Section ── */}
|
|
400
|
+
<SectionHead
|
|
401
|
+
icon={<BuildingIcon size={16} />}
|
|
402
|
+
label={t("EKYC_BUILDING_INFO") || "Building info"}
|
|
403
|
+
/>
|
|
292
404
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
405
|
+
{/* Dropdowns grid */}
|
|
406
|
+
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "14px", marginBottom: "14px" }}>
|
|
407
|
+
<div>
|
|
408
|
+
<div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
|
|
409
|
+
{t("EKYC_TYPE_OF_CONNECTION") || "Type of connection"}
|
|
410
|
+
</div>
|
|
411
|
+
<Dropdown
|
|
412
|
+
selected={connectionCategory}
|
|
413
|
+
select={setConnectionCategory}
|
|
414
|
+
option={connectionCategoryOptions}
|
|
415
|
+
optionKey="label"
|
|
416
|
+
t={t}
|
|
417
|
+
placeholder={t("EKYC_SELECT") || "Select"}
|
|
418
|
+
/>
|
|
298
419
|
</div>
|
|
299
|
-
<
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
420
|
+
<div>
|
|
421
|
+
<div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
|
|
422
|
+
{t("EKYC_CONNECTION_CATEGORY") || "Connection category"}
|
|
423
|
+
</div>
|
|
424
|
+
<Dropdown
|
|
425
|
+
selected={connectionType}
|
|
426
|
+
select={setConnectionType}
|
|
427
|
+
option={connectionTypeOptions}
|
|
428
|
+
optionKey="label"
|
|
429
|
+
t={t}
|
|
430
|
+
placeholder={t("EKYC_SELECT") || "Select"}
|
|
431
|
+
/>
|
|
311
432
|
</div>
|
|
312
|
-
<Dropdown
|
|
313
|
-
selected={connectionType}
|
|
314
|
-
select={setConnectionType}
|
|
315
|
-
option={connectionTypeOptions}
|
|
316
|
-
optionKey="label"
|
|
317
|
-
t={t}
|
|
318
|
-
placeholder={t("EKYC_SELECT") || "Select"}
|
|
319
|
-
/>
|
|
320
433
|
</div>
|
|
321
|
-
</div>
|
|
322
434
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
435
|
+
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "14px", marginBottom: "24px" }}>
|
|
436
|
+
<div>
|
|
437
|
+
<div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
|
|
438
|
+
{t("EKYC_USER_TYPE") || "User type"}
|
|
439
|
+
</div>
|
|
440
|
+
<Dropdown
|
|
441
|
+
selected={userType}
|
|
442
|
+
select={setUserType}
|
|
443
|
+
option={userTypeOptions}
|
|
444
|
+
optionKey="label"
|
|
445
|
+
t={t}
|
|
446
|
+
placeholder={t("EKYC_SELECT") || "Select"}
|
|
447
|
+
/>
|
|
327
448
|
</div>
|
|
328
|
-
<
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
449
|
+
<div>
|
|
450
|
+
<div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
|
|
451
|
+
{t("EKYC_NO_OF_FLOORS") || "No. of floors"}
|
|
452
|
+
</div>
|
|
453
|
+
<Dropdown
|
|
454
|
+
selected={noOfFloors}
|
|
455
|
+
select={setNoOfFloors}
|
|
456
|
+
option={floorOptions}
|
|
457
|
+
optionKey="label"
|
|
458
|
+
t={t}
|
|
459
|
+
placeholder={t("EKYC_SELECT") || "Select"}
|
|
460
|
+
/>
|
|
340
461
|
</div>
|
|
341
|
-
<Dropdown
|
|
342
|
-
selected={noOfFloors}
|
|
343
|
-
select={setNoOfFloors}
|
|
344
|
-
option={floorOptions}
|
|
345
|
-
optionKey="label"
|
|
346
|
-
t={t}
|
|
347
|
-
placeholder={t("EKYC_SELECT") || "Select"}
|
|
348
|
-
/>
|
|
349
462
|
</div>
|
|
350
|
-
</div>
|
|
351
463
|
|
|
352
|
-
|
|
464
|
+
<hr style={{ margin: "24px 0", border: 0, borderTop: "1px solid #EAECF0" }} />
|
|
353
465
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
466
|
+
{/* ── Documents & Photo Section ── */}
|
|
467
|
+
<SectionHead
|
|
468
|
+
icon={<DocumentIcon size={16} />}
|
|
469
|
+
label={t("EKYC_DOCUMENTS_PHOTO") || "Documents & photo"}
|
|
470
|
+
/>
|
|
359
471
|
|
|
360
|
-
|
|
472
|
+
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "14px", marginBottom: "20px" }}>
|
|
361
473
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
474
|
+
{/* PDF Upload */}
|
|
475
|
+
<div>
|
|
476
|
+
<div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "8px" }}>
|
|
477
|
+
{t("EKYC_UPLOAD_PROPERTY_DOC") || "Upload property document"}
|
|
478
|
+
</div>
|
|
479
|
+
<UploadFile
|
|
480
|
+
id={"ekyc-property-doc"}
|
|
481
|
+
extraStyleName={"propertyCreate"}
|
|
482
|
+
accept=".pdf"
|
|
483
|
+
onUpload={selectpdf}
|
|
484
|
+
onDelete={() => {
|
|
485
|
+
setPropertyDocumentFileStoreId(null);
|
|
486
|
+
setPropertyDocument(null);
|
|
487
|
+
setFilepdf(null);
|
|
488
|
+
}}
|
|
489
|
+
message={propertyDocumentFileStoreId ? `1 ${t(`EKYC_ACTION_FILEUPLOADED`)}` : t(`EKYC_ACTION_NO_FILEUPLOADED`)}
|
|
490
|
+
error={error}
|
|
491
|
+
disabled={!pidNumber}
|
|
492
|
+
/>
|
|
493
|
+
{!pidNumber && (
|
|
494
|
+
<div style={{ fontSize: "11px", color: "#D92D20", marginTop: "4px" }}>
|
|
495
|
+
{t("EKYC_ENTER_PID_FIRST_CTA") || "Enter PID to upload"}
|
|
496
|
+
</div>
|
|
497
|
+
)}
|
|
366
498
|
</div>
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
style={{
|
|
373
|
-
border: "1.5px dashed #B5D4F4", borderRadius: "10px",
|
|
374
|
-
padding: "28px 20px", textAlign: "center", cursor: "pointer",
|
|
375
|
-
backgroundColor: "#E6F1FB", minHeight: "160px",
|
|
376
|
-
display: "flex", flexDirection: "column",
|
|
377
|
-
alignItems: "center", justifyContent: "center", gap: "10px",
|
|
378
|
-
transition: "border-color 0.15s",
|
|
379
|
-
}}
|
|
380
|
-
>
|
|
381
|
-
<div style={{ background: "#fff", padding: "10px", borderRadius: "10px", display: "flex" }}>
|
|
382
|
-
<svg width="32" height="32" viewBox="0 0 24 24" fill="#185FA5">
|
|
383
|
-
<path d="M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zm-1 7V3.5L18.5 9H13z" />
|
|
384
|
-
<path d="M12 18v-4M12 14l-2 2M12 14l2 2" stroke="#fff" strokeWidth="1.5" strokeLinecap="round" />
|
|
385
|
-
</svg>
|
|
499
|
+
|
|
500
|
+
{/* Building Photo Upload */}
|
|
501
|
+
<div>
|
|
502
|
+
<div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "8px" }}>
|
|
503
|
+
{t("EKYC_CAPTURE_BUILDING_IMAGE") || "Capture building image"}
|
|
386
504
|
</div>
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
505
|
+
<UploadFile
|
|
506
|
+
id={"ekyc-building-photo"}
|
|
507
|
+
extraStyleName={"propertyCreate"}
|
|
508
|
+
accept=".jpg,.png,.jpeg"
|
|
509
|
+
onUpload={selectphoto}
|
|
510
|
+
onDelete={() => {
|
|
511
|
+
setBuildingPhotoFileStoreId(null);
|
|
512
|
+
setBuildingPhoto(null);
|
|
513
|
+
setFilephoto(null);
|
|
514
|
+
}}
|
|
515
|
+
message={buildingPhotoFileStoreId ? `1 ${t(`EKYC_ACTION_FILEUPLOADED`)}` : t(`EKYC_ACTION_NO_FILEUPLOADED`)}
|
|
516
|
+
error={error}
|
|
517
|
+
/>
|
|
518
|
+
{buildingPhoto && (
|
|
519
|
+
<div style={{ marginTop: "10px", borderRadius: "8px", overflow: "hidden", border: "1px solid #EAECF0" }}>
|
|
520
|
+
<img src={buildingPhoto} alt="Building Preview" style={{ width: "100%", maxHeight: "150px", objectFit: "cover" }} />
|
|
390
521
|
</div>
|
|
391
|
-
) : (
|
|
392
|
-
<>
|
|
393
|
-
<div style={{ fontSize: "13px", fontWeight: "600", color: "#185FA5" }}>
|
|
394
|
-
{t("EKYC_UPLOAD_PROPERTY_DOC_CTA") || "Tap to upload"}
|
|
395
|
-
</div>
|
|
396
|
-
<div style={{ fontSize: "12px", color: "#378ADD" }}>PDF only</div>
|
|
397
|
-
</>
|
|
398
522
|
)}
|
|
399
523
|
</div>
|
|
400
524
|
</div>
|
|
401
525
|
|
|
402
|
-
{/*
|
|
403
|
-
<div
|
|
404
|
-
|
|
405
|
-
|
|
526
|
+
{/* Info Banner */}
|
|
527
|
+
<div style={{
|
|
528
|
+
backgroundColor: "#E6F1FB", border: "0.5px solid #B5D4F4",
|
|
529
|
+
borderRadius: "8px", padding: "12px 14px",
|
|
530
|
+
display: "flex", alignItems: "flex-start", gap: "10px", marginBottom: "4px",
|
|
531
|
+
}}>
|
|
532
|
+
<div style={{ flexShrink: 0, marginTop: "1px" }}>
|
|
533
|
+
<InfoBannerIcon fill="#185FA5" />
|
|
406
534
|
</div>
|
|
407
|
-
<
|
|
408
|
-
|
|
409
|
-
onClick={!buildingPhoto ? () => cameraRef.current.click() : undefined}
|
|
410
|
-
onMouseOver={(e) => { if (!buildingPhoto) e.currentTarget.style.borderColor = "#185FA5"; }}
|
|
411
|
-
onMouseOut={(e) => { if (!buildingPhoto) e.currentTarget.style.borderColor = "#D0D5DD"; }}
|
|
412
|
-
style={{
|
|
413
|
-
border: "1.5px dashed #D0D5DD", borderRadius: "10px",
|
|
414
|
-
minHeight: "160px", display: "flex", flexDirection: "column",
|
|
415
|
-
alignItems: "center", justifyContent: "center",
|
|
416
|
-
backgroundColor: "#F9FAFB",
|
|
417
|
-
cursor: buildingPhoto ? "default" : "pointer",
|
|
418
|
-
overflow: "hidden", transition: "border-color 0.15s",
|
|
419
|
-
position: "relative",
|
|
420
|
-
padding: buildingPhoto ? "0" : "28px 20px",
|
|
421
|
-
}}
|
|
422
|
-
>
|
|
423
|
-
{!buildingPhoto ? (
|
|
424
|
-
<>
|
|
425
|
-
<div style={{ background: "#E6F1FB", width: "52px", height: "52px", borderRadius: "50%", display: "flex", alignItems: "center", justifyContent: "center", marginBottom: "10px" }}>
|
|
426
|
-
<CameraIcon size={26} />
|
|
427
|
-
</div>
|
|
428
|
-
<div style={{ fontSize: "13px", fontWeight: "600", color: "#101828" }}>
|
|
429
|
-
{t("EKYC_TAP_TO_CAPTURE") || "Tap to capture"}
|
|
430
|
-
</div>
|
|
431
|
-
<div style={{ fontSize: "12px", color: "#667085", marginTop: "2px" }}>
|
|
432
|
-
{t("EKYC_BUILDING_PHOTO") || "Building photo with GPS"}
|
|
433
|
-
</div>
|
|
434
|
-
</>
|
|
435
|
-
) : (
|
|
436
|
-
<>
|
|
437
|
-
<img src={buildingPhoto} alt="Building" style={{ width: "100%", maxHeight: "200px", objectFit: "cover", display: "block" }} />
|
|
438
|
-
<button
|
|
439
|
-
onClick={(e) => { e.stopPropagation(); setBuildingPhoto(null); if (cameraRef.current) cameraRef.current.value = ""; }}
|
|
440
|
-
style={{
|
|
441
|
-
position: "absolute", top: "8px", right: "8px",
|
|
442
|
-
background: "#fff", border: "0.5px solid #EAECF0",
|
|
443
|
-
borderRadius: "7px", padding: "5px 10px",
|
|
444
|
-
display: "flex", alignItems: "center", gap: "5px",
|
|
445
|
-
cursor: "pointer", fontSize: "12px", color: "#D92D20", fontWeight: "500",
|
|
446
|
-
}}
|
|
447
|
-
>
|
|
448
|
-
<TrashIcon size={13} /> {t("EKYC_REMOVE") || "Remove"}
|
|
449
|
-
</button>
|
|
450
|
-
</>
|
|
451
|
-
)}
|
|
535
|
+
<div style={{ fontSize: "13px", color: "#185FA5", lineHeight: "1.5" }}>
|
|
536
|
+
{t("EKYC_TENANT_INFO_NOTICE") || "This section is enabled only if the user is not the owner. Tenant details will be required if tenant is selected."}
|
|
452
537
|
</div>
|
|
453
538
|
</div>
|
|
539
|
+
|
|
540
|
+
</div>
|
|
541
|
+
|
|
542
|
+
{/* Submit (Non-sticky, at form end) */}
|
|
543
|
+
<div style={{ marginTop: "24px" }}>
|
|
544
|
+
<SubmitBar
|
|
545
|
+
label={t("EKYC_SAVE_AND_CONTINUE") || "Save & Continue"}
|
|
546
|
+
onSubmit={handleSaveAndContinue}
|
|
547
|
+
/>
|
|
454
548
|
</div>
|
|
455
549
|
|
|
456
|
-
{/*
|
|
550
|
+
{/* Secure notice */}
|
|
457
551
|
<div style={{
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
552
|
+
display: "flex", alignItems: "center", justifyContent: "center",
|
|
553
|
+
gap: "5px", marginTop: "16px",
|
|
554
|
+
fontSize: "11px", color: "#98A2B3",
|
|
461
555
|
}}>
|
|
462
|
-
<
|
|
463
|
-
<
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
</div>
|
|
556
|
+
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
557
|
+
<rect x="3" y="11" width="18" height="11" rx="2" />
|
|
558
|
+
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
|
|
559
|
+
</svg>
|
|
560
|
+
{t("EKYC_SECURE_DATA_NOTICE") || "Your data is encrypted and secure"}
|
|
468
561
|
</div>
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
{/* Submit (Non-sticky, at form end) */}
|
|
473
|
-
<div style={{ marginTop: "24px" }}>
|
|
474
|
-
<SubmitBar
|
|
475
|
-
label={t("EKYC_SAVE_AND_CONTINUE") || "Save & Continue"}
|
|
476
|
-
onSubmit={handleSaveAndContinue}
|
|
477
|
-
/>
|
|
478
|
-
</div>
|
|
479
|
-
|
|
480
|
-
{/* Secure notice */}
|
|
481
|
-
<div style={{
|
|
482
|
-
display: "flex", alignItems: "center", justifyContent: "center",
|
|
483
|
-
gap: "5px", marginTop: "16px",
|
|
484
|
-
fontSize: "11px", color: "#98A2B3",
|
|
485
|
-
}}>
|
|
486
|
-
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
487
|
-
<rect x="3" y="11" width="18" height="11" rx="2" />
|
|
488
|
-
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
|
|
489
|
-
</svg>
|
|
490
|
-
{t("EKYC_SECURE_DATA_NOTICE") || "Your data is encrypted and secure"}
|
|
491
|
-
</div>
|
|
492
|
-
</Card>
|
|
562
|
+
</Card>
|
|
563
|
+
</div>
|
|
493
564
|
</div>
|
|
565
|
+
{toast && (
|
|
566
|
+
<Toast
|
|
567
|
+
label={toast.message}
|
|
568
|
+
error={toast.type === "error"}
|
|
569
|
+
info={toast.type === "info"}
|
|
570
|
+
success={toast.type === "success"}
|
|
571
|
+
onClose={() => setToast(null)}
|
|
572
|
+
/>
|
|
573
|
+
)}
|
|
494
574
|
</div>
|
|
495
575
|
);
|
|
496
576
|
};
|