@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,452 +1,660 @@
|
|
|
1
1
|
import React, { useState, useRef, Fragment } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Card,
|
|
4
|
+
LabelFieldPair,
|
|
5
|
+
CardLabel,
|
|
6
|
+
TextInput,
|
|
7
|
+
SubmitBar,
|
|
8
|
+
CardHeader,
|
|
9
|
+
RadioButtons,
|
|
10
|
+
ActionBar,
|
|
11
|
+
InfoBannerIcon,
|
|
12
|
+
PropertyHouse,
|
|
13
|
+
LocationIcon,
|
|
14
|
+
HomeIcon,
|
|
15
|
+
ConnectingCheckPoints,
|
|
16
|
+
CheckPoint,
|
|
17
|
+
} from "@djb25/digit-ui-react-components";
|
|
3
18
|
import { useTranslation } from "react-i18next";
|
|
4
19
|
import { useHistory, useLocation } from "react-router-dom";
|
|
5
20
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
21
|
+
// ─── Icons ────────────────────────────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
const FlagIcon = ({ size = 20 }) => (
|
|
24
|
+
<svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
25
|
+
<path d="M14.4 6L13.6 4H5V21H7V14H12.6L13.4 16H20V6H14.4Z" fill="#0F6E56" />
|
|
26
|
+
</svg>
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const IdCardIcon = ({ size = 20 }) => (
|
|
30
|
+
<svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
31
|
+
<path
|
|
32
|
+
d="M2 7V17C2 18.1 2.9 19 4 19H20C21.1 19 22 18.1 22 17V7C22 5.9 21.1 5 20 5H4C2.9 5 2 5.9 2 7ZM12 11H14V13H12V11ZM12 7H14V9H12V7ZM16 11H20V13H16V11ZM16 7H20V9H16V7ZM4 7H10V15H4V7ZM20 17H4V16H20V17Z"
|
|
33
|
+
fill="#185FA5"
|
|
34
|
+
/>
|
|
35
|
+
</svg>
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const CameraIcon = ({ size = 28 }) => (
|
|
39
|
+
<svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
40
|
+
<path
|
|
41
|
+
d="M9 2L7.17 4H4C2.9 4 2 4.9 2 6V18C2 19.1 2.9 20 4 20H20C21.1 20 22 19.1 22 18V6C22 4.9 21.1 4 20 4H16.83L15 2H9ZM12 17C9.24 17 7 14.76 7 12C7 9.24 9.24 7 12 7C14.76 7 17 9.24 17 12C17 14.76 14.76 17 12 17ZM12 9C10.34 9 9 10.34 9 12C9 13.66 10.34 15 12 15C13.66 15 15 13.66 15 12C15 10.34 13.66 9 12 9Z"
|
|
42
|
+
fill="#185FA5"
|
|
43
|
+
/>
|
|
44
|
+
</svg>
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const TargetIcon = ({ size = 20 }) => (
|
|
48
|
+
<svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
49
|
+
<path
|
|
50
|
+
d="M12 8C9.79 8 8 9.79 8 12C8 14.21 9.79 16 12 16C14.21 16 16 14.21 16 12C16 9.79 14.21 8 12 8ZM20.94 11C20.48 6.83 17.17 3.52 13 3.06V1H11V3.06C6.83 3.52 3.52 6.83 3.06 11H1V13H3.06C3.52 17.17 6.83 20.48 11 20.94V23H13V20.94C17.17 20.48 20.48 17.17 20.94 13H23V11H20.94ZM12 19C8.13 19 5 15.87 5 12C5 8.13 8.13 5 12 5C15.87 5 19 8.13 19 12C19 15.87 15.87 19 12 19Z"
|
|
51
|
+
fill="#185FA5"
|
|
52
|
+
/>
|
|
53
|
+
</svg>
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const PincodeIcon = ({ size = 18 }) => (
|
|
57
|
+
<svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
58
|
+
<path
|
|
59
|
+
d="M13 13V11H15V13H13ZM13 9V7H15V9H13ZM17 13V11H19V13H17ZM17 9V7H19V9H17ZM11 13V11H9V13H11ZM11 9V7H9V9H11ZM7 13V11H5V13H7ZM7 9V7H5V9H7ZM21 3H3C1.9 3 1 3.9 1 5V19C1 20.1 1.9 21 3 21H21C22.1 21 23 20.1 23 19V5C23 3.9 22.1 3 21 3ZM21 19H3V5H21V19Z"
|
|
60
|
+
fill="currentColor"
|
|
61
|
+
/>
|
|
62
|
+
</svg>
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const TrashIcon = ({ size = 16 }) => (
|
|
66
|
+
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="#D92D20" strokeWidth="2" strokeLinecap="round">
|
|
67
|
+
<polyline points="3 6 5 6 21 6" />
|
|
68
|
+
<path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" />
|
|
69
|
+
<path d="M10 11v6M14 11v6" />
|
|
70
|
+
<path d="M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2" />
|
|
71
|
+
</svg>
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const CheckIcon = ({ size = 11, color = "#fff" }) => (
|
|
75
|
+
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="3" strokeLinecap="round">
|
|
76
|
+
<polyline points="20 6 9 17 4 12" />
|
|
77
|
+
</svg>
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
// ─── Reusable: Icon-prefixed input ────────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
const IconInput = ({ icon, topAligned = false, inputStyle = {}, ...props }) => (
|
|
83
|
+
<div style={{ position: "relative", width: "100%" }}>
|
|
84
|
+
<div style={{
|
|
85
|
+
position: "absolute",
|
|
86
|
+
left: "10px",
|
|
87
|
+
...(topAligned ? { top: "14px" } : { top: "50%", transform: "translateY(-50%)" }),
|
|
88
|
+
zIndex: 1,
|
|
89
|
+
opacity: 0.45,
|
|
90
|
+
display: "flex",
|
|
91
|
+
pointerEvents: "none",
|
|
92
|
+
}}>
|
|
93
|
+
{icon}
|
|
94
|
+
</div>
|
|
95
|
+
<TextInput
|
|
96
|
+
textInputStyle={{ paddingLeft: "36px", paddingRight: "12px", ...inputStyle }}
|
|
97
|
+
{...props}
|
|
98
|
+
/>
|
|
99
|
+
</div>
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
// ─── Reusable: Section heading with inline rule ───────────────────────────────
|
|
103
|
+
|
|
104
|
+
const SectionHead = ({ icon, label }) => (
|
|
105
|
+
<div style={{
|
|
106
|
+
display: "flex", alignItems: "center", gap: "8px",
|
|
107
|
+
marginBottom: "16px", marginTop: "4px",
|
|
108
|
+
}}>
|
|
109
|
+
<div style={{ opacity: 0.5, display: "flex" }}>{icon}</div>
|
|
110
|
+
<span style={{ fontSize: "15px", fontWeight: "600", color: "#0B0C0C", whiteSpace: "nowrap" }}>
|
|
111
|
+
{label}
|
|
112
|
+
</span>
|
|
113
|
+
<div style={{ flex: 1, height: "1px", background: "#EAECF0" }} />
|
|
114
|
+
</div>
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
// ─── Reusable: Admin info card ────────────────────────────────────────────────
|
|
118
|
+
|
|
119
|
+
const AdminCard = ({ bgColor, iconBg, icon, labelColor, label, value }) => (
|
|
120
|
+
<div style={{
|
|
121
|
+
backgroundColor: bgColor,
|
|
122
|
+
padding: "14px 16px",
|
|
123
|
+
borderRadius: "8px",
|
|
124
|
+
display: "flex",
|
|
125
|
+
alignItems: "center",
|
|
126
|
+
gap: "14px",
|
|
127
|
+
border: "0.5px solid #EAECF0",
|
|
128
|
+
}}>
|
|
129
|
+
<div style={{ backgroundColor: iconBg, padding: "8px", borderRadius: "8px", display: "flex", flexShrink: 0 }}>
|
|
130
|
+
{icon}
|
|
131
|
+
</div>
|
|
132
|
+
<div>
|
|
133
|
+
<div style={{ color: labelColor, fontSize: "10px", fontWeight: "600", textTransform: "uppercase", letterSpacing: "0.05em", marginBottom: "3px" }}>
|
|
134
|
+
{label}
|
|
135
|
+
</div>
|
|
136
|
+
<div style={{ fontSize: "14px", fontWeight: "600", color: "#101828" }}>{value}</div>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
// ─── Main Component ───────────────────────────────────────────────────────────
|
|
67
142
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
143
|
+
const AddressDetails = ({ isSection = false, onComplete, parentState }) => {
|
|
144
|
+
const { t } = useTranslation();
|
|
145
|
+
const history = useHistory();
|
|
146
|
+
const location = useLocation();
|
|
147
|
+
|
|
148
|
+
const flowState = parentState || location.state || {
|
|
149
|
+
kNumber: "EKYC-1234567890",
|
|
150
|
+
selectedOption: { code: "SELF", name: "EKYC_SELF" },
|
|
151
|
+
connectionDetails: null,
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const addrDetails = flowState.connectionDetails?.addressDetails || {};
|
|
155
|
+
|
|
156
|
+
const [addressType, setAddressType] = useState({ code: "AADHAAR", name: "EKYC_AADHAAR_ADDRESS" });
|
|
157
|
+
const [correctAddress, setCorrectAddress] = useState({ code: "NO", name: "CORE_COMMON_NO" });
|
|
158
|
+
const [fullAddress, setFullAddress] = useState(addrDetails.fullAddress || "");
|
|
159
|
+
const [flatNo, setFlatNo] = useState(addrDetails.flatHouseNumber || "");
|
|
160
|
+
const [building, setBuilding] = useState(addrDetails.buildingTower || "");
|
|
161
|
+
const [landmark, setLandmark] = useState(addrDetails.landmark || "");
|
|
162
|
+
const [pincode, setPincode] = useState(addrDetails.pinCode || "");
|
|
163
|
+
const [doorPhoto, setDoorPhoto] = useState(null);
|
|
164
|
+
const [isLocationFetching, setIsLocationFetching] = useState(false);
|
|
165
|
+
const fileInputRef = useRef(null);
|
|
166
|
+
|
|
167
|
+
const addressOptions = [
|
|
168
|
+
{ code: "AADHAAR", name: "EKYC_AADHAAR_ADDRESS" },
|
|
169
|
+
{ code: "OLD", name: "EKYC_OLD_ADDRESS" },
|
|
170
|
+
];
|
|
171
|
+
|
|
172
|
+
const yesNoOptions = [
|
|
173
|
+
{ code: "YES", name: "CORE_COMMON_YES" },
|
|
174
|
+
{ code: "NO", name: "CORE_COMMON_NO" },
|
|
175
|
+
];
|
|
176
|
+
|
|
177
|
+
const handleCompleteVerification = () => {
|
|
178
|
+
const payload = { addressType, fullAddress, flatNo, building, landmark, pincode, doorPhoto };
|
|
179
|
+
if (onComplete) {
|
|
180
|
+
onComplete(payload);
|
|
181
|
+
} else {
|
|
182
|
+
const { kNumber, selectedOption, connectionDetails } = flowState;
|
|
183
|
+
history.push("/digit-ui/employee/ekyc/property-info", {
|
|
184
|
+
kNumber, selectedOption, connectionDetails, addressDetails: payload,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
const handleCapture = (e) => {
|
|
190
|
+
const file = e.target.files[0];
|
|
191
|
+
if (!file) return;
|
|
192
|
+
const reader = new FileReader();
|
|
193
|
+
reader.onloadend = () => setDoorPhoto(reader.result);
|
|
194
|
+
reader.readAsDataURL(file);
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const removePhoto = () => {
|
|
198
|
+
setDoorPhoto(null);
|
|
199
|
+
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const handleUseCurrentLocation = () => {
|
|
203
|
+
if (!("geolocation" in navigator)) {
|
|
204
|
+
alert(t("GEOLOCATION_NOT_SUPPORTED") || "Geolocation is not supported by your browser");
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
setIsLocationFetching(true);
|
|
208
|
+
navigator.geolocation.getCurrentPosition(
|
|
209
|
+
async ({ coords: { latitude, longitude } }) => {
|
|
210
|
+
try {
|
|
211
|
+
const res = await fetch(
|
|
212
|
+
`https://nominatim.openstreetmap.org/reverse?format=json&lat=${latitude}&lon=${longitude}&zoom=18&addressdetails=1`
|
|
213
|
+
);
|
|
214
|
+
if (!res.ok) throw new Error("Geocode failed");
|
|
215
|
+
const data = await res.json();
|
|
216
|
+
if (data?.address) {
|
|
217
|
+
const a = data.address;
|
|
218
|
+
setFullAddress([a.amenity, a.road, a.neighbourhood, a.suburb, a.city, a.state, a.postcode].filter(Boolean).join(", "));
|
|
219
|
+
setPincode(a.postcode || "");
|
|
220
|
+
setLandmark(a.suburb || a.neighbourhood || "");
|
|
221
|
+
setFlatNo(a.amenity || "");
|
|
222
|
+
}
|
|
223
|
+
} catch (err) {
|
|
224
|
+
console.error("Reverse geocode error:", err);
|
|
225
|
+
} finally {
|
|
226
|
+
setIsLocationFetching(false);
|
|
77
227
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
`https://nominatim.openstreetmap.org/reverse?format=json&lat=${latitude}&lon=${longitude}&zoom=18&addressdetails=1`
|
|
86
|
-
);
|
|
87
|
-
if (!response.ok) throw new Error("Failed to fetch address");
|
|
88
|
-
const data = await response.json();
|
|
89
|
-
|
|
90
|
-
if (data && data.address) {
|
|
91
|
-
const addr = [
|
|
92
|
-
data.address?.amenity,
|
|
93
|
-
data.address?.road,
|
|
94
|
-
data.address?.neighbourhood,
|
|
95
|
-
data.address?.suburb,
|
|
96
|
-
data.address?.city,
|
|
97
|
-
data.address?.state,
|
|
98
|
-
data.address?.postcode
|
|
99
|
-
].filter(Boolean).join(", ");
|
|
100
|
-
|
|
101
|
-
setFullAddress(addr || "");
|
|
102
|
-
setPincode(data.address?.postcode || "");
|
|
103
|
-
setLandmark(data.address?.suburb || data.address?.neighbourhood || "");
|
|
104
|
-
setFlatNo(data.address?.amenity || "");
|
|
105
|
-
}
|
|
106
|
-
} catch (error) {
|
|
107
|
-
console.error("Error reverse geocoding:", error);
|
|
108
|
-
} finally {
|
|
109
|
-
setIsLocationFetching(false);
|
|
110
|
-
}
|
|
111
|
-
},
|
|
112
|
-
(error) => {
|
|
113
|
-
console.error("Error getting location:", error);
|
|
114
|
-
setIsLocationFetching(false);
|
|
115
|
-
alert(t("LOCATION_FETCH_FAILED") || "Failed to fetch your current location. Please ensure location permissions are granted.");
|
|
116
|
-
},
|
|
117
|
-
{ enableHighAccuracy: true, timeout: 10000, maximumAge: 0 }
|
|
118
|
-
);
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
const FlagIcon = () => (
|
|
122
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
123
|
-
<path d="M14.4 6L13.6 4H5V21H7V14H12.6L13.4 16H20V6H14.4Z" fill="#00703C" />
|
|
124
|
-
</svg>
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
const IdCardIcon = () => (
|
|
128
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
129
|
-
<path d="M2 7V17C2 18.1 2.9 19 4 19H20C21.1 19 22 18.1 22 17V7C22 5.9 21.1 5 20 5H4C2.9 5 2 5.9 2 7ZM12 11H14V13H12V11ZM12 7H14V9H12V7ZM16 11H20V13H16V11ZM16 7H20V9H16V7ZM4 7H10V15H4V7ZM20 17H4V16H20V17Z" fill="#3D51B0" />
|
|
130
|
-
</svg>
|
|
131
|
-
);
|
|
132
|
-
|
|
133
|
-
const CameraIcon = () => (
|
|
134
|
-
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
135
|
-
<path d="M9 2L7.17 4H4C2.9 4 2 4.9 2 6V18C2 19.1 2.9 20 4 20H20C21.1 20 22 19.1 22 18V6C22 4.9 21.1 4 20 4H16.83L15 2H9ZM12 17C9.24 17 7 14.76 7 12C7 9.24 9.24 7 12 7C14.76 7 17 9.24 17 12C17 14.76 14.76 17 12 17ZM12 9C10.34 9 9 10.34 9 12C9 13.66 10.34 15 12 15C13.66 15 15 13.66 15 12C15 10.34 13.66 9 12 9Z" fill="#0068faff" />
|
|
136
|
-
</svg>
|
|
137
|
-
);
|
|
138
|
-
|
|
139
|
-
const TargetIcon = () => (
|
|
140
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
141
|
-
<path d="M12 8C9.79 8 8 9.79 8 12C8 14.21 9.79 16 12 16C14.21 16 16 14.21 16 12C16 9.79 14.21 8 12 8ZM20.94 11C20.48 6.83 17.17 3.52 13 3.06V1H11V3.06C6.83 3.52 3.52 6.83 3.06 11H1V13H3.06C3.52 17.17 6.83 20.48 11 20.94V23H13V20.94C17.17 20.48 20.48 17.17 20.94 13H23V11H20.94ZM12 19C8.13 19 5 15.87 5 12C5 8.13 8.13 5 12 5C15.87 5 19 8.13 19 12C19 15.87 15.87 19 12 19Z" fill="#0068faff" />
|
|
142
|
-
</svg>
|
|
143
|
-
);
|
|
144
|
-
|
|
145
|
-
const PincodeIcon = () => (
|
|
146
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
147
|
-
<path d="M13 13V11H15V13H13ZM13 9V7H15V9H13ZM17 13V11H19V13H17ZM17 9V7H19V9H17ZM11 13V11H9V13H11ZM11 9V7H9V9H11ZM7 13V11H5V13H7ZM7 9V7H5V9H7ZM21 3H3C1.9 3 1 3.9 1 5V19C1 20.1 1.9 21 3 21H21C22.1 21 23 20.1 23 19V5C23 3.9 22.1 3 21 3ZM21 19H3V5H21V19Z" fill="#0068faff" />
|
|
148
|
-
</svg>
|
|
228
|
+
},
|
|
229
|
+
(err) => {
|
|
230
|
+
console.error("Geolocation error:", err);
|
|
231
|
+
setIsLocationFetching(false);
|
|
232
|
+
alert(t("LOCATION_FETCH_FAILED") || "Failed to fetch location. Please grant location permissions.");
|
|
233
|
+
},
|
|
234
|
+
{ enableHighAccuracy: true, timeout: 10000, maximumAge: 0 }
|
|
149
235
|
);
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
const renderContent = () => (
|
|
239
|
+
<div style={{ animation: "fadeSlideIn 0.3s ease" }}>
|
|
240
|
+
|
|
241
|
+
{/* ── Address Type Toggle ── */}
|
|
242
|
+
<SectionHead
|
|
243
|
+
icon={<LocationIcon className="icon" styles={{ fill: "#0B0C0C", width: "16px", height: "16px" }} />}
|
|
244
|
+
label={t("EKYC_ADDRESS_DETAILS_HEADER") || "Address Details"}
|
|
245
|
+
/>
|
|
246
|
+
|
|
247
|
+
<div style={{ marginBottom: "20px" }}>
|
|
248
|
+
<RadioButtons
|
|
249
|
+
options={addressOptions}
|
|
250
|
+
optionsKey="name"
|
|
251
|
+
selectedOption={addressType}
|
|
252
|
+
onSelect={setAddressType}
|
|
253
|
+
t={t}
|
|
254
|
+
innerStyles={{ display: "flex", alignItems: "center" }}
|
|
255
|
+
style={{ display: "flex", gap: "40px" }}
|
|
256
|
+
/>
|
|
257
|
+
</div>
|
|
258
|
+
|
|
259
|
+
{/* ── Aadhaar Address display ── */}
|
|
260
|
+
{addressType.code === "AADHAAR" && (
|
|
261
|
+
<div style={{
|
|
262
|
+
backgroundColor: "#E1F5EE",
|
|
263
|
+
border: "0.5px solid #5DCAA5",
|
|
264
|
+
borderRadius: "8px",
|
|
265
|
+
padding: "14px 16px",
|
|
266
|
+
display: "flex",
|
|
267
|
+
alignItems: "flex-start",
|
|
268
|
+
gap: "12px",
|
|
269
|
+
marginBottom: "20px",
|
|
270
|
+
animation: "fadeSlideIn 0.3s ease",
|
|
271
|
+
}}>
|
|
272
|
+
<div style={{ backgroundColor: "#9FE1CB", padding: "6px", borderRadius: "6px", display: "flex", flexShrink: 0 }}>
|
|
273
|
+
<LocationIcon className="icon" styles={{ fill: "#085041", width: "16px", height: "16px" }} />
|
|
274
|
+
</div>
|
|
275
|
+
<div style={{ fontSize: "14px", lineHeight: "1.6", color: "#04342C", fontWeight: "500" }}>
|
|
276
|
+
{addrDetails.fullAddress || "H.No. 123, Sector 15, Rohini, Delhi – 110085"}
|
|
277
|
+
</div>
|
|
278
|
+
</div>
|
|
279
|
+
)}
|
|
150
280
|
|
|
151
|
-
|
|
281
|
+
{/* ── Old / Custom Address ── */}
|
|
282
|
+
{addressType.code === "OLD" && (
|
|
152
283
|
<div style={{ animation: "fadeSlideIn 0.3s ease" }}>
|
|
153
|
-
{isSection && <hr style={{ margin: "40px 0", border: "0", borderTop: "2px solid #EAECF0" }} />}
|
|
154
|
-
<Header style={{ marginBottom: "24px" }}>{t("EKYC_ADDRESS_DETAILS_HEADER") || "Address Details"}</Header>
|
|
155
|
-
<div style={{ marginBottom: "32px" }}>
|
|
156
|
-
<RadioButtons
|
|
157
|
-
options={addressOptions}
|
|
158
|
-
optionsKey="name"
|
|
159
|
-
selectedOption={addressType}
|
|
160
|
-
onSelect={setAddressType}
|
|
161
|
-
t={t}
|
|
162
|
-
innerStyles={{ display: "flex", alignItems: "center" }}
|
|
163
|
-
style={{ display: "flex", gap: "50px", justifyContent: "flex-start" }}
|
|
164
|
-
/>
|
|
165
|
-
</div>
|
|
166
|
-
|
|
167
|
-
{addressType.code === "AADHAAR" && (
|
|
168
|
-
<div style={{ backgroundColor: "#F9FAFB", padding: "16px", borderRadius: "12px", marginBottom: "24px", border: "1px solid #EAECF0", display: "flex", alignItems: "flex-start", gap: "12px", animation: "fadeSlideIn 0.3s ease" }}>
|
|
169
|
-
<div style={{ backgroundColor: "#E7F4EE", padding: "8px", borderRadius: "8px" }}>
|
|
170
|
-
<LocationIcon className="icon" styles={{ fill: "#00703C", width: "20px", height: "20px" }} />
|
|
171
|
-
</div>
|
|
172
|
-
<div style={{ fontSize: "16px", lineHeight: "1.6", color: "#344054", fontWeight: "500" }}>
|
|
173
|
-
H.No. 123, Sector 15, Rohini<br />
|
|
174
|
-
Delhi - 110085
|
|
175
|
-
</div>
|
|
176
|
-
</div>
|
|
177
|
-
)}
|
|
178
284
|
|
|
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
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
<TextInput
|
|
235
|
-
value={fullAddress}
|
|
236
|
-
onChange={(e) => setFullAddress(e.target.value)}
|
|
237
|
-
placeholder={t("EKYC_ENTER_FULL_ADDRESS") || "Enter Full Address"}
|
|
238
|
-
textInputStyle={{ paddingLeft: "40px", minHeight: "80px" }}
|
|
239
|
-
/>
|
|
240
|
-
</div>
|
|
241
|
-
</LabelFieldPair>
|
|
242
|
-
|
|
243
|
-
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "24px" }}>
|
|
244
|
-
<LabelFieldPair>
|
|
245
|
-
<CardLabel style={{ fontWeight: "600" }}>{t("EKYC_FLAT_HOUSE_NUMBER") || "Flat/House Number"}</CardLabel>
|
|
246
|
-
<div className="field" style={{ position: "relative" }}>
|
|
247
|
-
<div style={{ position: "absolute", left: "12px", top: "50%", transform: "translateY(-50%)", zIndex: 1, opacity: 0.6 }}>
|
|
248
|
-
<PropertyHouse styles={{ fill: "#0068faff", width: "20px", height: "20px" }} />
|
|
249
|
-
</div>
|
|
250
|
-
<TextInput
|
|
251
|
-
value={flatNo}
|
|
252
|
-
onChange={(e) => setFlatNo(e.target.value)}
|
|
253
|
-
placeholder={t("EKYC_ENTER_FLAT_NO") || "e.g. 45-B"}
|
|
254
|
-
textInputStyle={{ paddingLeft: "40px" }}
|
|
255
|
-
/>
|
|
256
|
-
</div>
|
|
257
|
-
</LabelFieldPair>
|
|
258
|
-
<LabelFieldPair>
|
|
259
|
-
<CardLabel style={{ fontWeight: "600" }}>{t("EKYC_BUILDING_TOWER") || "Building/Tower"}</CardLabel>
|
|
260
|
-
<div className="field" style={{ position: "relative" }}>
|
|
261
|
-
<div style={{ position: "absolute", left: "12px", top: "50%", transform: "translateY(-50%)", zIndex: 1, opacity: 0.6 }}>
|
|
262
|
-
<PropertyHouse styles={{ fill: "#0068faff", width: "20px", height: "20px" }} />
|
|
263
|
-
</div>
|
|
264
|
-
<TextInput
|
|
265
|
-
value={building}
|
|
266
|
-
onChange={(e) => setBuilding(e.target.value)}
|
|
267
|
-
placeholder={t("EKYC_ENTER_BUILDING") || "e.g. Tower 4"}
|
|
268
|
-
textInputStyle={{ paddingLeft: "40px" }}
|
|
269
|
-
/>
|
|
270
|
-
</div>
|
|
271
|
-
</LabelFieldPair>
|
|
272
|
-
</div>
|
|
273
|
-
|
|
274
|
-
<LabelFieldPair>
|
|
275
|
-
<CardLabel style={{ fontWeight: "600" }}>{t("EKYC_LANDMARK") || "Landmark"}</CardLabel>
|
|
276
|
-
<div className="field" style={{ position: "relative" }}>
|
|
277
|
-
<div style={{ position: "absolute", left: "12px", top: "50%", transform: "translateY(-50%)", zIndex: 1, opacity: 0.6 }}>
|
|
278
|
-
<LocationIcon className="icon" styles={{ fill: "#0068faff", width: "20px", height: "20px" }} />
|
|
279
|
-
</div>
|
|
280
|
-
<TextInput
|
|
281
|
-
value={landmark}
|
|
282
|
-
onChange={(e) => setLandmark(e.target.value)}
|
|
283
|
-
placeholder={t("EKYC_ENTER_LANDMARK") || "Near Central Park"}
|
|
284
|
-
textInputStyle={{ paddingLeft: "40px" }}
|
|
285
|
-
/>
|
|
286
|
-
</div>
|
|
287
|
-
</LabelFieldPair>
|
|
288
|
-
|
|
289
|
-
<LabelFieldPair>
|
|
290
|
-
<CardLabel style={{ fontWeight: "600" }}>{t("EKYC_PINCODE") || "Pincode"}</CardLabel>
|
|
291
|
-
<div className="field" style={{ position: "relative" }}>
|
|
292
|
-
<div style={{ position: "absolute", left: "12px", top: "50%", transform: "translateY(-50%)", zIndex: 1, opacity: 0.6 }}>
|
|
293
|
-
<PincodeIcon />
|
|
294
|
-
</div>
|
|
295
|
-
<TextInput
|
|
296
|
-
value={pincode}
|
|
297
|
-
onChange={(e) => setPincode(e.target.value)}
|
|
298
|
-
placeholder={t("EKYC_ENTER_PINCODE") || "6-digit pincode"}
|
|
299
|
-
textInputStyle={{ paddingLeft: "40px" }}
|
|
300
|
-
maxLength={6}
|
|
301
|
-
/>
|
|
302
|
-
</div>
|
|
303
|
-
</LabelFieldPair>
|
|
304
|
-
</div>
|
|
285
|
+
{/* Correction toggle */}
|
|
286
|
+
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: "14px" }}>
|
|
287
|
+
<CardLabel style={{ fontWeight: "500", marginBottom: 0, fontSize: "13px", color: "#505A5F" }}>
|
|
288
|
+
{t("EKYC_ADDRESS_CORRECTION_PROMPT") || "Correct the address?"}
|
|
289
|
+
</CardLabel>
|
|
290
|
+
<RadioButtons
|
|
291
|
+
options={yesNoOptions}
|
|
292
|
+
optionsKey="name"
|
|
293
|
+
selectedOption={correctAddress}
|
|
294
|
+
onSelect={setCorrectAddress}
|
|
295
|
+
t={t}
|
|
296
|
+
innerStyles={{ display: "flex", gap: "20px" }}
|
|
297
|
+
style={{ marginBottom: 0 }}
|
|
298
|
+
/>
|
|
299
|
+
</div>
|
|
300
|
+
|
|
301
|
+
{/* Use Current Location */}
|
|
302
|
+
<div
|
|
303
|
+
onClick={!isLocationFetching ? handleUseCurrentLocation : undefined}
|
|
304
|
+
style={{
|
|
305
|
+
border: "0.5px solid #D0D5DD",
|
|
306
|
+
borderRadius: "8px",
|
|
307
|
+
padding: "12px 16px",
|
|
308
|
+
display: "flex",
|
|
309
|
+
alignItems: "center",
|
|
310
|
+
justifyContent: "space-between",
|
|
311
|
+
marginBottom: "20px",
|
|
312
|
+
cursor: isLocationFetching ? "not-allowed" : "pointer",
|
|
313
|
+
backgroundColor: isLocationFetching ? "#F9FAFB" : "#fff",
|
|
314
|
+
transition: "background 0.15s",
|
|
315
|
+
opacity: isLocationFetching ? 0.7 : 1,
|
|
316
|
+
}}
|
|
317
|
+
onMouseOver={(e) => { if (!isLocationFetching) e.currentTarget.style.background = "#F9FAFB"; }}
|
|
318
|
+
onMouseOut={(e) => { if (!isLocationFetching) e.currentTarget.style.background = "#fff"; }}
|
|
319
|
+
>
|
|
320
|
+
<div style={{ display: "flex", alignItems: "center", gap: "12px" }}>
|
|
321
|
+
<div style={{ backgroundColor: "#E6F1FB", padding: "7px", borderRadius: "7px", display: "flex" }}>
|
|
322
|
+
{isLocationFetching ? (
|
|
323
|
+
<div style={{
|
|
324
|
+
width: "18px", height: "18px", border: "2px solid #185FA5",
|
|
325
|
+
borderTopColor: "transparent", borderRadius: "50%",
|
|
326
|
+
animation: "spin 1s linear infinite",
|
|
327
|
+
}} />
|
|
328
|
+
) : (
|
|
329
|
+
<TargetIcon size={18} />
|
|
330
|
+
)}
|
|
331
|
+
</div>
|
|
332
|
+
<span style={{ fontWeight: "500", fontSize: "14px", color: "#344054" }}>
|
|
333
|
+
{isLocationFetching
|
|
334
|
+
? t("EKYC_FETCHING_LOCATION") || "Fetching location..."
|
|
335
|
+
: t("EKYC_USE_CURRENT_LOCATION") || "Use current location"}
|
|
336
|
+
</span>
|
|
337
|
+
</div>
|
|
338
|
+
{!isLocationFetching && (
|
|
339
|
+
<span style={{ fontSize: "18px", color: "#98A2B3", lineHeight: 1 }}>›</span>
|
|
305
340
|
)}
|
|
341
|
+
</div>
|
|
306
342
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
<div style={{
|
|
310
|
-
|
|
311
|
-
<PropertyHouse styles={{ fill: "#0068faff", width: "24px", height: "24px" }} />
|
|
312
|
-
</div>
|
|
313
|
-
<CardHeader style={{ margin: 0, fontSize: "20px" }}>{t("EKYC_ADMINISTRATIVE_DIVISION") || "Administrative Division"}</CardHeader>
|
|
343
|
+
{/* Full Address (textarea-style) */}
|
|
344
|
+
<div style={{ marginBottom: "14px" }}>
|
|
345
|
+
<div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
|
|
346
|
+
{t("EKYC_FULL_ADDRESS") || "Full address"}
|
|
314
347
|
</div>
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
348
|
+
<IconInput
|
|
349
|
+
icon={<PropertyHouse styles={{ fill: "#0068fa", width: "15px", height: "15px" }} />}
|
|
350
|
+
topAligned
|
|
351
|
+
value={fullAddress}
|
|
352
|
+
onChange={(e) => setFullAddress(e.target.value)}
|
|
353
|
+
placeholder={t("EKYC_ENTER_FULL_ADDRESS") || "Enter full address"}
|
|
354
|
+
inputStyle={{ minHeight: "72px" }}
|
|
355
|
+
/>
|
|
356
|
+
</div>
|
|
357
|
+
|
|
358
|
+
{/* Flat + Building */}
|
|
359
|
+
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "14px", marginBottom: "14px" }}>
|
|
360
|
+
<div>
|
|
361
|
+
<div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
|
|
362
|
+
{t("EKYC_FLAT_HOUSE_NUMBER") || "Flat / House no."}
|
|
363
|
+
</div>
|
|
364
|
+
<IconInput
|
|
365
|
+
icon={<PropertyHouse styles={{ fill: "#0068fa", width: "15px", height: "15px" }} />}
|
|
366
|
+
value={flatNo}
|
|
367
|
+
onChange={(e) => setFlatNo(e.target.value)}
|
|
368
|
+
placeholder={t("EKYC_ENTER_FLAT_NO") || "e.g. 45-B"}
|
|
369
|
+
/>
|
|
335
370
|
</div>
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
<
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
371
|
+
<div>
|
|
372
|
+
<div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
|
|
373
|
+
{t("EKYC_BUILDING_TOWER") || "Building / Tower"}
|
|
374
|
+
</div>
|
|
375
|
+
<IconInput
|
|
376
|
+
icon={<PropertyHouse styles={{ fill: "#0068fa", width: "15px", height: "15px" }} />}
|
|
377
|
+
value={building}
|
|
378
|
+
onChange={(e) => setBuilding(e.target.value)}
|
|
379
|
+
placeholder={t("EKYC_ENTER_BUILDING") || "e.g. Tower 4"}
|
|
380
|
+
/>
|
|
346
381
|
</div>
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
justifyContent: "center",
|
|
362
|
-
backgroundColor: "#F9FAFB",
|
|
363
|
-
transition: "all 0.2s ease",
|
|
364
|
-
boxShadow: "inset 0px 2px 4px rgba(0, 0, 0, 0.02)"
|
|
365
|
-
}}
|
|
366
|
-
onClick={!doorPhoto ? openGallery : undefined}
|
|
367
|
-
onMouseOver={(e) => !doorPhoto ? e.currentTarget.style.borderColor = "#0068faff" : null}
|
|
368
|
-
onMouseOut={(e) => !doorPhoto ? e.currentTarget.style.borderColor = "#D0D5DD" : null}
|
|
369
|
-
>
|
|
370
|
-
<input
|
|
371
|
-
type="file"
|
|
372
|
-
ref={fileInputRef}
|
|
373
|
-
onChange={handleCapture}
|
|
374
|
-
accept="image/*"
|
|
375
|
-
style={{ display: "none" }}
|
|
376
|
-
/>
|
|
377
|
-
{!doorPhoto ? (
|
|
378
|
-
<>
|
|
379
|
-
<div style={{ backgroundColor: "#FFFFFF", width: "64px", height: "64px", borderRadius: "50%", display: "flex", alignItems: "center", justifyContent: "center", margin: "0 auto 16px", boxShadow: "0px 1px 3px rgba(16, 24, 40, 0.1)" }}>
|
|
380
|
-
<CameraIcon />
|
|
381
|
-
</div>
|
|
382
|
-
<div style={{ fontWeight: "700", fontSize: "16px", marginBottom: "4px", color: "#101828" }}>{t("EKYC_TAP_TO_CAPTURE") || "Tap to Capture"}</div>
|
|
383
|
-
<div style={{ color: "#667085", fontSize: "14px" }}>{t("EKYC_CAPTURE_DOOR_IMAGE") || "Capture Door Image"}</div>
|
|
384
|
-
</>
|
|
385
|
-
) : (
|
|
386
|
-
<div style={{ position: "relative", width: "100%", height: "100%", display: "flex", justifyContent: "center" }}>
|
|
387
|
-
<img src={doorPhoto} alt="Door" style={{ width: "100%", maxHeight: "300px", objectFit: "cover", borderRadius: "12px", display: "block" }} />
|
|
388
|
-
<div style={{ position: "absolute", top: "12px", right: "12px" }}>
|
|
389
|
-
<button
|
|
390
|
-
onClick={(e) => { e.stopPropagation(); removePhoto(); }}
|
|
391
|
-
style={{ background: "#FFFFFF", border: "1px solid #EAECF0", borderRadius: "8px", padding: "8px", display: "flex", boxShadow: "0px 1px 2px rgba(16, 24, 40, 0.05)", cursor: "pointer" }}
|
|
392
|
-
>
|
|
393
|
-
<RemoveableTag text="" onClick={() => { }} extraStyles={{ tagStyles: { margin: 0, padding: 0 } }} />
|
|
394
|
-
</button>
|
|
395
|
-
</div>
|
|
396
|
-
</div>
|
|
397
|
-
)}
|
|
382
|
+
</div>
|
|
383
|
+
|
|
384
|
+
{/* Landmark + Pincode */}
|
|
385
|
+
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "14px", marginBottom: "4px" }}>
|
|
386
|
+
<div>
|
|
387
|
+
<div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
|
|
388
|
+
{t("EKYC_LANDMARK") || "Landmark"}
|
|
389
|
+
</div>
|
|
390
|
+
<IconInput
|
|
391
|
+
icon={<LocationIcon className="icon" styles={{ fill: "#0068fa", width: "15px", height: "15px" }} />}
|
|
392
|
+
value={landmark}
|
|
393
|
+
onChange={(e) => setLandmark(e.target.value)}
|
|
394
|
+
placeholder={t("EKYC_ENTER_LANDMARK") || "Near Central Park"}
|
|
395
|
+
/>
|
|
398
396
|
</div>
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
397
|
+
<div>
|
|
398
|
+
<div style={{ fontSize: "11px", fontWeight: "600", color: "#667085", textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: "6px" }}>
|
|
399
|
+
{t("EKYC_PINCODE") || "Pincode"}
|
|
400
|
+
</div>
|
|
401
|
+
<IconInput
|
|
402
|
+
icon={<PincodeIcon size={15} />}
|
|
403
|
+
value={pincode}
|
|
404
|
+
onChange={(e) => { if (/^\d*$/.test(e.target.value)) setPincode(e.target.value); }}
|
|
405
|
+
placeholder={t("EKYC_ENTER_PINCODE") || "6-digit pincode"}
|
|
406
|
+
maxLength={6}
|
|
407
|
+
/>
|
|
408
|
+
</div>
|
|
409
|
+
</div>
|
|
403
410
|
</div>
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
411
|
+
)}
|
|
412
|
+
|
|
413
|
+
<hr style={{ margin: "24px 0", border: 0, borderTop: "1px solid #EAECF0" }} />
|
|
414
|
+
|
|
415
|
+
{/* ── Administrative Division ── */}
|
|
416
|
+
<SectionHead
|
|
417
|
+
icon={<PropertyHouse styles={{ fill: "#0B0C0C", width: "16px", height: "16px" }} />}
|
|
418
|
+
label={t("EKYC_ADMINISTRATIVE_DIVISION") || "Administrative Division"}
|
|
419
|
+
/>
|
|
420
|
+
|
|
421
|
+
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "14px", marginBottom: "24px" }}>
|
|
422
|
+
<AdminCard
|
|
423
|
+
bgColor="#E1F5EE"
|
|
424
|
+
iconBg="#9FE1CB"
|
|
425
|
+
icon={<FlagIcon size={18} />}
|
|
426
|
+
labelColor="#0F6E56"
|
|
427
|
+
label={t("EKYC_ASSEMBLY") || "Assembly"}
|
|
428
|
+
value={addrDetails.assembly || "AC-12 Chandni Chowk"}
|
|
429
|
+
/>
|
|
430
|
+
<AdminCard
|
|
431
|
+
bgColor="#E6F1FB"
|
|
432
|
+
iconBg="#B5D4F4"
|
|
433
|
+
icon={<IdCardIcon size={18} />}
|
|
434
|
+
labelColor="#185FA5"
|
|
435
|
+
label={t("EKYC_WARD") || "Ward"}
|
|
436
|
+
value={addrDetails.ward || "WARD-45 Civil Lines"}
|
|
437
|
+
/>
|
|
438
|
+
</div>
|
|
439
|
+
|
|
440
|
+
<hr style={{ margin: "24px 0", border: 0, borderTop: "1px solid #EAECF0" }} />
|
|
441
|
+
|
|
442
|
+
{/* ── Door Photo ── */}
|
|
443
|
+
<SectionHead
|
|
444
|
+
icon={<CameraIcon size={16} />}
|
|
445
|
+
label={t("EKYC_DOOR_PHOTO_HEADER") || "Door photo with GPS stamp"}
|
|
446
|
+
/>
|
|
447
|
+
|
|
448
|
+
<div style={{ fontSize: "12px", color: "#667085", marginBottom: "12px" }}>
|
|
449
|
+
{t("EKYC_REQUIRED_FOR_VERIFICATION") || "Required for verification"}
|
|
450
|
+
</div>
|
|
451
|
+
|
|
452
|
+
{/* Warning banner */}
|
|
453
|
+
<div style={{
|
|
454
|
+
backgroundColor: "#FFFAEB",
|
|
455
|
+
border: "0.5px solid #FEDF89",
|
|
456
|
+
borderRadius: "8px",
|
|
457
|
+
padding: "12px 14px",
|
|
458
|
+
display: "flex",
|
|
459
|
+
alignItems: "flex-start",
|
|
460
|
+
gap: "10px",
|
|
461
|
+
marginBottom: "16px",
|
|
462
|
+
}}>
|
|
463
|
+
<div style={{ flexShrink: 0, marginTop: "1px" }}>
|
|
464
|
+
<InfoBannerIcon fill="#B54708" />
|
|
465
|
+
</div>
|
|
466
|
+
<div>
|
|
467
|
+
<div style={{ fontWeight: "600", color: "#B54708", fontSize: "13px", marginBottom: "2px" }}>
|
|
468
|
+
{t("EKYC_IMPORTANT") || "Important"}
|
|
469
|
+
</div>
|
|
470
|
+
<div style={{ fontSize: "12px", color: "#92400E" }}>
|
|
471
|
+
{t("EKYC_CAPTURE_LIVE_CAMERA") || "Capture with live camera for GPS metadata"}
|
|
472
|
+
</div>
|
|
473
|
+
</div>
|
|
474
|
+
</div>
|
|
475
|
+
|
|
476
|
+
{/* Drop zone */}
|
|
477
|
+
<input
|
|
478
|
+
type="file"
|
|
479
|
+
ref={fileInputRef}
|
|
480
|
+
onChange={handleCapture}
|
|
481
|
+
accept="image/*"
|
|
482
|
+
style={{ display: "none" }}
|
|
483
|
+
/>
|
|
484
|
+
<div
|
|
485
|
+
onClick={!doorPhoto ? () => fileInputRef.current.click() : undefined}
|
|
486
|
+
onMouseOver={(e) => { if (!doorPhoto) e.currentTarget.style.borderColor = "#185FA5"; }}
|
|
487
|
+
onMouseOut={(e) => { if (!doorPhoto) e.currentTarget.style.borderColor = "#D0D5DD"; }}
|
|
488
|
+
style={{
|
|
489
|
+
border: "1.5px dashed #D0D5DD",
|
|
490
|
+
borderRadius: "10px",
|
|
491
|
+
minHeight: "160px",
|
|
492
|
+
display: "flex",
|
|
493
|
+
flexDirection: "column",
|
|
494
|
+
alignItems: "center",
|
|
495
|
+
justifyContent: "center",
|
|
496
|
+
backgroundColor: "#F9FAFB",
|
|
497
|
+
cursor: doorPhoto ? "default" : "pointer",
|
|
498
|
+
overflow: "hidden",
|
|
499
|
+
transition: "border-color 0.15s",
|
|
500
|
+
position: "relative",
|
|
501
|
+
padding: doorPhoto ? "0" : "32px 24px",
|
|
502
|
+
}}
|
|
503
|
+
>
|
|
504
|
+
{!doorPhoto ? (
|
|
505
|
+
<>
|
|
506
|
+
<div style={{
|
|
507
|
+
width: "52px", height: "52px", borderRadius: "50%",
|
|
508
|
+
background: "#E6F1FB", display: "flex",
|
|
509
|
+
alignItems: "center", justifyContent: "center", marginBottom: "12px",
|
|
510
|
+
}}>
|
|
511
|
+
<CameraIcon size={26} />
|
|
435
512
|
</div>
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
<div style={{ fontSize: "14px", fontWeight: "700", color: "#505A5F" }}>
|
|
442
|
-
{t("EKYC_K_NUMBER")}: <span style={{ color: "#0B0C0C" }}>{flowState?.kNumber}</span>
|
|
443
|
-
</div>
|
|
444
|
-
</div>
|
|
445
|
-
{renderContent()}
|
|
446
|
-
</Card>
|
|
513
|
+
<div style={{ fontWeight: "600", fontSize: "14px", color: "#101828", marginBottom: "4px" }}>
|
|
514
|
+
{t("EKYC_TAP_TO_CAPTURE") || "Tap to capture"}
|
|
515
|
+
</div>
|
|
516
|
+
<div style={{ fontSize: "12px", color: "#667085" }}>
|
|
517
|
+
{t("EKYC_CAPTURE_DOOR_IMAGE") || "Capture door image"}
|
|
447
518
|
</div>
|
|
519
|
+
</>
|
|
520
|
+
) : (
|
|
521
|
+
<>
|
|
522
|
+
<img
|
|
523
|
+
src={doorPhoto}
|
|
524
|
+
alt="Door"
|
|
525
|
+
style={{ width: "100%", maxHeight: "280px", objectFit: "cover", display: "block" }}
|
|
526
|
+
/>
|
|
527
|
+
<button
|
|
528
|
+
onClick={(e) => { e.stopPropagation(); removePhoto(); }}
|
|
529
|
+
style={{
|
|
530
|
+
position: "absolute", top: "10px", right: "10px",
|
|
531
|
+
background: "#fff", border: "0.5px solid #EAECF0",
|
|
532
|
+
borderRadius: "7px", padding: "6px 10px",
|
|
533
|
+
display: "flex", alignItems: "center", gap: "5px",
|
|
534
|
+
cursor: "pointer", fontSize: "12px", color: "#D92D20", fontWeight: "500",
|
|
535
|
+
}}
|
|
536
|
+
>
|
|
537
|
+
<TrashIcon size={13} /> {t("EKYC_REMOVE") || "Remove"}
|
|
538
|
+
</button>
|
|
539
|
+
</>
|
|
540
|
+
)}
|
|
541
|
+
</div>
|
|
542
|
+
|
|
543
|
+
{/* Submit */}
|
|
544
|
+
{isSection ? (
|
|
545
|
+
<div style={{ marginTop: "24px" }}>
|
|
546
|
+
<SubmitBar
|
|
547
|
+
label={t("EKYC_COMPLETE_VERIFICATION_AND_PROCEED") || "Complete & Proceed"}
|
|
548
|
+
onSubmit={handleCompleteVerification}
|
|
549
|
+
/>
|
|
448
550
|
</div>
|
|
551
|
+
) : (
|
|
552
|
+
<ActionBar>
|
|
553
|
+
<SubmitBar
|
|
554
|
+
label={t("EKYC_COMPLETE_VERIFICATION") || "Complete Verification"}
|
|
555
|
+
onSubmit={handleCompleteVerification}
|
|
556
|
+
/>
|
|
557
|
+
</ActionBar>
|
|
558
|
+
)}
|
|
559
|
+
|
|
560
|
+
{/* Secure notice */}
|
|
561
|
+
<div style={{
|
|
562
|
+
display: "flex", alignItems: "center", justifyContent: "center",
|
|
563
|
+
gap: "5px", marginTop: "16px",
|
|
564
|
+
fontSize: "11px", color: "#98A2B3",
|
|
565
|
+
}}>
|
|
566
|
+
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
567
|
+
<rect x="3" y="11" width="18" height="11" rx="2" />
|
|
568
|
+
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
|
|
569
|
+
</svg>
|
|
570
|
+
{t("EKYC_SECURE_DATA_NOTICE") || "Your data is encrypted and secure"}
|
|
571
|
+
</div>
|
|
572
|
+
</div>
|
|
573
|
+
);
|
|
574
|
+
|
|
575
|
+
// ── When rendered as inline section inside AadhaarVerification ──
|
|
576
|
+
if (isSection) {
|
|
577
|
+
return (
|
|
578
|
+
<Fragment>
|
|
579
|
+
<hr style={{ margin: "32px 0", border: 0, borderTop: "2px solid #EAECF0" }} />
|
|
580
|
+
{renderContent()}
|
|
581
|
+
</Fragment>
|
|
449
582
|
);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// ── When rendered as a standalone page ──
|
|
586
|
+
return (
|
|
587
|
+
<div className="inbox-container">
|
|
588
|
+
<style>{`
|
|
589
|
+
@keyframes spin { to { transform: rotate(360deg); } }
|
|
590
|
+
@keyframes fadeSlideIn { from { opacity:0; transform:translateY(8px); } to { opacity:1; transform:translateY(0); } }
|
|
591
|
+
`}</style>
|
|
592
|
+
|
|
593
|
+
{/* Sidebar */}
|
|
594
|
+
<div className="filters-container">
|
|
595
|
+
<Card style={{ display: "flex", alignItems: "center", padding: "12px 16px", marginBottom: "12px", borderRadius: "8px" }}>
|
|
596
|
+
<div style={{ color: "#185FA5", marginRight: "10px", display: "flex" }}>
|
|
597
|
+
<HomeIcon style={{ width: "20px", height: "20px" }} />
|
|
598
|
+
</div>
|
|
599
|
+
<div style={{ fontWeight: "600", fontSize: "15px", color: "#0B0C0C" }}>
|
|
600
|
+
{t("EKYC_PROCESS") || "eKYC Process"}
|
|
601
|
+
</div>
|
|
602
|
+
</Card>
|
|
603
|
+
|
|
604
|
+
<div style={{ background: "#fff", padding: "16px 14px", borderRadius: "8px", border: "1px solid #EAECF0" }}>
|
|
605
|
+
{[
|
|
606
|
+
{ label: t("EKYC_STEP_AADHAAR") || "Aadhaar", done: true, active: false },
|
|
607
|
+
{ label: t("EKYC_STEP_ADDRESS") || "Address", done: false, active: true },
|
|
608
|
+
{ label: t("EKYC_STEP_PROPERTY") || "Property", done: false, active: false },
|
|
609
|
+
{ label: t("EKYC_STEP_REVIEW") || "Review", done: false, active: false },
|
|
610
|
+
].map((step, i) => (
|
|
611
|
+
<div key={i} style={{ display: "flex", gap: "10px", alignItems: "flex-start", position: "relative", paddingBottom: i < 3 ? "18px" : 0 }}>
|
|
612
|
+
{i < 3 && (
|
|
613
|
+
<div style={{ position: "absolute", left: "10px", top: "22px", width: "1px", height: "calc(100% - 10px)", background: "#EAECF0" }} />
|
|
614
|
+
)}
|
|
615
|
+
<div style={{
|
|
616
|
+
width: "20px", height: "20px", borderRadius: "50%", flexShrink: 0, marginTop: "1px",
|
|
617
|
+
border: step.done ? "none" : step.active ? "1.5px solid #185FA5" : "1.5px solid #D0D5DD",
|
|
618
|
+
background: step.done ? "#0F6E56" : step.active ? "#E6F1FB" : "#fff",
|
|
619
|
+
display: "flex", alignItems: "center", justifyContent: "center",
|
|
620
|
+
fontSize: "10px", fontWeight: "500",
|
|
621
|
+
color: step.done ? "#fff" : step.active ? "#185FA5" : "#98A2B3",
|
|
622
|
+
}}>
|
|
623
|
+
{step.done ? <CheckIcon size={11} color="#fff" /> : i + 1}
|
|
624
|
+
</div>
|
|
625
|
+
<div style={{
|
|
626
|
+
fontSize: "12px", paddingTop: "2px",
|
|
627
|
+
color: step.done ? "#0F6E56" : step.active ? "#0B0C0C" : "#667085",
|
|
628
|
+
fontWeight: step.done || step.active ? "600" : "400",
|
|
629
|
+
}}>
|
|
630
|
+
{step.label}
|
|
631
|
+
</div>
|
|
632
|
+
</div>
|
|
633
|
+
))}
|
|
634
|
+
</div>
|
|
635
|
+
</div>
|
|
636
|
+
|
|
637
|
+
{/* Main */}
|
|
638
|
+
<div style={{ flex: 1, marginLeft: "16px" }}>
|
|
639
|
+
<Card>
|
|
640
|
+
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "20px" }}>
|
|
641
|
+
<CardHeader style={{ margin: 0, fontSize: "18px" }}>
|
|
642
|
+
{t("EKYC_ADDRESS_DETAILS_HEADER") || "Address Details"}
|
|
643
|
+
</CardHeader>
|
|
644
|
+
<div style={{
|
|
645
|
+
background: "#F9FAFB", border: "0.5px solid #EAECF0",
|
|
646
|
+
borderRadius: "20px", padding: "4px 14px",
|
|
647
|
+
fontSize: "12px", color: "#667085",
|
|
648
|
+
}}>
|
|
649
|
+
{t("EKYC_K_NUMBER") || "K Number"}:{" "}
|
|
650
|
+
<span style={{ color: "#0B0C0C", fontWeight: "600" }}>{flowState?.kNumber}</span>
|
|
651
|
+
</div>
|
|
652
|
+
</div>
|
|
653
|
+
{renderContent()}
|
|
654
|
+
</Card>
|
|
655
|
+
</div>
|
|
656
|
+
</div>
|
|
657
|
+
);
|
|
450
658
|
};
|
|
451
659
|
|
|
452
|
-
export default AddressDetails;
|
|
660
|
+
export default AddressDetails;
|