@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.
@@ -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 || { kNumber: "EKYC-1234567890" };
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,42 +114,146 @@ 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(null);
113
- const [connectionType, setConnectionType] = useState(null);
114
- const [userType, setUserType] = useState(null);
115
- const [noOfFloors, setNoOfFloors] = useState(null);
116
- const [propertyDocument, setPropertyDocument] = useState(null);
117
- const [buildingPhoto, setBuildingPhoto] = useState(null);
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);
121
234
 
122
235
  const handleSaveAndContinue = () => {
123
- history.push("/digit-ui/employee/ekyc/review", {
236
+ history.push("/digit-ui/employee/ekyc/meter-details", {
124
237
  ...flowState,
125
238
  propertyDetails: {
126
239
  ownerType, pidNumber, connectionType,
127
240
  connectionCategory, userType, noOfFloors,
128
- propertyDocument, buildingPhoto,
241
+ propertyDocument, propertyDocumentFileStoreId,
242
+ buildingPhoto, buildingPhotoFileStoreId,
129
243
  },
244
+ initialData,
130
245
  });
131
246
  };
132
247
 
133
- const handleFileUpload = (e) => {
134
- const file = e.target.files[0];
135
- if (!file) return;
136
- setPropertyDocument(file);
137
- };
248
+ function selectpdf(e) {
249
+ setPropertyDocumentFileStoreId(null);
250
+ setFilepdf(e.target.files[0]);
251
+ }
138
252
 
139
- const handlePhotoCapture = (e) => {
140
- const file = e.target.files[0];
141
- if (!file) return;
142
- const reader = new FileReader();
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,350 +276,303 @@ const PropertyInfo = () => {
165
276
  })) || [];
166
277
 
167
278
  return (
168
- <div className="inbox-container">
169
- <style>{`
279
+ <>
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
- {/* ── Sidebar ── */}
177
- <div className="filters-container">
178
- <Card style={{ display: "flex", alignItems: "center", padding: "12px 16px", marginBottom: "12px", borderRadius: "8px" }}>
179
- <div style={{ color: "#185FA5", marginRight: "10px", display: "flex" }}>
180
- <HomeIcon style={{ width: "20px", height: "20px" }} />
181
- </div>
182
- <div style={{ fontWeight: "600", fontSize: "15px", color: "#0B0C0C" }}>
183
- {t("EKYC_PROCESS") || "eKYC Process"}
184
- </div>
185
- </Card>
186
-
187
- <div style={{ background: "#fff", padding: "16px 14px", borderRadius: "8px", border: "1px solid #EAECF0" }}>
188
- {[
189
- { label: t("EKYC_STEP_AADHAAR") || "Aadhaar", done: true, active: false },
190
- { label: t("EKYC_STEP_ADDRESS") || "Address", done: true, active: false },
191
- { label: t("EKYC_STEP_PROPERTY") || "Property", done: false, active: true },
192
- { label: t("EKYC_STEP_REVIEW") || "Review", done: false, active: false },
193
- ].map((step, i) => (
194
- <div key={i} style={{ display: "flex", gap: "10px", alignItems: "flex-start", position: "relative", paddingBottom: i < 3 ? "18px" : 0 }}>
195
- {i < 3 && (
196
- <div style={{ position: "absolute", left: "10px", top: "22px", width: "1px", height: "calc(100% - 10px)", background: "#EAECF0" }} />
197
- )}
198
- <div style={{
199
- width: "20px", height: "20px", borderRadius: "50%", flexShrink: 0, marginTop: "1px",
200
- border: step.done ? "none" : step.active ? "1.5px solid #185FA5" : "1.5px solid #D0D5DD",
201
- background: step.done ? "#0F6E56" : step.active ? "#E6F1FB" : "#fff",
202
- display: "flex", alignItems: "center", justifyContent: "center",
203
- fontSize: "10px", fontWeight: "500",
204
- color: step.done ? "#fff" : step.active ? "#185FA5" : "#98A2B3",
205
- }}>
206
- {step.done ? <CheckIcon size={11} color="#fff" /> : i + 1}
207
- </div>
208
- <div style={{
209
- fontSize: "12px", paddingTop: "2px",
210
- color: step.done ? "#0F6E56" : step.active ? "#0B0C0C" : "#667085",
211
- fontWeight: step.done || step.active ? "600" : "400",
212
- }}>
213
- {step.label}
214
- </div>
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" }} />
215
293
  </div>
216
- ))}
217
- </div>
218
- </div>
219
-
220
- {/* ── Main Content ── */}
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>
294
+ <div style={{ fontWeight: "600", fontSize: "15px", color: "#0B0C0C" }}>
295
+ {t("EKYC_PROCESS") || "eKYC Process"}
235
296
  </div>
236
- </div>
237
-
238
- <div style={{ animation: "fadeSlideIn 0.3s ease" }}>
239
-
240
- {/* ── Property Details Section ── */}
241
- <SectionHead
242
- icon={<BriefcaseIcon size={16} />}
243
- label={t("EKYC_PROPERTY_DETAILS") || "Property details"}
244
- />
245
-
246
- {/* Owner / Tenant Toggle */}
247
- <div style={{ marginBottom: "20px" }}>
248
- <div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "8px" }}>
249
- {t("EKYC_PROPERTY_OWNER") || "Property owner"}
250
- </div>
251
- <div style={{ display: "flex", backgroundColor: "#F2F4F7", padding: "4px", borderRadius: "10px", gap: "4px" }}>
252
- {["OWNER", "TENANT"].map((type) => (
253
- <button
254
- key={type}
255
- onClick={() => setOwnerType(type)}
256
- style={{
257
- flex: 1, padding: "9px 12px", borderRadius: "7px", border: "none", cursor: "pointer",
258
- fontSize: "13px", fontWeight: "600", transition: "all 0.15s",
259
- background: ownerType === type ? "#185FA5" : "transparent",
260
- color: ownerType === type ? "#fff" : "#667085",
261
- }}
262
- >
263
- {t(`EKYC_${type}`) || (type === "OWNER" ? "Owner" : "Tenant")}
264
- </button>
265
- ))}
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_METER") || "Meter", done: false, active: false },
305
+ { label: t("EKYC_STEP_REVIEW") || "Review", done: false, active: false },
306
+ ].map((step, i) => (
307
+ <div key={i} style={{ display: "flex", gap: "10px", alignItems: "flex-start", position: "relative", paddingBottom: i < 4 ? "18px" : 0 }}>
308
+ {i < 4 && (
309
+ <div style={{ position: "absolute", left: "10px", top: "22px", width: "1px", height: "calc(100% - 10px)", background: "#EAECF0" }} />
310
+ )}
311
+ <div style={{
312
+ width: "20px", height: "20px", borderRadius: "50%", flexShrink: 0, marginTop: "1px",
313
+ border: step.done ? "none" : step.active ? "1.5px solid #185FA5" : "1.5px solid #D0D5DD",
314
+ background: step.done ? "#0F6E56" : step.active ? "#E6F1FB" : "#fff",
315
+ display: "flex", alignItems: "center", justifyContent: "center",
316
+ fontSize: "10px", fontWeight: "500",
317
+ color: step.done ? "#fff" : step.active ? "#185FA5" : "#98A2B3",
318
+ }}>
319
+ {step.done ? <CheckIcon size={11} color="#fff" /> : i + 1}
320
+ </div>
321
+ <div style={{
322
+ fontSize: "12px", paddingTop: "2px",
323
+ color: step.done ? "#0F6E56" : step.active ? "#0B0C0C" : "#667085",
324
+ fontWeight: step.done || step.active ? "600" : "400",
325
+ }}>
326
+ {step.label}
327
+ </div>
266
328
  </div>
267
- </div>
329
+ ))}
330
+ </div>
331
+ </div>
268
332
 
269
- {/* PID Number */}
270
- <div style={{ marginBottom: "20px" }}>
271
- <div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
272
- {t("EKYC_PID_NUMBER") || "PID number"}{" "}
273
- <span style={{ fontStyle: "italic", fontWeight: "400", textTransform: "none", color: "#98A2B3" }}>
274
- {t("EKYC_OPTIONAL") || "optional"}
275
- </span>
333
+ {/* ── Main Content ── */}
334
+ <div style={{ flex: 1, marginLeft: "16px" }}>
335
+ <Card>
336
+ {/* Header */}
337
+ <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "20px" }}>
338
+ <CardHeader style={{ margin: 0, fontSize: "18px" }}>
339
+ {t("EKYC_PROPERTY_DETAILS_HEADER") || "Property Details"}
340
+ </CardHeader>
341
+ <div style={{
342
+ background: "#F9FAFB", border: "0.5px solid #EAECF0",
343
+ borderRadius: "20px", padding: "4px 14px",
344
+ fontSize: "12px", color: "#667085",
345
+ }}>
346
+ {t("EKYC_K_NUMBER") || "K Number"}:{" "}
347
+ <span style={{ color: "#0B0C0C", fontWeight: "600" }}>{kNumber}</span>
276
348
  </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
349
  </div>
284
350
 
285
- <hr style={{ margin: "24px 0", border: 0, borderTop: "1px solid #EAECF0" }} />
351
+ <div style={{ animation: "fadeSlideIn 0.3s ease" }}>
286
352
 
287
- {/* ── Building Info Section ── */}
288
- <SectionHead
289
- icon={<BuildingIcon size={16} />}
290
- label={t("EKYC_BUILDING_INFO") || "Building info"}
291
- />
353
+ {/* ── Property Details Section ── */}
354
+ <SectionHead
355
+ icon={<BriefcaseIcon size={16} />}
356
+ label={t("EKYC_PROPERTY_DETAILS") || "Property details"}
357
+ />
292
358
 
293
- {/* Dropdowns grid */}
294
- <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "14px", marginBottom: "14px" }}>
295
- <div>
296
- <div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
297
- {t("EKYC_TYPE_OF_CONNECTION") || "Type of connection"}
359
+ {/* Owner / Tenant Toggle */}
360
+ <div style={{ marginBottom: "20px" }}>
361
+ <div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "8px" }}>
362
+ {t("EKYC_PROPERTY_OWNER") || "Property owner"}
298
363
  </div>
299
- <Dropdown
300
- selected={connectionCategory}
301
- select={setConnectionCategory}
302
- option={connectionCategoryOptions}
303
- optionKey="label"
304
- t={t}
305
- placeholder={t("EKYC_SELECT") || "Select"}
306
- />
307
- </div>
308
- <div>
309
- <div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
310
- {t("EKYC_CONNECTION_CATEGORY") || "Connection category"}
364
+ <div style={{ display: "flex", backgroundColor: "#F2F4F7", padding: "4px", borderRadius: "10px", gap: "4px" }}>
365
+ {["OWNER", "TENANT"].map((type) => (
366
+ <button
367
+ key={type}
368
+ onClick={() => setOwnerType(type)}
369
+ style={{
370
+ flex: 1, padding: "9px 12px", borderRadius: "7px", border: "none", cursor: "pointer",
371
+ fontSize: "13px", fontWeight: "600", transition: "all 0.15s",
372
+ background: ownerType === type ? "#185FA5" : "transparent",
373
+ color: ownerType === type ? "#fff" : "#667085",
374
+ }}
375
+ >
376
+ {t(`EKYC_${type}`) || (type === "OWNER" ? "Owner" : "Tenant")}
377
+ </button>
378
+ ))}
311
379
  </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
380
  </div>
321
- </div>
322
381
 
323
- <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "14px", marginBottom: "24px" }}>
324
- <div>
382
+ {/* PID Number */}
383
+ <div style={{ marginBottom: "20px" }}>
325
384
  <div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
326
- {t("EKYC_USER_TYPE") || "User type"}
385
+ {t("EKYC_PID_NUMBER") || "PID number"}{" "}
386
+ <span style={{ fontStyle: "italic", fontWeight: "400", textTransform: "none", color: "#98A2B3" }}>
387
+ — {t("EKYC_OPTIONAL") || "optional"}
388
+ </span>
327
389
  </div>
328
- <Dropdown
329
- selected={userType}
330
- select={setUserType}
331
- option={userTypeOptions}
332
- optionKey="label"
333
- t={t}
334
- placeholder={t("EKYC_SELECT") || "Select"}
390
+ <IconInput
391
+ icon={<PidIcon size={15} />}
392
+ value={pidNumber}
393
+ onChange={(e) => setPidNumber(e.target.value)}
394
+ placeholder={t("EKYC_ENTER_PID_NUMBER") || "Enter PID number"}
335
395
  />
336
396
  </div>
337
- <div>
338
- <div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
339
- {t("EKYC_NO_OF_FLOORS") || "No. of floors"}
397
+
398
+ <hr style={{ margin: "24px 0", border: 0, borderTop: "1px solid #EAECF0" }} />
399
+
400
+ {/* ── Building Info Section ── */}
401
+ <SectionHead
402
+ icon={<BuildingIcon size={16} />}
403
+ label={t("EKYC_BUILDING_INFO") || "Building info"}
404
+ />
405
+
406
+ {/* Dropdowns grid */}
407
+ <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "14px", marginBottom: "14px" }}>
408
+ {/* <div>
409
+ <div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
410
+ {t("EKYC_TYPE_OF_CONNECTION") || "Type of connection"}
411
+ </div>
412
+ <Dropdown
413
+ selected={connectionCategory}
414
+ select={setConnectionCategory}
415
+ option={connectionCategoryOptions}
416
+ optionKey="label"
417
+ t={t}
418
+ placeholder={t("EKYC_SELECT") || "Select"}
419
+ />
420
+ </div> */}
421
+ {/* <div>
422
+ <div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
423
+ {t("EKYC_CONNECTION_CATEGORY") || "Connection category"}
424
+ </div>
425
+ <Dropdown
426
+ selected={connectionType}
427
+ select={setConnectionType}
428
+ option={connectionTypeOptions}
429
+ optionKey="label"
430
+ t={t}
431
+ placeholder={t("EKYC_SELECT") || "Select"}
432
+ />
433
+ </div> */}
434
+ </div>
435
+
436
+ <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "14px", marginBottom: "24px" }}>
437
+ <div>
438
+ <div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
439
+ {t("EKYC_USER_TYPE") || "User type"}
440
+ </div>
441
+ <Dropdown
442
+ selected={userType}
443
+ select={setUserType}
444
+ option={userTypeOptions}
445
+ optionKey="label"
446
+ t={t}
447
+ placeholder={t("EKYC_SELECT") || "Select"}
448
+ />
449
+ </div>
450
+ <div>
451
+ <div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
452
+ {t("EKYC_NO_OF_FLOORS") || "No. of floors"}
453
+ </div>
454
+ <Dropdown
455
+ selected={noOfFloors}
456
+ select={setNoOfFloors}
457
+ option={floorOptions}
458
+ optionKey="label"
459
+ t={t}
460
+ placeholder={t("EKYC_SELECT") || "Select"}
461
+ />
340
462
  </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
463
  </div>
350
- </div>
351
464
 
352
- <hr style={{ margin: "24px 0", border: 0, borderTop: "1px solid #EAECF0" }} />
465
+ <hr style={{ margin: "24px 0", border: 0, borderTop: "1px solid #EAECF0" }} />
353
466
 
354
- {/* ── Documents & Photo Section ── */}
355
- <SectionHead
356
- icon={<DocumentIcon size={16} />}
357
- label={t("EKYC_DOCUMENTS_PHOTO") || "Documents & photo"}
358
- />
467
+ {/* ── Documents & Photo Section ── */}
468
+ <SectionHead
469
+ icon={<DocumentIcon size={16} />}
470
+ label={t("EKYC_DOCUMENTS_PHOTO") || "Documents & photo"}
471
+ />
359
472
 
360
- <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "14px", marginBottom: "20px" }}>
473
+ <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "14px", marginBottom: "20px" }}>
361
474
 
362
- {/* PDF Upload */}
363
- <div>
364
- <div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "8px" }}>
365
- {t("EKYC_UPLOAD_PROPERTY_DOC") || "Upload property document"}
475
+ {/* PDF Upload */}
476
+ <div>
477
+ <div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "8px" }}>
478
+ {t("EKYC_UPLOAD_PROPERTY_DOC") || "Upload property document"}
479
+ </div>
480
+ <UploadFile
481
+ id={"ekyc-property-doc"}
482
+ extraStyleName={"propertyCreate"}
483
+ accept=".pdf"
484
+ onUpload={selectpdf}
485
+ onDelete={() => {
486
+ setPropertyDocumentFileStoreId(null);
487
+ setPropertyDocument(null);
488
+ setFilepdf(null);
489
+ }}
490
+ message={propertyDocumentFileStoreId ? `1 ${t(`EKYC_ACTION_FILEUPLOADED`)}` : t(`EKYC_ACTION_NO_FILEUPLOADED`)}
491
+ error={error}
492
+ disabled={!pidNumber}
493
+ />
494
+ {!pidNumber && (
495
+ <div style={{ fontSize: "11px", color: "#D92D20", marginTop: "4px" }}>
496
+ {t("EKYC_ENTER_PID_FIRST_CTA") || "Enter PID to upload"}
497
+ </div>
498
+ )}
366
499
  </div>
367
- <input type="file" ref={fileRef} accept=".pdf" style={{ display: "none" }} onChange={handleFileUpload} />
368
- <div
369
- onClick={() => pidNumber && fileRef.current.click()}
370
- onMouseOver={(e) => { if (pidNumber) e.currentTarget.style.borderColor = "#185FA5"; }}
371
- onMouseOut={(e) => { if (pidNumber) e.currentTarget.style.borderColor = "#B5D4F4"; }}
372
- style={{
373
- border: pidNumber ? "1.5px dashed #B5D4F4" : "1.5px dashed #D0D5DD",
374
- borderRadius: "10px",
375
- padding: "28px 20px",
376
- textAlign: "center",
377
- cursor: pidNumber ? "pointer" : "not-allowed",
378
- backgroundColor: pidNumber ? "#E6F1FB" : "#F9FAFB",
379
- minHeight: "160px",
380
- display: "flex",
381
- flexDirection: "column",
382
- alignItems: "center",
383
- justifyContent: "center",
384
- gap: "10px",
385
- transition: "all 0.15s",
386
- opacity: pidNumber ? 1 : 0.6,
387
- }}
388
- >
389
- <div style={{
390
- background: pidNumber ? "#fff" : "#EAECF0",
391
- padding: "10px",
392
- borderRadius: "10px",
393
- display: "flex",
394
- filter: pidNumber ? "none" : "grayscale(100%)"
395
- }}>
396
- <svg width="32" height="32" viewBox="0 0 24 24" fill={pidNumber ? "#185FA5" : "#98A2B3"}>
397
- <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" />
398
- <path d="M12 18v-4M12 14l-2 2M12 14l2 2" stroke="#fff" strokeWidth="1.5" strokeLinecap="round" />
399
- </svg>
500
+
501
+ {/* Building Photo Upload */}
502
+ <div>
503
+ <div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "8px" }}>
504
+ {t("EKYC_CAPTURE_BUILDING_IMAGE") || "Capture building image"}
400
505
  </div>
401
- {propertyDocument ? (
402
- <div style={{ fontSize: "13px", fontWeight: "600", color: "#0F6E56" }}>
403
- {propertyDocument.name}
506
+ <UploadFile
507
+ id={"ekyc-building-photo"}
508
+ extraStyleName={"propertyCreate"}
509
+ accept=".jpg,.png,.jpeg"
510
+ onUpload={selectphoto}
511
+ onDelete={() => {
512
+ setBuildingPhotoFileStoreId(null);
513
+ setBuildingPhoto(null);
514
+ setFilephoto(null);
515
+ }}
516
+ message={buildingPhotoFileStoreId ? `1 ${t(`EKYC_ACTION_FILEUPLOADED`)}` : t(`EKYC_ACTION_NO_FILEUPLOADED`)}
517
+ error={error}
518
+ />
519
+ {buildingPhoto && (
520
+ <div style={{ marginTop: "10px", borderRadius: "8px", overflow: "hidden", border: "1px solid #EAECF0" }}>
521
+ <img src={buildingPhoto} alt="Building Preview" style={{ width: "100%", maxHeight: "150px", objectFit: "cover" }} />
404
522
  </div>
405
- ) : (
406
- <>
407
- <div style={{ fontSize: "13px", fontWeight: "600", color: pidNumber ? "#185FA5" : "#98A2B3" }}>
408
- {pidNumber ? (t("EKYC_UPLOAD_PROPERTY_DOC_CTA") || "Tap to upload") : (t("EKYC_ENTER_PID_FIRST_CTA") || "Enter PID to upload")}
409
- </div>
410
- <div style={{ fontSize: "12px", color: pidNumber ? "#378ADD" : "#98A2B3" }}>{pidNumber ? "PDF | Max 5MB" : "Requires PID"}</div>
411
- </>
412
523
  )}
413
524
  </div>
414
525
  </div>
415
526
 
416
- {/* Camera Capture */}
417
- <div>
418
- <div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "8px" }}>
419
- {t("EKYC_CAPTURE_BUILDING_IMAGE") || "Capture building image"}
527
+ {/* Info Banner */}
528
+ <div style={{
529
+ backgroundColor: "#E6F1FB", border: "0.5px solid #B5D4F4",
530
+ borderRadius: "8px", padding: "12px 14px",
531
+ display: "flex", alignItems: "flex-start", gap: "10px", marginBottom: "4px",
532
+ }}>
533
+ <div style={{ flexShrink: 0, marginTop: "1px" }}>
534
+ <InfoBannerIcon fill="#185FA5" />
420
535
  </div>
421
- <input type="file" ref={cameraRef} accept="image/*" capture="environment" style={{ display: "none" }} onChange={handlePhotoCapture} />
422
- <div
423
- onClick={!buildingPhoto ? () => cameraRef.current.click() : undefined}
424
- onMouseOver={(e) => { if (!buildingPhoto) e.currentTarget.style.borderColor = "#185FA5"; }}
425
- onMouseOut={(e) => { if (!buildingPhoto) e.currentTarget.style.borderColor = "#D0D5DD"; }}
426
- style={{
427
- border: "1.5px dashed #D0D5DD", borderRadius: "10px",
428
- minHeight: "160px", display: "flex", flexDirection: "column",
429
- alignItems: "center", justifyContent: "center",
430
- backgroundColor: "#F9FAFB",
431
- cursor: buildingPhoto ? "default" : "pointer",
432
- overflow: "hidden", transition: "border-color 0.15s",
433
- position: "relative",
434
- padding: buildingPhoto ? "0" : "28px 20px",
435
- }}
436
- >
437
- {!buildingPhoto ? (
438
- <>
439
- <div style={{ background: "#E6F1FB", width: "52px", height: "52px", borderRadius: "50%", display: "flex", alignItems: "center", justifyContent: "center", marginBottom: "10px" }}>
440
- <CameraIcon size={26} />
441
- </div>
442
- <div style={{ fontSize: "13px", fontWeight: "600", color: "#101828" }}>
443
- {t("EKYC_TAP_TO_CAPTURE") || "Tap to capture"}
444
- </div>
445
- <div style={{ fontSize: "12px", color: "#667085", marginTop: "2px" }}>
446
- {t("EKYC_BUILDING_PHOTO") || "Building photo with GPS"}
447
- </div>
448
- <div style={{ fontSize: "11px", color: "#98A2B3", marginTop: "2px" }}>
449
- JPG, PNG | Max 2MB
450
- </div>
451
- </>
452
- ) : (
453
- <>
454
- <img src={buildingPhoto} alt="Building" style={{ width: "100%", maxHeight: "200px", objectFit: "cover", display: "block" }} />
455
- <button
456
- onClick={(e) => { e.stopPropagation(); setBuildingPhoto(null); if (cameraRef.current) cameraRef.current.value = ""; }}
457
- style={{
458
- position: "absolute", top: "8px", right: "8px",
459
- background: "#fff", border: "0.5px solid #EAECF0",
460
- borderRadius: "7px", padding: "5px 10px",
461
- display: "flex", alignItems: "center", gap: "5px",
462
- cursor: "pointer", fontSize: "12px", color: "#D92D20", fontWeight: "500",
463
- }}
464
- >
465
- <TrashIcon size={13} /> {t("EKYC_REMOVE") || "Remove"}
466
- </button>
467
- </>
468
- )}
536
+ <div style={{ fontSize: "13px", color: "#185FA5", lineHeight: "1.5" }}>
537
+ {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."}
469
538
  </div>
470
539
  </div>
540
+
541
+ </div>
542
+
543
+ {/* Submit (Non-sticky, at form end) */}
544
+ <div style={{ marginTop: "24px" }}>
545
+ <SubmitBar
546
+ label={t("EKYC_SAVE_AND_CONTINUE") || "Save & Continue"}
547
+ onSubmit={handleSaveAndContinue}
548
+ />
471
549
  </div>
472
550
 
473
- {/* Info Banner */}
551
+ {/* Secure notice */}
474
552
  <div style={{
475
- backgroundColor: "#E6F1FB", border: "0.5px solid #B5D4F4",
476
- borderRadius: "8px", padding: "12px 14px",
477
- display: "flex", alignItems: "flex-start", gap: "10px", marginBottom: "4px",
553
+ display: "flex", alignItems: "center", justifyContent: "center",
554
+ gap: "5px", marginTop: "16px",
555
+ fontSize: "11px", color: "#98A2B3",
478
556
  }}>
479
- <div style={{ flexShrink: 0, marginTop: "1px" }}>
480
- <InfoBannerIcon fill="#185FA5" />
481
- </div>
482
- <div style={{ fontSize: "13px", color: "#185FA5", lineHeight: "1.5" }}>
483
- {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."}
484
- </div>
557
+ <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
558
+ <rect x="3" y="11" width="18" height="11" rx="2" />
559
+ <path d="M7 11V7a5 5 0 0 1 10 0v4" />
560
+ </svg>
561
+ {t("EKYC_SECURE_DATA_NOTICE") || "Your data is encrypted and secure"}
485
562
  </div>
486
-
487
- </div>
488
-
489
- {/* Submit (Non-sticky, at form end) */}
490
- <div style={{ marginTop: "24px" }}>
491
- <SubmitBar
492
- label={t("EKYC_SAVE_AND_CONTINUE") || "Save & Continue"}
493
- onSubmit={handleSaveAndContinue}
494
- />
495
- </div>
496
-
497
- {/* Secure notice */}
498
- <div style={{
499
- display: "flex", alignItems: "center", justifyContent: "center",
500
- gap: "5px", marginTop: "16px",
501
- fontSize: "11px", color: "#98A2B3",
502
- }}>
503
- <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
504
- <rect x="3" y="11" width="18" height="11" rx="2" />
505
- <path d="M7 11V7a5 5 0 0 1 10 0v4" />
506
- </svg>
507
- {t("EKYC_SECURE_DATA_NOTICE") || "Your data is encrypted and secure"}
508
- </div>
509
- </Card>
563
+ </Card>
564
+ </div>
510
565
  </div>
511
- </div>
566
+ {toast && (
567
+ <Toast
568
+ label={toast.message}
569
+ error={toast.type === "error"}
570
+ info={toast.type === "info"}
571
+ success={toast.type === "success"}
572
+ onClose={() => setToast(null)}
573
+ />
574
+ )}
575
+ </>
512
576
  );
513
577
  };
514
578