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

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.
Files changed (40) hide show
  1. package/dist/index.js +1 -1
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.modern.js +1338 -591
  4. package/dist/index.modern.js.map +1 -1
  5. package/package.json +1 -1
  6. package/src/Module.js +25 -7
  7. package/src/components/AadhaarVerification.js +415 -0
  8. package/src/components/AddressDetails.js +207 -0
  9. package/src/components/CeoDashboard.js +205 -0
  10. package/src/components/DesktopInbox.js +1 -1
  11. package/src/components/EKYCCard.js +4 -0
  12. package/src/components/MeterDetails.js +372 -0
  13. package/src/components/PropertyInfo.js +303 -0
  14. package/src/components/Review.js +572 -0
  15. package/src/components/SearchFormFieldsComponent.js +3 -3
  16. package/src/components/analytics/charts/ClusterHeatmap.js +88 -0
  17. package/src/components/analytics/charts/TaskStatusChart.js +92 -0
  18. package/src/components/analytics/components/AnalyticsTable.js +106 -0
  19. package/src/components/analytics/components/DashboardLayout.js +72 -0
  20. package/src/components/analytics/components/EmptyState.js +27 -0
  21. package/src/components/analytics/components/ErrorBoundary.js +27 -0
  22. package/src/components/analytics/components/FilterBar.js +73 -0
  23. package/src/components/analytics/components/NotificationPanel.js +77 -0
  24. package/src/components/analytics/components/SLAWidget.js +56 -0
  25. package/src/components/analytics/components/SkeletonLoader.js +53 -0
  26. package/src/components/analytics/components/SummaryCard.js +74 -0
  27. package/src/components/analytics/components/WorkflowTimeline.js +55 -0
  28. package/src/components/analytics/styles/Dashboard.css +54 -0
  29. package/src/components/analytics/utils/exportUtils.js +64 -0
  30. package/src/components/analytics/utils/filterSerializer.js +50 -0
  31. package/src/config/config.js +1 -1
  32. package/src/pages/citizen/index.js +74 -18
  33. package/src/pages/employee/ConsumerDetails.js +10 -281
  34. package/src/pages/employee/Inbox.js +6 -4
  35. package/src/pages/employee/index.js +44 -8
  36. package/src/pages/employee/AadhaarVerification.js +0 -512
  37. package/src/pages/employee/AddressDetails.js +0 -548
  38. package/src/pages/employee/MeterDetails.js +0 -496
  39. package/src/pages/employee/PropertyInfo.js +0 -489
  40. package/src/pages/employee/Review.js +0 -314
@@ -0,0 +1,303 @@
1
+ import React, { useState, Fragment, useEffect } from "react";
2
+ import { useLocation } from "react-router-dom";
3
+ import {
4
+ CardLabel,
5
+ TextInput,
6
+ Dropdown,
7
+ UploadFile,
8
+ Toast,
9
+ FormStep,
10
+ Loader
11
+ } from "@djb25/digit-ui-react-components";
12
+ import { useTranslation } from "react-i18next";
13
+
14
+ const PropertyInfo = ({ config, onSelect, formData }) => {
15
+ const { t } = useTranslation();
16
+ const location = useLocation();
17
+ const flowState = location.state || {};
18
+ const tenantId = Digit.ULBService.getCurrentTenantId();
19
+
20
+ const searchKno = flowState?.kNumber || flowState?.kno || formData?.kNumber || formData?.kno || sessionStorage.getItem("EKYC_K_NUMBER");
21
+
22
+ const { isLoading, data: searchData } = Digit.Hooks.ekyc.useSearchConnection(
23
+ { tenantId, details: { kno: searchKno } },
24
+ { enabled: !!searchKno, cacheTime: 0 }
25
+ );
26
+
27
+ const updateMutation = Digit.Hooks.ekyc.useEkycUpdate(tenantId);
28
+
29
+ const savedData = formData?.propertyDetails || {};
30
+
31
+ // 🔹 STATES
32
+ const [pidNumber, setPidNumber] = useState(savedData.pidNumber || "");
33
+ const [propertyType, setPropertyType] = useState(savedData.propertyType ? { name: savedData.propertyType } : null);
34
+ const [subPropertyCategory, setSubPropertyCategory] = useState(savedData.subPropertyCategory ? { name: savedData.subPropertyCategory } : null);
35
+
36
+ const [noOfFloors, setNoOfFloors] = useState(savedData.noOfFloors || "");
37
+ const [floorNo, setFloorNo] = useState(savedData.floorNo || "");
38
+
39
+ const [noOfRooms, setNoOfRooms] = useState(savedData.noOfRooms || "");
40
+ const [noOfBeds, setNoOfBeds] = useState(savedData.noOfBeds || "");
41
+ const [dwellingUnits, setDwellingUnits] = useState(savedData.dwellingUnits || "");
42
+
43
+ const [buildingImage, setBuildingImage] = useState(null);
44
+ const [buildingImageId, setBuildingImageId] = useState(savedData.buildingImageId || null);
45
+
46
+ const [toast, setToast] = useState(null);
47
+
48
+ // 🔹 PROPERTY TYPE OPTIONS
49
+ const propertyTypeOptions = [
50
+ { name: "Residential" },
51
+ { name: "Commercial" },
52
+ { name: "Hotel" },
53
+ { name: "Hospital" },
54
+ { name: "Nursing Home" },
55
+ ];
56
+
57
+ useEffect(() => {
58
+ const rawData = searchData || formData?.connectionDetails;
59
+ const propertyInfo = rawData?.propertyInfo || rawData?.propertyDetails || {};
60
+
61
+ if (propertyInfo && Object.keys(propertyInfo).length > 0 && !savedData.pidNumber) {
62
+ if (propertyInfo.pidNumber) setPidNumber(propertyInfo.pidNumber);
63
+ if (propertyInfo.numberOfFloors || propertyInfo.noOfFloor) setNoOfFloors(String(propertyInfo.numberOfFloors || propertyInfo.noOfFloor));
64
+ if (propertyInfo.buildingImageFileStoreId) setBuildingImageId(propertyInfo.buildingImageFileStoreId);
65
+
66
+ if (propertyInfo.subPropertyCategory) {
67
+ const matchingType = propertyTypeOptions.find(type => type.name.toLowerCase() === propertyInfo.subPropertyCategory.toLowerCase());
68
+ if (matchingType) setPropertyType(matchingType);
69
+ else setPropertyType({ name: propertyInfo.subPropertyCategory });
70
+ setSubPropertyCategory({ name: propertyInfo.subPropertyCategory });
71
+ }
72
+
73
+ if (propertyInfo.propertyType) {
74
+ setSubPropertyCategory({ name: propertyInfo.propertyType }); // Just in case, depending on how UI renders it
75
+ if (!propertyInfo.subPropertyCategory) setPropertyType({ name: propertyInfo.propertyType });
76
+ }
77
+
78
+ if (propertyInfo.floorNo) setFloorNo(propertyInfo.floorNo);
79
+ if (propertyInfo.numberOfRooms !== null && propertyInfo.numberOfRooms !== undefined) setNoOfRooms(String(propertyInfo.numberOfRooms));
80
+ if (propertyInfo.numberOfBeds !== null && propertyInfo.numberOfBeds !== undefined) setNoOfBeds(String(propertyInfo.numberOfBeds));
81
+ if (propertyInfo.numberOfDwellingUnits !== null && propertyInfo.numberOfDwellingUnits !== undefined) setDwellingUnits(String(propertyInfo.numberOfDwellingUnits));
82
+ }
83
+ }, [searchData, formData?.connectionDetails]);
84
+
85
+ // 🔹 FILE UPLOAD
86
+ const handleUpload = async (e) => {
87
+ const file = e.target.files[0];
88
+ if (!file) return;
89
+
90
+ if (file.size > 2000000) {
91
+ setToast({ type: "error", message: "Max size 2MB exceeded" });
92
+ return;
93
+ }
94
+
95
+ try {
96
+ const res = await Digit.UploadServices.Filestorage(
97
+ "EKYC",
98
+ file,
99
+ tenantId
100
+ );
101
+
102
+ const fileStoreId = res?.data?.files?.[0]?.fileStoreId;
103
+
104
+ if (fileStoreId) {
105
+ setBuildingImageId(fileStoreId);
106
+
107
+ const reader = new FileReader();
108
+ reader.onloadend = () => setBuildingImage(reader.result);
109
+ reader.readAsDataURL(file);
110
+
111
+ setToast({ type: "success", message: "Upload successful" });
112
+ }
113
+ } catch {
114
+ setToast({ type: "error", message: "Upload failed" });
115
+ }
116
+ };
117
+
118
+ // 🔹 VALIDATION
119
+ const isValid = () => {
120
+ if (!propertyType) return false;
121
+ if (!subPropertyCategory) return false;
122
+ if (!noOfFloors || Number(noOfFloors) < 1) return false;
123
+ if (!buildingImageId) return false;
124
+
125
+ if (propertyType?.name === "Hotel" && !noOfRooms) return false;
126
+ if (
127
+ (propertyType?.name === "Hospital" ||
128
+ propertyType?.name === "Nursing Home") &&
129
+ !noOfBeds
130
+ )
131
+ return false;
132
+
133
+ return true;
134
+ };
135
+
136
+ // 🔹 SUBMIT
137
+ const onStepSelect = async () => {
138
+ /* Optional validation enforce
139
+ if (!isValid()) {
140
+ setToast({ type: "error", message: "Fill all required fields" });
141
+ return;
142
+ }
143
+ */
144
+
145
+ const data = {
146
+ pidNumber,
147
+ propertyType: propertyType?.name,
148
+ subPropertyCategory: subPropertyCategory?.name,
149
+ noOfFloors,
150
+ floorNo,
151
+ noOfRooms,
152
+ noOfBeds,
153
+ dwellingUnits,
154
+ buildingImageId,
155
+ };
156
+
157
+ try {
158
+ await updateMutation.mutateAsync({
159
+ RequestInfo: {},
160
+ updateType: "PROPERTY",
161
+ kno: searchKno,
162
+ ...data,
163
+ });
164
+ setToast({ type: "success", message: "Property details updated successfully!" });
165
+ onSelect(config.key, data);
166
+ } catch (error) {
167
+ setToast({ type: "error", message: "Failed to update property details" });
168
+ }
169
+ };
170
+
171
+ if (isLoading) {
172
+ return <Loader />;
173
+ }
174
+
175
+ return (
176
+ <Fragment>
177
+ <FormStep
178
+ t={t}
179
+ onSelect={onStepSelect}
180
+ config={config}
181
+ label={t("ES_COMMON_CONTINUE")}
182
+ isDisabled={!isValid()}
183
+ >
184
+ <div>
185
+ <CardLabel>PID Number</CardLabel>
186
+ <TextInput value={pidNumber} onChange={(e) => setPidNumber(e.target.value)} />
187
+ </div>
188
+
189
+ <div>
190
+ <CardLabel>Property Type</CardLabel>
191
+ <Dropdown
192
+ option={propertyTypeOptions}
193
+ selected={propertyType}
194
+ select={setPropertyType}
195
+ />
196
+ </div>
197
+
198
+ <div>
199
+ <CardLabel>Sub Property Category</CardLabel>
200
+ <Dropdown option={[]} selected={subPropertyCategory} select={setSubPropertyCategory} />
201
+ </div>
202
+
203
+ <div>
204
+ <CardLabel>No. of Floors *</CardLabel>
205
+ <TextInput
206
+ type="number"
207
+ value={noOfFloors}
208
+ onChange={(e) => setNoOfFloors(e.target.value)}
209
+ />
210
+ </div>
211
+
212
+ <div>
213
+ <CardLabel>Floor No. of this KNO</CardLabel>
214
+ <TextInput value={floorNo} onChange={(e) => setFloorNo(e.target.value)} />
215
+ </div>
216
+
217
+ <div>
218
+ <CardLabel>No of Beds</CardLabel>
219
+ <TextInput
220
+ type="number"
221
+ value={noOfBeds}
222
+ onChange={(e) => setNoOfBeds(e.target.value)}
223
+ />
224
+ </div>
225
+
226
+ <div>
227
+ <CardLabel>No. of Rooms</CardLabel>
228
+ <TextInput
229
+ type="number"
230
+ value={noOfRooms}
231
+ onChange={(e) => setNoOfRooms(e.target.value)}
232
+ />
233
+ </div>
234
+
235
+ {/* HOTEL CONDITION */}
236
+ {propertyType?.name === "Hotel" && (
237
+ <div>
238
+ <CardLabel>No. of Rooms *</CardLabel>
239
+ <TextInput
240
+ type="number"
241
+ value={noOfRooms}
242
+ onChange={(e) => setNoOfRooms(e.target.value)}
243
+ />
244
+ </div>
245
+ )}
246
+
247
+ {/* HOSPITAL CONDITION */}
248
+ {(propertyType?.name === "Hospital" ||
249
+ propertyType?.name === "Nursing Home") && (
250
+ <div>
251
+ <CardLabel>No. of Beds *</CardLabel>
252
+ <TextInput
253
+ type="number"
254
+ value={noOfBeds}
255
+ onChange={(e) => setNoOfBeds(e.target.value)}
256
+ />
257
+ </div>
258
+ )}
259
+
260
+ <div>
261
+ <CardLabel>Number of Dwelling Units</CardLabel>
262
+ <TextInput
263
+ type="number"
264
+ value={dwellingUnits}
265
+ onChange={(e) => setDwellingUnits(e.target.value)}
266
+ />
267
+ </div>
268
+
269
+ <div>
270
+ <CardLabel>Building Image *</CardLabel>
271
+ <UploadFile
272
+ onUpload={handleUpload}
273
+ onDelete={() => {
274
+ setBuildingImage(null);
275
+ setBuildingImageId(null);
276
+ }}
277
+ message={buildingImageId ? "Uploaded" : "No file selected"}
278
+ />
279
+ </div>
280
+
281
+ {buildingImage && (
282
+ <div style={{ gridColumn: "span 2" }}>
283
+ <img
284
+ src={buildingImage}
285
+ alt="preview"
286
+ style={{ width: "100%", marginTop: "10px" }}
287
+ />
288
+ </div>
289
+ )}
290
+
291
+ {toast && (
292
+ <Toast
293
+ label={toast.message}
294
+ error={toast.type === "error"}
295
+ onClose={() => setToast(null)}
296
+ />
297
+ )}
298
+ </FormStep>
299
+ </Fragment>
300
+ );
301
+ };
302
+
303
+ export default PropertyInfo;