@djb25/digit-ui-module-ekyc 1.0.2 → 1.0.4
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 +2092 -1477
- package/dist/index.modern.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ConnectionDetailsView.js +83 -79
- package/src/components/DesktopInbox.js +117 -126
- package/src/components/SearchConsumer.js +103 -102
- package/src/pages/employee/AadhaarVerification.js +526 -330
- package/src/pages/employee/AddressDetails.js +637 -429
- package/src/pages/employee/Create.js +5 -19
- package/src/pages/employee/PropertyInfo.js +409 -316
- package/src/pages/employee/Review.js +335 -109
|
@@ -1,401 +1,494 @@
|
|
|
1
|
-
import React, { useState, useRef } from "react";
|
|
2
|
-
import {
|
|
1
|
+
import React, { useState, useRef, Fragment } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Card,
|
|
4
|
+
CardLabel,
|
|
5
|
+
TextInput,
|
|
6
|
+
SubmitBar,
|
|
7
|
+
CardHeader,
|
|
8
|
+
ActionBar,
|
|
9
|
+
Dropdown,
|
|
10
|
+
InfoBannerIcon,
|
|
11
|
+
HomeIcon,
|
|
12
|
+
} from "@djb25/digit-ui-react-components";
|
|
3
13
|
import { useTranslation } from "react-i18next";
|
|
4
14
|
import { useHistory, useLocation } from "react-router-dom";
|
|
5
15
|
|
|
16
|
+
// ─── Icons ────────────────────────────────────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
const CheckIcon = ({ size = 11, color = "#fff" }) => (
|
|
19
|
+
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="3" strokeLinecap="round">
|
|
20
|
+
<polyline points="20 6 9 17 4 12" />
|
|
21
|
+
</svg>
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const BuildingIcon = ({ size = 16 }) => (
|
|
25
|
+
<svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor">
|
|
26
|
+
<path d="M12 7V3H2v18h20V7H12zM6 19H4v-2h2v2zm0-4H4v-2h2v2zm0-4H4V9h2v2zm0-4H4V5h2v2zm4 12H8v-2h2v2zm0-4H8v-2h2v2zm0-4H8V9h2v2zm0-4H8V5h2v2zm10 12h-8V9h8v10zm-2-8h-4v2h4v-2zm0 4h-4v2h4v-2z" />
|
|
27
|
+
</svg>
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
const BriefcaseIcon = ({ size = 16 }) => (
|
|
31
|
+
<svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor">
|
|
32
|
+
<path d="M20 6H16V4c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H4c-1.11 0-2 .89-2 2v13c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-6-2v2h-4V4h4z" />
|
|
33
|
+
</svg>
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const DocumentIcon = ({ size = 16 }) => (
|
|
37
|
+
<svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor">
|
|
38
|
+
<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" />
|
|
39
|
+
</svg>
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const CameraIcon = ({ size = 24 }) => (
|
|
43
|
+
<svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor">
|
|
44
|
+
<path d="M9 2L7.17 4H4C2.9 4 2 4.9 2 6v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L13 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" />
|
|
45
|
+
</svg>
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const TrashIcon = ({ size = 14 }) => (
|
|
49
|
+
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="#D92D20" strokeWidth="2" strokeLinecap="round">
|
|
50
|
+
<polyline points="3 6 5 6 21 6" />
|
|
51
|
+
<path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" />
|
|
52
|
+
<path d="M10 11v6M14 11v6" />
|
|
53
|
+
<path d="M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2" />
|
|
54
|
+
</svg>
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const PidIcon = ({ size = 16 }) => (
|
|
58
|
+
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
59
|
+
<rect x="3" y="4" width="18" height="16" rx="2" />
|
|
60
|
+
<path d="M7 8h5M7 12h8M7 16h4" />
|
|
61
|
+
</svg>
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
// ─── Reusable: Section heading with inline rule ───────────────────────────────
|
|
65
|
+
|
|
66
|
+
const SectionHead = ({ icon, label }) => (
|
|
67
|
+
<div style={{
|
|
68
|
+
display: "flex", alignItems: "center", gap: "8px",
|
|
69
|
+
marginBottom: "16px", marginTop: "4px",
|
|
70
|
+
}}>
|
|
71
|
+
<div style={{ opacity: 0.5, display: "flex" }}>{icon}</div>
|
|
72
|
+
<span style={{ fontSize: "15px", fontWeight: "600", color: "#0B0C0C", whiteSpace: "nowrap" }}>
|
|
73
|
+
{label}
|
|
74
|
+
</span>
|
|
75
|
+
<div style={{ flex: 1, height: "1px", background: "#EAECF0" }} />
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
// ─── Reusable: Icon-prefixed input ────────────────────────────────────────────
|
|
80
|
+
|
|
81
|
+
const IconInput = ({ icon, ...props }) => (
|
|
82
|
+
<div style={{ position: "relative", width: "100%" }}>
|
|
83
|
+
<div style={{
|
|
84
|
+
position: "absolute", left: "10px",
|
|
85
|
+
top: "50%", transform: "translateY(-50%)",
|
|
86
|
+
zIndex: 1, opacity: 0.45, display: "flex", pointerEvents: "none",
|
|
87
|
+
}}>
|
|
88
|
+
{icon}
|
|
89
|
+
</div>
|
|
90
|
+
<TextInput textInputStyle={{ paddingLeft: "36px", paddingRight: "12px" }} {...props} />
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
// ─── Main Component ───────────────────────────────────────────────────────────
|
|
95
|
+
|
|
6
96
|
const PropertyInfo = () => {
|
|
7
97
|
const { t } = useTranslation();
|
|
8
98
|
const history = useHistory();
|
|
9
99
|
const location = useLocation();
|
|
10
100
|
|
|
11
|
-
const
|
|
101
|
+
const flowState = location.state || { kNumber: "EKYC-1234567890" };
|
|
102
|
+
const { kNumber } = flowState;
|
|
103
|
+
|
|
12
104
|
const tenantId = Digit.ULBService.getCurrentTenantId();
|
|
13
|
-
const { data: dataV0
|
|
14
|
-
const { data
|
|
15
|
-
const { data: dataV1
|
|
16
|
-
const { data: dataV2
|
|
105
|
+
const { data: dataV0 } = Digit.Hooks.ekyc.useGetPropertyType(tenantId);
|
|
106
|
+
const { data: dataConn } = Digit.Hooks.ekyc.useGetConnectionTypeV2(tenantId);
|
|
107
|
+
const { data: dataV1 } = Digit.Hooks.ekyc.useGetUserType(tenantId);
|
|
108
|
+
const { data: dataV2 } = Digit.Hooks.ekyc.useGetFloorCount(tenantId);
|
|
17
109
|
|
|
18
110
|
const [ownerType, setOwnerType] = useState("OWNER");
|
|
19
111
|
const [pidNumber, setPidNumber] = useState("");
|
|
20
|
-
const [connectionType, setConnectionType] = useState(null);
|
|
21
112
|
const [connectionCategory, setConnectionCategory] = useState(null);
|
|
113
|
+
const [connectionType, setConnectionType] = useState(null);
|
|
22
114
|
const [userType, setUserType] = useState(null);
|
|
23
115
|
const [noOfFloors, setNoOfFloors] = useState(null);
|
|
24
116
|
const [propertyDocument, setPropertyDocument] = useState(null);
|
|
25
117
|
const [buildingPhoto, setBuildingPhoto] = useState(null);
|
|
118
|
+
|
|
26
119
|
const fileRef = useRef(null);
|
|
27
120
|
const cameraRef = useRef(null);
|
|
28
121
|
|
|
29
122
|
const handleSaveAndContinue = () => {
|
|
30
123
|
history.push("/digit-ui/employee/ekyc/review", {
|
|
31
|
-
...
|
|
124
|
+
...flowState,
|
|
32
125
|
propertyDetails: {
|
|
33
|
-
ownerType,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
userType,
|
|
38
|
-
noOfFloors,
|
|
39
|
-
propertyDocument,
|
|
40
|
-
buildingPhoto
|
|
41
|
-
}
|
|
126
|
+
ownerType, pidNumber, connectionType,
|
|
127
|
+
connectionCategory, userType, noOfFloors,
|
|
128
|
+
propertyDocument, buildingPhoto,
|
|
129
|
+
},
|
|
42
130
|
});
|
|
43
131
|
};
|
|
44
132
|
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
</div>
|
|
51
|
-
);
|
|
133
|
+
const handleFileUpload = (e) => {
|
|
134
|
+
const file = e.target.files[0];
|
|
135
|
+
if (!file) return;
|
|
136
|
+
setPropertyDocument(file);
|
|
137
|
+
};
|
|
52
138
|
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
+
};
|
|
60
146
|
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
<path d="M8 16H9V17H8V16Z" fill="white" />
|
|
66
|
-
<path d="M15 16H16V17H15V16Z" fill="white" />
|
|
67
|
-
<path d="M12 15.5L14 13.5H10L12 15.5Z" fill="white" />
|
|
68
|
-
{/* Simple representation of upload arrow on document */}
|
|
69
|
-
<path d="M12 18V14M12 14L10 16M12 14L14 16" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
|
70
|
-
</svg>
|
|
71
|
-
);
|
|
147
|
+
const connectionCategoryOptions =
|
|
148
|
+
dataV0?.["ws-services-calculation"]?.propertyTypeV2?.map((item) => ({
|
|
149
|
+
label: t(item.code), value: item.code,
|
|
150
|
+
})) || [];
|
|
72
151
|
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
152
|
+
const connectionTypeOptions =
|
|
153
|
+
dataConn?.["ws-services-calculation"]?.connectionTypeV2?.map((item) => ({
|
|
154
|
+
label: t(item.code), value: item.code,
|
|
155
|
+
})) || [];
|
|
156
|
+
|
|
157
|
+
const userTypeOptions =
|
|
158
|
+
dataV1?.["ws-services-calculation"]?.userTypeV2?.map((item) => ({
|
|
159
|
+
label: t(item.code), value: item.code,
|
|
160
|
+
})) || [];
|
|
161
|
+
|
|
162
|
+
const floorOptions =
|
|
163
|
+
dataV2?.["ws-services-calculation"]?.floorCount?.map((item) => ({
|
|
164
|
+
label: t(item.code), value: item.code,
|
|
165
|
+
})) || [];
|
|
78
166
|
|
|
79
167
|
return (
|
|
80
168
|
<div className="inbox-container">
|
|
169
|
+
<style>{`
|
|
170
|
+
@keyframes fadeSlideIn {
|
|
171
|
+
from { opacity: 0; transform: translateY(8px); }
|
|
172
|
+
to { opacity: 1; transform: translateY(0); }
|
|
173
|
+
}
|
|
174
|
+
`}</style>
|
|
175
|
+
|
|
176
|
+
{/* ── Sidebar ── */}
|
|
81
177
|
<div className="filters-container">
|
|
82
|
-
{
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
<HomeIcon style={{ width: "24px", height: "24px" }} />
|
|
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" }} />
|
|
86
181
|
</div>
|
|
87
|
-
<div style={{ fontWeight: "
|
|
88
|
-
{t("EKYC_PROCESS")}
|
|
182
|
+
<div style={{ fontWeight: "600", fontSize: "15px", color: "#0B0C0C" }}>
|
|
183
|
+
{t("EKYC_PROCESS") || "eKYC Process"}
|
|
89
184
|
</div>
|
|
90
185
|
</Card>
|
|
91
186
|
|
|
92
|
-
{
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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>
|
|
215
|
+
</div>
|
|
216
|
+
))}
|
|
100
217
|
</div>
|
|
101
218
|
</div>
|
|
102
219
|
|
|
220
|
+
{/* ── Main Content ── */}
|
|
103
221
|
<div style={{ flex: 1, marginLeft: "16px" }}>
|
|
104
222
|
<Card>
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
<
|
|
108
|
-
{t("
|
|
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>
|
|
109
235
|
</div>
|
|
110
236
|
</div>
|
|
111
237
|
|
|
112
|
-
<div style={{
|
|
113
|
-
<SuitcaseIcon />
|
|
114
|
-
<span style={{ fontSize: "20px", fontWeight: "700", color: "#101828" }}>{t("Property Details")}</span>
|
|
115
|
-
</div>
|
|
238
|
+
<div style={{ animation: "fadeSlideIn 0.3s ease" }}>
|
|
116
239
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
borderRadius: "10px",
|
|
144
|
-
border: "none",
|
|
145
|
-
backgroundColor: ownerType === "TENANT" ? "#3D51B0" : "transparent",
|
|
146
|
-
color: ownerType === "TENANT" ? "#FFFFFF" : "#667085",
|
|
147
|
-
fontWeight: "600",
|
|
148
|
-
cursor: "pointer",
|
|
149
|
-
transition: "all 0.2s"
|
|
150
|
-
}}
|
|
151
|
-
>
|
|
152
|
-
{t("Tenant")}
|
|
153
|
-
</button>
|
|
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
|
+
))}
|
|
154
266
|
</div>
|
|
155
267
|
</div>
|
|
156
268
|
|
|
157
|
-
{/* PID Number
|
|
158
|
-
<div style={{ marginBottom: "
|
|
159
|
-
<
|
|
160
|
-
{t("
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
value={pidNumber}
|
|
165
|
-
onChange={(e) => setPidNumber(e.target.value)}
|
|
166
|
-
placeholder={t("Enter_PID_Number")}
|
|
167
|
-
textInputStyle={{ paddingLeft: "44px", borderRadius: "12px", border: "1px solid #D0D5DD", height: "56px" }}
|
|
168
|
-
/>
|
|
169
|
-
<div style={{ position: "absolute", left: "16px", top: "50%", transform: "translateY(-50%)", color: "#3D51B0", fontSize: "20px", fontWeight: "600" }}>#</div>
|
|
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>
|
|
170
276
|
</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
|
+
/>
|
|
171
283
|
</div>
|
|
172
|
-
</Card>
|
|
173
284
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
<
|
|
178
|
-
|
|
285
|
+
<hr style={{ margin: "24px 0", border: 0, borderTop: "1px solid #EAECF0" }} />
|
|
286
|
+
|
|
287
|
+
{/* ── Building Info Section ── */}
|
|
288
|
+
<SectionHead
|
|
289
|
+
icon={<BuildingIcon size={16} />}
|
|
290
|
+
label={t("EKYC_BUILDING_INFO") || "Building info"}
|
|
291
|
+
/>
|
|
179
292
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
state: connectionCategory,
|
|
187
|
-
setState: setConnectionCategory,
|
|
188
|
-
options: dataV0?.["ws-services-calculation"]?.propertyTypeV2?.map(item => ({
|
|
189
|
-
label: t(item.code),
|
|
190
|
-
value: item.code
|
|
191
|
-
})) || []
|
|
192
|
-
},
|
|
193
|
-
{
|
|
194
|
-
label: "Connection_Category",
|
|
195
|
-
state: connectionType,
|
|
196
|
-
setState: setConnectionType,
|
|
197
|
-
options: data?.["ws-services-calculation"]?.connectionTypeV2?.map(item => ({
|
|
198
|
-
label: t(item.code),
|
|
199
|
-
value: item.code
|
|
200
|
-
})) || []
|
|
201
|
-
},
|
|
202
|
-
// { label: "User_Type", state: userType, setState: setUserType },
|
|
203
|
-
{
|
|
204
|
-
label: "User_Type",
|
|
205
|
-
state: userType,
|
|
206
|
-
setState: setUserType,
|
|
207
|
-
options: dataV1?.["ws-services-calculation"]?.userTypeV2?.map(item => ({
|
|
208
|
-
label: t(item.code),
|
|
209
|
-
value: item.code
|
|
210
|
-
})) || []
|
|
211
|
-
},
|
|
212
|
-
{
|
|
213
|
-
label: "No_of_Floor",
|
|
214
|
-
state: noOfFloors,
|
|
215
|
-
setState: setNoOfFloors,
|
|
216
|
-
options: dataV2?.["ws-services-calculation"]?.floorCount?.map(item => ({
|
|
217
|
-
label: t(item.code),
|
|
218
|
-
value: item.code
|
|
219
|
-
})) || []
|
|
220
|
-
}
|
|
221
|
-
].map((item, idx) => (
|
|
222
|
-
<div key={idx} style={{ marginBottom: "20px" }}>
|
|
223
|
-
<CardLabel style={{ fontSize: "14px", fontWeight: "600", color: "#344054", marginBottom: "8px" }}>{t(item.label)}</CardLabel>
|
|
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"}
|
|
298
|
+
</div>
|
|
224
299
|
<Dropdown
|
|
225
|
-
selected={
|
|
226
|
-
select={
|
|
227
|
-
option={
|
|
300
|
+
selected={connectionCategory}
|
|
301
|
+
select={setConnectionCategory}
|
|
302
|
+
option={connectionCategoryOptions}
|
|
228
303
|
optionKey="label"
|
|
229
304
|
t={t}
|
|
230
|
-
|
|
305
|
+
placeholder={t("EKYC_SELECT") || "Select"}
|
|
231
306
|
/>
|
|
232
307
|
</div>
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
{t("
|
|
260
|
-
|
|
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"}
|
|
311
|
+
</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
|
+
</div>
|
|
321
|
+
</div>
|
|
322
|
+
|
|
323
|
+
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "14px", marginBottom: "24px" }}>
|
|
324
|
+
<div>
|
|
325
|
+
<div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
|
|
326
|
+
{t("EKYC_USER_TYPE") || "User type"}
|
|
327
|
+
</div>
|
|
328
|
+
<Dropdown
|
|
329
|
+
selected={userType}
|
|
330
|
+
select={setUserType}
|
|
331
|
+
option={userTypeOptions}
|
|
332
|
+
optionKey="label"
|
|
333
|
+
t={t}
|
|
334
|
+
placeholder={t("EKYC_SELECT") || "Select"}
|
|
335
|
+
/>
|
|
336
|
+
</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"}
|
|
340
|
+
</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
|
+
</div>
|
|
350
|
+
</div>
|
|
351
|
+
|
|
352
|
+
<hr style={{ margin: "24px 0", border: 0, borderTop: "1px solid #EAECF0" }} />
|
|
261
353
|
|
|
354
|
+
{/* ── Documents & Photo Section ── */}
|
|
355
|
+
<SectionHead
|
|
356
|
+
icon={<DocumentIcon size={16} />}
|
|
357
|
+
label={t("EKYC_DOCUMENTS_PHOTO") || "Documents & photo"}
|
|
358
|
+
/>
|
|
359
|
+
|
|
360
|
+
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "14px", marginBottom: "20px" }}>
|
|
361
|
+
|
|
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"}
|
|
366
|
+
</div>
|
|
367
|
+
<input type="file" ref={fileRef} accept=".pdf" style={{ display: "none" }} onChange={handleFileUpload} />
|
|
262
368
|
<div
|
|
369
|
+
onClick={() => fileRef.current.click()}
|
|
370
|
+
onMouseOver={(e) => e.currentTarget.style.borderColor = "#185FA5"}
|
|
371
|
+
onMouseOut={(e) => e.currentTarget.style.borderColor = "#B5D4F4"}
|
|
263
372
|
style={{
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
cursor: "pointer",
|
|
271
|
-
display: "flex",
|
|
272
|
-
flexDirection: "column",
|
|
273
|
-
justifyContent: "center"
|
|
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",
|
|
274
379
|
}}
|
|
275
|
-
onClick={() => fileRef.current.click()}
|
|
276
380
|
>
|
|
277
|
-
<
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
fontWeight: "600",
|
|
283
|
-
fontSize: "16px",
|
|
284
|
-
marginBottom: "20px",
|
|
285
|
-
lineHeight: "1.5"
|
|
286
|
-
}}
|
|
287
|
-
>
|
|
288
|
-
{t("Upload_your_property_document_in_PDF_Only")}
|
|
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>
|
|
289
386
|
</div>
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
style={{
|
|
294
|
-
backgroundColor: "#FFFFFF",
|
|
295
|
-
padding: "12px",
|
|
296
|
-
borderRadius: "12px",
|
|
297
|
-
boxShadow: "0px 1px 2px rgba(16, 24, 40, 0.05)"
|
|
298
|
-
}}
|
|
299
|
-
>
|
|
300
|
-
<PdfIcon />
|
|
387
|
+
{propertyDocument ? (
|
|
388
|
+
<div style={{ fontSize: "13px", fontWeight: "600", color: "#0F6E56" }}>
|
|
389
|
+
✓ {propertyDocument.name}
|
|
301
390
|
</div>
|
|
302
|
-
|
|
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
|
+
)}
|
|
303
399
|
</div>
|
|
304
400
|
</div>
|
|
305
401
|
|
|
306
|
-
{/* Capture
|
|
307
|
-
<div
|
|
308
|
-
style={{
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
flexDirection: "column"
|
|
313
|
-
}}
|
|
314
|
-
>
|
|
315
|
-
<CardLabel
|
|
316
|
-
style={{
|
|
317
|
-
fontSize: "14px",
|
|
318
|
-
fontWeight: "600",
|
|
319
|
-
color: "#344054",
|
|
320
|
-
marginBottom: "8px"
|
|
321
|
-
}}
|
|
322
|
-
>
|
|
323
|
-
{t("Capture_Building_Image")}
|
|
324
|
-
</CardLabel>
|
|
325
|
-
|
|
402
|
+
{/* Camera Capture */}
|
|
403
|
+
<div>
|
|
404
|
+
<div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "8px" }}>
|
|
405
|
+
{t("EKYC_CAPTURE_BUILDING_IMAGE") || "Capture building image"}
|
|
406
|
+
</div>
|
|
407
|
+
<input type="file" ref={cameraRef} accept="image/*" capture="environment" style={{ display: "none" }} onChange={handlePhotoCapture} />
|
|
326
408
|
<div
|
|
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"; }}
|
|
327
412
|
style={{
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
flexDirection: "column",
|
|
337
|
-
justifyContent: "center"
|
|
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",
|
|
338
421
|
}}
|
|
339
|
-
onClick={() => cameraRef.current.click()}
|
|
340
422
|
>
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
display: "
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
}}
|
|
371
|
-
>
|
|
372
|
-
{t("Tap_to_Capture")}
|
|
373
|
-
</div>
|
|
374
|
-
|
|
375
|
-
<div style={{ color: "#667085", fontSize: "14px" }}>
|
|
376
|
-
{t("Building_Photo")}
|
|
377
|
-
</div>
|
|
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
|
+
)}
|
|
378
452
|
</div>
|
|
379
453
|
</div>
|
|
380
454
|
</div>
|
|
381
455
|
|
|
382
456
|
{/* Info Banner */}
|
|
383
|
-
<div style={{
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
457
|
+
<div style={{
|
|
458
|
+
backgroundColor: "#E6F1FB", border: "0.5px solid #B5D4F4",
|
|
459
|
+
borderRadius: "8px", padding: "12px 14px",
|
|
460
|
+
display: "flex", alignItems: "flex-start", gap: "10px", marginBottom: "4px",
|
|
461
|
+
}}>
|
|
462
|
+
<div style={{ flexShrink: 0, marginTop: "1px" }}>
|
|
463
|
+
<InfoBannerIcon fill="#185FA5" />
|
|
388
464
|
</div>
|
|
389
|
-
<div style={{
|
|
390
|
-
{t("
|
|
465
|
+
<div style={{ fontSize: "13px", color: "#185FA5", lineHeight: "1.5" }}>
|
|
466
|
+
{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."}
|
|
391
467
|
</div>
|
|
392
468
|
</div>
|
|
393
|
-
<div style={{ display: "flex", justifyContent: "flex-start", marginTop: "24px" }}>
|
|
394
|
-
<SubmitBar label={t("Save_&_Continue")} onSubmit={handleSaveAndContinue} style={{ borderRadius: "8px", height: "48px", margin: 0 }} />
|
|
395
|
-
</div>
|
|
396
|
-
</Card>
|
|
397
469
|
|
|
470
|
+
</div>
|
|
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>
|
|
398
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>
|
|
399
492
|
</Card>
|
|
400
493
|
</div>
|
|
401
494
|
</div>
|