@djb25/digit-ui-module-ekyc 1.0.3 → 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.
@@ -1,6 +1,5 @@
1
1
  import React, { useState, useRef, Fragment } from "react";
2
2
  import {
3
- Header,
4
3
  Card,
5
4
  LabelFieldPair,
6
5
  CardLabel,
@@ -9,10 +8,7 @@ import {
9
8
  CardHeader,
10
9
  RadioButtons,
11
10
  ActionBar,
12
- TickMark,
13
11
  HomeIcon,
14
- StatusTable,
15
- Row,
16
12
  ConnectingCheckPoints,
17
13
  CheckPoint,
18
14
  } from "@djb25/digit-ui-react-components";
@@ -20,67 +16,127 @@ import { useTranslation } from "react-i18next";
20
16
  import { useLocation, useHistory } from "react-router-dom";
21
17
  import AddressDetails from "./AddressDetails";
22
18
 
23
- // ─── Icons ──────────────────────────────────────────────────────────────────
19
+ // ─── Icons ───────────────────────────────────────────────────────────────────
24
20
 
25
- const FingerprintIcon = ({ size = 22, color = "#6366f1" }) => (
26
- <svg width={size} height={size} viewBox="0 0 24 24" fill="none">
27
- <path
28
- d="M17.81 4.47c-.08 0-.16-.02-.23-.06C15.66 3.42 14 3 12.01 3c-1.98 0-3.86.47-5.57 1.41-.24.13-.54.04-.67-.2-.13-.24-.04-.55.2-.68C7.82 2.52 9.86 2 12.01 2c2.13 0 3.96.46 5.57 1.41.24.13.33.43.2.67-.09.13-.24.39-.39.39zM12 21c-.28 0-.5-.22-.5-.5v-4.42c-2.33-.21-4.44-1.35-5.94-3.21-1.5-1.86-2.22-4.18-2.02-6.52.05-.59.55-1.03 1.14-.98s1.03.55.98 1.14c-.15 1.76.39 3.51 1.52 4.91 1.12 1.4 2.7 2.26 4.45 2.42.21.02.37.19.37.4v6.26c0 .28-.22.5-.5.5z"
29
- fill={color}
30
- />
31
- <path d="M12 11c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1z" fill={color} />
21
+ const LockIcon = ({ size = 16 }) => (
22
+ <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round">
23
+ <rect x="3" y="11" width="18" height="11" rx="2" />
24
+ <path d="M7 11V7a5 5 0 0 1 10 0v4" />
32
25
  </svg>
33
26
  );
34
27
 
35
- const UserIcon = ({ size = 16, color = "#64748b" }) => (
36
- <svg width={size} height={size} viewBox="0 0 24 24" fill="none">
37
- <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" stroke={color} strokeWidth="2" strokeLinecap="round" />
38
- <circle cx="12" cy="7" r="4" stroke={color} strokeWidth="2" />
28
+ const UserIcon = ({ size = 16, color = "currentColor" }) => (
29
+ <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.8" strokeLinecap="round">
30
+ <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
31
+ <circle cx="12" cy="7" r="4" />
39
32
  </svg>
40
33
  );
41
34
 
42
- const PhoneIcon = ({ size = 16, color = "#64748b" }) => (
43
- <svg width={size} height={size} viewBox="0 0 24 24" fill="none">
44
- <path
45
- d="M22 16.92v3a2 2 0 01-2.18 2 19.79 19.79 0 01-8.63-3.07A19.5 19.5 0 013.07 10.6 19.79 19.79 0 0 0 3 1.82C3 .72 3.72 0 4.82 0h3a2 2 0 012 1.72c.127.96.361 1.903.7 2.81a2 2 0 01-.45 2.11L8.91 7.91a16 16 0 006.16 6.16l1.27-1.27a2 2 0 012.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0122 16.92z"
46
- stroke={color}
47
- strokeWidth="2"
48
- strokeLinecap="round"
49
- />
35
+ const PhoneIcon = ({ size = 16, color = "currentColor" }) => (
36
+ <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.8" strokeLinecap="round">
37
+ <path d="M22 16.92v3a2 2 0 01-2.18 2 19.79 19.79 0 01-8.63-3.07 19.5 19.5 0 01-5.37-5.37 19.79 19.79 0 01-3.07-8.63A2 2 0 014.82 0h3a2 2 0 012 1.72c.127.96.361 1.903.7 2.81a2 2 0 01-.45 2.11L8.91 7.91a16 16 0 006.16 6.16l1.27-1.27a2 2 0 012.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0122 16.92z" />
50
38
  </svg>
51
39
  );
52
40
 
53
41
  const WhatsappIcon = ({ size = 16 }) => (
54
42
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none">
55
43
  <path
56
- d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347z"
44
+ d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413z"
57
45
  fill="#25D366"
58
46
  />
59
47
  <path
60
48
  d="M12 2C6.477 2 2 6.477 2 12c0 1.89.525 3.66 1.438 5.168L2 22l4.832-1.438A9.96 9.96 0 0012 22c5.523 0 10-4.477 10-10S17.523 2 12 2z"
61
- stroke="#25D366"
62
- strokeWidth="2"
63
- strokeLinecap="round"
49
+ stroke="#25D366" strokeWidth="1.8" strokeLinecap="round"
64
50
  />
65
51
  </svg>
66
52
  );
67
53
 
68
- const MailIcon = ({ size = 16, color = "#64748b" }) => (
69
- <svg width={size} height={size} viewBox="0 0 24 24" fill="none">
70
- <path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z" stroke={color} strokeWidth="2" strokeLinecap="round" />
71
- <path d="M22 6l-10 7L2 6" stroke={color} strokeWidth="2" strokeLinecap="round" />
54
+ const MailIcon = ({ size = 16, color = "currentColor" }) => (
55
+ <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.8" strokeLinecap="round">
56
+ <path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z" />
57
+ <path d="M22 6l-10 7L2 6" />
72
58
  </svg>
73
59
  );
74
60
 
75
- const UsersIcon = ({ size = 16, color = "#64748b" }) => (
76
- <svg width={size} height={size} viewBox="0 0 24 24" fill="none">
77
- <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" stroke={color} strokeWidth="2" strokeLinecap="round" />
78
- <circle cx="9" cy="7" r="4" stroke={color} strokeWidth="2" />
79
- <path d="M23 21v-2a4 4 0 0 0-3-3.87" stroke={color} strokeWidth="2" strokeLinecap="round" />
80
- <path d="M16 3.13a4 4 0 0 1 0 7.75" stroke={color} strokeWidth="2" strokeLinecap="round" />
61
+ const UsersIcon = ({ size = 16, color = "currentColor" }) => (
62
+ <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.8" strokeLinecap="round">
63
+ <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
64
+ <circle cx="9" cy="7" r="4" />
65
+ <path d="M23 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75" />
81
66
  </svg>
82
67
  );
83
68
 
69
+ const CheckIcon = ({ size = 15, color = "#1D9E75" }) => (
70
+ <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2.8" strokeLinecap="round">
71
+ <polyline points="20 6 9 17 4 12" />
72
+ </svg>
73
+ );
74
+
75
+ // ─── Reusable: Icon-prefixed input wrapper ────────────────────────────────────
76
+
77
+ const IconInput = ({ icon, rightIcon, inputStyle = {}, ...props }) => (
78
+ <div style={{ position: "relative", width: "100%" }}>
79
+ <div style={{
80
+ position: "absolute", left: "10px", top: "50%",
81
+ transform: "translateY(-50%)", zIndex: 1, opacity: 0.45,
82
+ display: "flex", pointerEvents: "none",
83
+ }}>
84
+ {icon}
85
+ </div>
86
+ <TextInput
87
+ textInputStyle={{ paddingLeft: "36px", paddingRight: rightIcon ? "36px" : "12px", ...inputStyle }}
88
+ {...props}
89
+ />
90
+ {rightIcon && (
91
+ <div style={{
92
+ position: "absolute", right: "10px", top: "50%",
93
+ transform: "translateY(-50%)", display: "flex",
94
+ }}>
95
+ {rightIcon}
96
+ </div>
97
+ )}
98
+ </div>
99
+ );
100
+
101
+ // ─── Reusable: Section heading with inline rule ───────────────────────────────
102
+
103
+ const SectionHead = ({ icon, label }) => (
104
+ <div style={{
105
+ display: "flex", alignItems: "center", gap: "8px",
106
+ marginBottom: "16px", marginTop: "4px",
107
+ }}>
108
+ <div style={{ opacity: 0.5, display: "flex" }}>{icon}</div>
109
+ <span style={{ fontSize: "15px", fontWeight: "600", color: "#0B0C0C", whiteSpace: "nowrap" }}>
110
+ {label}
111
+ </span>
112
+ <div style={{ flex: 1, height: "1px", background: "#EAECF0" }} />
113
+ </div>
114
+ );
115
+
116
+ // ─── Reusable: Radio toggle row ───────────────────────────────────────────────
117
+
118
+ const RadioToggleRow = ({ label, selected, onSelect, t, options }) => (
119
+ <div style={{
120
+ display: "flex", alignItems: "center",
121
+ justifyContent: "space-between", marginBottom: "8px",
122
+ }}>
123
+ <CardLabel style={{ fontWeight: "500", marginBottom: 0, fontSize: "13px", color: "#505A5F" }}>
124
+ {label}
125
+ </CardLabel>
126
+ <RadioButtons
127
+ options={options}
128
+ optionsKey="name"
129
+ selectedOption={selected}
130
+ onSelect={onSelect}
131
+ t={t}
132
+ innerStyles={{ display: "flex", gap: "20px" }}
133
+ style={{ marginBottom: 0 }}
134
+ />
135
+ </div>
136
+ );
137
+
138
+ // ─── Main Component ───────────────────────────────────────────────────────────
139
+
84
140
  const AadhaarVerification = () => {
85
141
  const { t } = useTranslation();
86
142
  const location = useLocation();
@@ -99,18 +155,27 @@ const AadhaarVerification = () => {
99
155
  },
100
156
  };
101
157
 
158
+ // Normalize the nested data shape (API returns .connectionDetails, fallback uses .connectionDetailsInfo)
159
+ const details =
160
+ connectionDetails?.connectionDetails ||
161
+ connectionDetails?.connectionDetailsInfo ||
162
+ {};
163
+
164
+ // ── State ──
102
165
  const [aadhaarLastFour, setAadhaarLastFour] = useState("");
103
166
  const [isAadhaarVerified, setIsAadhaarVerified] = useState(false);
104
167
  const [isVerifying, setIsVerifying] = useState(false);
105
168
  const [nameCorrect, setNameCorrect] = useState({ code: "NO", name: "CORE_COMMON_NO" });
106
- const [userName, setUserName] = useState(connectionDetails?.connectionDetailsInfo?.consumerName || "");
169
+ const [userName, setUserName] = useState(details.consumerName || "");
170
+
107
171
  const [mobileChange, setMobileChange] = useState({ code: "NO", name: "CORE_COMMON_NO" });
108
- const [mobileNumber, setMobileNumber] = useState(connectionDetails?.connectionDetailsInfo?.phoneNumber || "");
109
- const [whatsappNumber, setWhatsappNumber] = useState(connectionDetails?.connectionDetailsInfo?.phoneNumber || "");
110
- const [email, setEmail] = useState(connectionDetails?.connectionDetailsInfo?.email || "");
111
- const [noOfPersons, setNoOfPersons] = useState("");
172
+ const [mobileNumber, setMobileNumber] = useState(details.phoneNumber || "");
112
173
 
113
- // New states for single-page flow
174
+ const [whatsappNumber, setWhatsappNumber] = useState(details.phoneNumber || "");
175
+ const [email, setEmail] = useState(details.email || "");
176
+ const [noOfPersons, setNoOfPersons] = useState(
177
+ connectionDetails?.addressDetails?.noOfPerson || ""
178
+ );
114
179
  const [showAddressSection, setShowAddressSection] = useState(false);
115
180
  const [addressData, setAddressData] = useState(null);
116
181
 
@@ -119,17 +184,22 @@ const AadhaarVerification = () => {
119
184
  { code: "NO", name: "CORE_COMMON_NO" },
120
185
  ];
121
186
 
187
+ // ── Handlers ──
122
188
  const handleVerifyAadhaar = () => {
123
- if (aadhaarLastFour.length === 4) {
124
- setIsVerifying(true);
189
+ if (aadhaarLastFour.length !== 4 || isVerifying) return;
190
+ setIsVerifying(true);
191
+ setTimeout(() => {
192
+ setIsVerifying(false);
193
+ setIsAadhaarVerified(true);
194
+ // Auto-expand address section upon verification
195
+ setShowAddressSection(true);
125
196
  setTimeout(() => {
126
- setIsVerifying(false);
127
- setIsAadhaarVerified(true);
128
- }, 1200);
129
- }
197
+ addressSectionRef.current?.scrollIntoView({ behavior: "smooth", block: "start" });
198
+ }, 100);
199
+ }, 1200);
130
200
  };
131
201
 
132
- const handleSaveAndContinueAadhaar = () => {
202
+ const handleSaveAndContinue = () => {
133
203
  setShowAddressSection(true);
134
204
  setTimeout(() => {
135
205
  addressSectionRef.current?.scrollIntoView({ behavior: "smooth", block: "start" });
@@ -142,299 +212,342 @@ const AadhaarVerification = () => {
142
212
  kNumber,
143
213
  selectedOption,
144
214
  connectionDetails,
145
- aadhaarDetails: { aadhaarLastFour, isAadhaarVerified, userName, mobileNumber, whatsappNumber, email, noOfPersons },
215
+ aadhaarDetails: {
216
+ aadhaarLastFour,
217
+ isAadhaarVerified,
218
+ userName,
219
+ mobileNumber,
220
+ whatsappNumber,
221
+ email,
222
+ noOfPersons,
223
+ },
146
224
  addressDetails,
147
225
  });
148
226
  };
149
227
 
228
+ // ── Styles ──
229
+ const styles = {
230
+ verifiedInput: {
231
+ borderColor: "#1D9E75",
232
+ backgroundColor: "#E1F5EE",
233
+ },
234
+ verifiedCard: {
235
+ backgroundColor: "#E1F5EE",
236
+ border: "0.5px solid #5DCAA5",
237
+ borderRadius: "8px",
238
+ padding: "16px",
239
+ marginTop: "14px",
240
+ marginBottom: "4px",
241
+ animation: "fadeSlideIn 0.35s ease",
242
+ },
243
+ infoLabel: {
244
+ fontSize: "11px",
245
+ fontWeight: "600",
246
+ color: "#1D9E75",
247
+ textTransform: "uppercase",
248
+ letterSpacing: "0.05em",
249
+ marginBottom: "3px",
250
+ },
251
+ infoValue: {
252
+ fontSize: "14px",
253
+ fontWeight: "500",
254
+ color: "#04342C",
255
+ },
256
+ twoCol: {
257
+ display: "grid",
258
+ gridTemplateColumns: "1fr 1fr",
259
+ gap: "14px",
260
+ marginBottom: "4px",
261
+ },
262
+ optionalTag: {
263
+ display: "inline-block",
264
+ fontSize: "10px",
265
+ background: "#F1EFE8",
266
+ color: "#5F5E5A",
267
+ border: "0.5px solid #D3D1C7",
268
+ borderRadius: "10px",
269
+ padding: "1px 7px",
270
+ marginLeft: "6px",
271
+ fontWeight: "400",
272
+ },
273
+ };
274
+
150
275
  return (
151
276
  <div className="inbox-container">
152
277
  <style>{`
153
- @keyframes spin { to { transform: rotate(360deg); } }
154
- @keyframes fadeSlideIn { from { opacity:0; transform:translateY(10px); } to { opacity:1; transform:translateY(0); } }
155
- @keyframes pulseGreen { 0%,100% { box-shadow:0 0 0 0 rgba(22,163,74,0.4); } 50% { box-shadow:0 0 0 8px rgba(22,163,74,0); } }
156
- `}</style>
157
-
278
+ @keyframes fadeSlideIn {
279
+ from { opacity: 0; transform: translateY(6px); }
280
+ to { opacity: 1; transform: translateY(0); }
281
+ }
282
+ @keyframes pulseGreen {
283
+ 0%, 100% { box-shadow: 0 0 0 0 rgba(29,158,117,0.35); }
284
+ 50% { box-shadow: 0 0 0 6px rgba(29,158,117,0); }
285
+ }
286
+ .ekyc-sidebar-step { display: flex; gap: 10px; align-items: flex-start; position: relative; padding-bottom: 18px; }
287
+ .ekyc-sidebar-step:last-child { padding-bottom: 0; }
288
+ .ekyc-step-line { position: absolute; left: 10px; top: 22px; width: 1px; height: calc(100% - 10px); background: #EAECF0; }
289
+ .ekyc-step-dot { width: 20px; height: 20px; border-radius: 50%; border: 1.5px solid #D0D5DD; display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 500; color: #98A2B3; background: #fff; flex-shrink: 0; margin-top: 1px; }
290
+ .ekyc-step-dot.active { border-color: #185FA5; color: #185FA5; background: #E6F1FB; }
291
+ .ekyc-step-dot.done { border-color: #0F6E56; background: #0F6E56; color: #fff; }
292
+ .ekyc-step-label { font-size: 12px; color: #667085; padding-top: 2px; }
293
+ .ekyc-step-label.active { color: #0B0C0C; font-weight: 600; }
294
+ .ekyc-step-label.done { color: #0F6E56; }
295
+ .ekyc-field-label { font-size: 11px; font-weight: 600; color: #667085; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 6px; }
296
+ `}</style>
297
+
298
+ {/* ── Sidebar ── */}
158
299
  <div className="filters-container">
159
- {/* Sidebar Title Card */}
160
- <Card
161
- className="sidebar-title-card"
162
- style={{ display: "flex", alignItems: "center", padding: "16px", marginBottom: "16px", borderRadius: "4px" }}
163
- >
164
- <div className="icon-container" style={{ color: "#0068faff", marginRight: "12px" }}>
165
- <HomeIcon style={{ width: "24px", height: "24px" }} />
300
+ <Card style={{ display: "flex", alignItems: "center", padding: "12px 16px", marginBottom: "12px", borderRadius: "8px" }}>
301
+ <div style={{ color: "#185FA5", marginRight: "10px", display: "flex" }}>
302
+ <HomeIcon style={{ width: "20px", height: "20px" }} />
303
+ </div>
304
+ <div style={{ fontWeight: "600", fontSize: "15px", color: "#0B0C0C" }}>
305
+ {t("EKYC_PROCESS") || "eKYC Process"}
166
306
  </div>
167
- <div style={{ fontWeight: "700", fontSize: "18px", color: "#0B0C0C" }}>{t("EKYC_PROCESS")}</div>
168
307
  </Card>
169
308
 
170
- {/* Progress Steps Sidebar */}
171
- <div
172
- style={{
173
- backgroundColor: "#FFFFFF",
174
- padding: "16px",
175
- borderRadius: "8px",
176
- border: "1px solid #EAECF0",
177
- boxShadow: "0 2px 4px rgba(0,0,0,0.02)",
178
- }}
179
- >
180
- <ConnectingCheckPoints>
181
- <CheckPoint label={t("EKYC_STEP_AADHAAR") || "Aadhaar"} isCompleted={showAddressSection} />
182
- <CheckPoint label={t("EKYC_STEP_ADDRESS") || "Address"} isCompleted={addressData !== null} />
183
- <CheckPoint label={t("EKYC_STEP_PROPERTY") || "Property"} isCompleted={false} />
184
- <CheckPoint label={t("EKYC_STEP_REVIEW") || "Review"} />
185
- </ConnectingCheckPoints>
309
+ <div style={{ background: "#fff", padding: "16px 14px", borderRadius: "8px", border: "1px solid #EAECF0" }}>
310
+ {[
311
+ { label: t("EKYC_STEP_AADHAAR") || "Aadhaar", done: showAddressSection, active: !showAddressSection },
312
+ { label: t("EKYC_STEP_ADDRESS") || "Address", done: addressData !== null, active: showAddressSection && addressData === null },
313
+ { label: t("EKYC_STEP_PROPERTY") || "Property", done: false, active: false },
314
+ { label: t("EKYC_STEP_REVIEW") || "Review", done: false, active: false },
315
+ ].map((step, i) => (
316
+ <div className="ekyc-sidebar-step" key={i}>
317
+ <div className={`ekyc-step-dot${step.done ? " done" : step.active ? " active" : ""}`}>
318
+ {step.done
319
+ ? <CheckIcon size={11} color="#fff" />
320
+ : i + 1}
321
+ </div>
322
+ {i < 3 && <div className="ekyc-step-line" />}
323
+ <div className={`ekyc-step-label${step.done ? " done" : step.active ? " active" : ""}`}>
324
+ {step.label}
325
+ </div>
326
+ </div>
327
+ ))}
186
328
  </div>
187
329
  </div>
188
330
 
331
+ {/* ── Main content ── */}
189
332
  <div style={{ flex: 1, marginLeft: "16px" }}>
190
333
  <Card>
191
- <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "24px" }}>
192
- <Header>{t("EKYC_AADHAAR_VERIFICATION_HEADER") || "Aadhaar Verification"}</Header>
193
- <div style={{ fontSize: "14px", fontWeight: "700", color: "#505A5F" }}>
194
- {t("EKYC_K_NUMBER")}: <span style={{ color: "#0B0C0C" }}>{kNumber}</span>
334
+
335
+ {/* K-Number badge */}
336
+ <div style={{ display: "flex", justifyContent: "flex-end", marginBottom: "20px" }}>
337
+ <div style={{
338
+ background: "#F9FAFB", border: "0.5px solid #EAECF0",
339
+ borderRadius: "20px", padding: "4px 14px",
340
+ fontSize: "12px", color: "#667085",
341
+ }}>
342
+ {t("EKYC_K_NUMBER") || "K Number"}:{" "}
343
+ <span style={{ color: "#0B0C0C", fontWeight: "600" }}>{kNumber}</span>
195
344
  </div>
196
345
  </div>
197
346
 
198
- {/* Section 1: Aadhaar Number */}
199
- <CardHeader style={{ fontSize: "20px", marginBottom: "16px" }}>{t("EKYC_AADHAAR_NUMBER_HEADER") || "Aadhaar Number"}</CardHeader>
347
+ {/* ── Section 1: Aadhaar ── */}
348
+ <SectionHead
349
+ icon={<LockIcon size={16} />}
350
+ label={t("EKYC_AADHAAR_NUMBER_HEADER") || "Aadhaar Number"}
351
+ />
200
352
 
353
+ <div className="ekyc-field-label">
354
+ {t("EKYC_LAST_4_DIGIT_AADHAAR") || "Enter 12 digits of Aadhaar"}
355
+ </div>
201
356
  <LabelFieldPair>
202
- <CardLabel style={{ fontWeight: "600" }}>{t("EKYC_LAST_4_DIGIT_AADHAAR") || "Last 4-digit Aadhaar Number"}</CardLabel>
203
- <div className="field" style={{ position: "relative" }}>
204
- <div style={{ position: "absolute", left: "12px", top: "50%", transform: "translateY(-50%)", zIndex: 1, opacity: 0.6 }}>
205
- <FingerprintIcon size={20} />
206
- </div>
207
- <TextInput
357
+ <div className="field">
358
+ <IconInput
359
+ icon={<LockIcon size={15} />}
360
+ rightIcon={isAadhaarVerified ? <CheckIcon size={15} /> : null}
208
361
  value={aadhaarLastFour}
209
362
  onChange={(e) => {
210
363
  const val = e.target.value;
211
- if (val.length <= 4 && /^\d*$/.test(val)) setAadhaarLastFour(val);
364
+ if (val.length <= 12 && /^\d*$/.test(val)) setAadhaarLastFour(val);
212
365
  }}
213
- placeholder={t("EKYC_ENTER_LAST_4_DIGIT") || "Enter last 4 digits"}
214
- textInputStyle={{ paddingLeft: "40px" }}
366
+ placeholder={t("EKYC_ENTER_LAST_4_DIGIT") || "Enter 12 digits"}
215
367
  maxLength={4}
368
+ disabled={isAadhaarVerified}
369
+ inputStyle={isAadhaarVerified ? styles.verifiedInput : {}}
216
370
  />
217
- {isAadhaarVerified && (
218
- <div style={{ position: "absolute", right: "12px", top: "50%", transform: "translateY(-50%)" }}>
219
- <TickMark fillColor="#2E9E8F" />
220
- </div>
221
- )}
222
371
  </div>
223
372
  </LabelFieldPair>
224
373
 
225
374
  {!isAadhaarVerified && (
226
375
  <SubmitBar
227
- label={isVerifying ? t("EKYC_VERIFYING") || "Verifying..." : t("EKYC_VERIFY_AADHAAR_BTN") || "Verify Aadhaar"}
376
+ label={isVerifying
377
+ ? t("EKYC_VERIFYING") || "Verifying..."
378
+ : t("EKYC_VERIFY_AADHAAR_BTN") || "Verify Aadhaar"}
228
379
  onSubmit={handleVerifyAadhaar}
229
380
  disabled={aadhaarLastFour.length !== 4 || isVerifying}
230
- style={{ marginTop: "16px", opacity: aadhaarLastFour.length !== 4 ? 0.6 : 1 }}
381
+ style={{ marginTop: "12px" }}
231
382
  />
232
383
  )}
233
384
 
234
385
  {isAadhaarVerified && (
235
- <div
236
- style={{
237
- backgroundColor: "#E7F4EE",
238
- padding: "20px",
239
- borderRadius: "8px",
240
- marginTop: "24px",
241
- marginBottom: "24px",
242
- border: "1px solid #D1E9DB",
243
- animation: "fadeSlideIn 0.4s ease",
244
- }}
245
- >
246
- <div style={{ display: "flex", alignItems: "center", gap: "10px", marginBottom: "16px" }}>
247
- <div
248
- style={{
249
- backgroundColor: "#D1E9DB",
250
- padding: "4px",
251
- borderRadius: "50%",
252
- display: "flex",
253
- animation: "pulseGreen 2s ease infinite",
254
- }}
255
- >
256
- <TickMark fillColor="#2E9E8F" />
386
+ <div style={styles.verifiedCard}>
387
+ <div style={{ display: "flex", alignItems: "center", gap: "8px", marginBottom: "14px" }}>
388
+ <div style={{
389
+ width: "24px", height: "24px", borderRadius: "50%",
390
+ background: "#9FE1CB", display: "flex", alignItems: "center",
391
+ justifyContent: "center", animation: "pulseGreen 2s ease infinite",
392
+ flexShrink: 0,
393
+ }}>
394
+ <CheckIcon size={13} color="#085041" />
257
395
  </div>
258
- <span style={{ fontWeight: "700", color: "#2E9E8F", fontSize: "18px" }}>
396
+ <span style={{ fontWeight: "600", color: "#085041", fontSize: "14px" }}>
259
397
  {t("EKYC_AADHAAR_VERIFIED_SUCCESS") || "Aadhaar Verified Successfully"}
260
398
  </span>
261
399
  </div>
262
- <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "16px" }}>
263
- <div style={{ display: "flex", flexDirection: "column" }}>
264
- <span style={{ color: "#667085", fontSize: "12px", fontWeight: "700", textTransform: "uppercase" }}>{t("EKYC_NAME")}</span>
265
- <span style={{ fontWeight: "700", fontSize: "16px", color: "#101828" }}>Rajesh Kumar Singh</span>
400
+ <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "12px" }}>
401
+ <div>
402
+ <div style={styles.infoLabel}>{t("EKYC_NAME") || "Name"}</div>
403
+ <div style={styles.infoValue}>{details.consumerName}</div>
266
404
  </div>
267
- <div style={{ display: "flex", flexDirection: "column" }}>
268
- <span style={{ color: "#667085", fontSize: "12px", fontWeight: "700", textTransform: "uppercase" }}>{t("EKYC_AADHAAR")}</span>
269
- <span style={{ fontWeight: "700", fontSize: "16px", color: "#101828" }}>XXXX XXXX {aadhaarLastFour}</span>
405
+ <div>
406
+ <div style={styles.infoLabel}>{t("EKYC_AADHAAR") || "Aadhaar"}</div>
407
+ <div style={styles.infoValue}>XXXX XXXX {aadhaarLastFour}</div>
270
408
  </div>
271
- <div style={{ display: "flex", flexDirection: "column", gridColumn: "span 2" }}>
272
- <span style={{ color: "#667085", fontSize: "12px", fontWeight: "700", textTransform: "uppercase" }}>{t("EKYC_ADDRESS")}</span>
273
- <span style={{ fontWeight: "500", fontSize: "15px", color: "#344054" }}>House No. 45, Sector 12, New Delhi - 110001</span>
409
+ <div style={{ gridColumn: "span 2" }}>
410
+ <div style={styles.infoLabel}>{t("EKYC_ADDRESS") || "Address"}</div>
411
+ <div style={{ ...styles.infoValue, fontSize: "13px" }}>{details.address}</div>
274
412
  </div>
275
413
  </div>
276
414
  </div>
277
415
  )}
278
416
 
279
- <hr style={{ margin: "32px 0", border: "0", borderTop: "1px solid #EAECF0" }} />
280
-
281
- {/* Section 2: Contact Details */}
282
- <CardHeader style={{ fontSize: "20px", marginBottom: "16px" }}>{t("EKYC_CONTACT_DETAILS_HEADER") || "Contact Details"}</CardHeader>
283
- <LabelFieldPair style={{ animation: "fadeSlideIn 0.3s ease" }}>
284
- <div style={{ display: "flex", alignItems: "center", gap: "20px" }}>
285
- <CardLabel style={{ fontWeight: "600", marginBottom: "0" }}>{t("EKYC_USER_NAME") || "Corrected Name"}</CardLabel>
286
-
287
- <RadioButtons
288
- options={yesNoOptions}
289
- optionsKey="name"
290
- selectedOption={nameCorrect}
291
- onSelect={setNameCorrect}
292
- t={t}
293
- innerStyles={{ display: "flex", gap: "24px" }}
294
- style={{ display: "flex", gap: "50px", marginBottom: "0" }}
295
- />
296
- </div>
297
- <div className="field" style={{ position: "relative" }}>
298
- <div
299
- style={{
300
- position: "absolute",
301
- left: "12px",
302
- top: "50%",
303
- transform: "translateY(-50%)",
304
- zIndex: 1,
305
- opacity: nameCorrect.code === "YES" ? 0.6 : 0.3,
306
- }}
307
- >
308
- <UserIcon size={18} color={nameCorrect.code === "YES" ? "#64748b" : "#94a3b8"} />
309
- </div>
310
- <TextInput
417
+ <hr style={{ margin: "24px 0", border: 0, borderTop: "1px solid #EAECF0" }} />
418
+
419
+ {/* ── Section 2: Contact Details ── */}
420
+ <SectionHead
421
+ icon={<UserIcon size={16} />}
422
+ label={t("EKYC_CONTACT_DETAILS_HEADER") || "Contact Details"}
423
+ />
424
+
425
+ {/* Name */}
426
+ <RadioToggleRow
427
+ label={`${t("EKYC_USER_NAME")} (${t("EKYC_NAME_CORRECT_HINT")})`}
428
+ selected={nameCorrect}
429
+ onSelect={setNameCorrect}
430
+ options={yesNoOptions}
431
+ t={t}
432
+ />
433
+ <LabelFieldPair>
434
+ <div className="field">
435
+ <IconInput
436
+ icon={<UserIcon size={15} color={nameCorrect.code === "YES" ? "#64748b" : "#94a3b8"} />}
311
437
  value={userName}
312
438
  onChange={(e) => setUserName(e.target.value)}
313
439
  placeholder={t("EKYC_ENTER_NAME_PLACEHOLDER") || "Enter full name"}
314
- textInputStyle={{ paddingLeft: "40px" }}
315
440
  disabled={nameCorrect.code !== "YES"}
316
441
  />
317
442
  </div>
318
443
  </LabelFieldPair>
319
444
 
445
+ {/* Mobile */}
446
+ <RadioToggleRow
447
+ label={`${t("EKYC_USER_MOBILE_NUMBER")} (${t("EKYC_UPDATE_MOBILE_HINT")})`}
448
+ selected={mobileChange}
449
+ onSelect={setMobileChange}
450
+ options={yesNoOptions}
451
+ t={t}
452
+ />
320
453
  <LabelFieldPair>
321
- <div style={{ display: "flex", alignItems: "center", gap: "20px", padding: "10px" }}>
322
- <CardLabel style={{ fontWeight: "600", marginBottom: "0" }}>{t("EKYC_USER_MOBILE_NUMBER") || "User Mobile Number"}</CardLabel>
323
-
324
- <RadioButtons
325
- options={yesNoOptions}
326
- optionsKey="name"
327
- selectedOption={mobileChange}
328
- onSelect={setMobileChange}
329
- t={t}
330
- innerStyles={{ display: "flex", gap: "24px" }}
331
- style={{ display: "flex", gap: "50px", marginBottom: "0" }}
332
- />
333
- </div>
334
- <div className="field" style={{ position: "relative" }}>
335
- <div
336
- style={{
337
- position: "absolute",
338
- left: "12px",
339
- top: "50%",
340
- transform: "translateY(-50%)",
341
- zIndex: 1,
342
- opacity: mobileChange.code === "YES" ? 0.6 : 0.3,
343
- }}
344
- >
345
- <PhoneIcon size={18} color={mobileChange.code === "YES" ? "#64748b" : "#94a3b8"} />
346
- </div>
347
- <TextInput
454
+ <div className="field">
455
+ <IconInput
456
+ icon={<PhoneIcon size={15} color={mobileChange.code === "YES" ? "#64748b" : "#94a3b8"} />}
348
457
  value={mobileNumber}
349
458
  onChange={(e) => setMobileNumber(e.target.value)}
350
459
  placeholder="+91 XXXXX XXXXX"
351
- textInputStyle={{ paddingLeft: "40px" }}
352
460
  disabled={mobileChange.code !== "YES"}
353
461
  />
354
462
  </div>
355
463
  </LabelFieldPair>
356
464
 
357
- <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "24px", marginTop: "24px" }}>
358
- <LabelFieldPair>
359
- <CardLabel style={{ fontWeight: "600" }}>{t("EKYC_WHATSAPP_NUMBER") || "WhatsApp Number"}</CardLabel>
360
- <div className="field" style={{ position: "relative" }}>
361
- <div style={{ position: "absolute", left: "12px", top: "50%", transform: "translateY(-50%)", zIndex: 1, opacity: 0.6 }}>
362
- <WhatsappIcon size={18} />
363
- </div>
364
- <TextInput
365
- value={whatsappNumber}
366
- onChange={(e) => setWhatsappNumber(e.target.value)}
367
- placeholder="+91 XXXXX XXXXX"
368
- textInputStyle={{ paddingLeft: "40px" }}
369
- />
465
+ {/* WhatsApp + Email */}
466
+ <div style={styles.twoCol}>
467
+ <div>
468
+ <div className="ekyc-field-label">
469
+ {t("EKYC_WHATSAPP_NUMBER") || "WhatsApp Number"}
370
470
  </div>
371
- </LabelFieldPair>
372
- <LabelFieldPair>
373
- <CardLabel style={{ fontWeight: "600" }}>
374
- {t("EKYC_EMAIL_ADDRESS") || "Email Address"}{" "}
375
- <span style={{ fontWeight: "400", color: "#667085" }}>({t("EKYC_OPTIONAL") || "Optional"})</span>
376
- </CardLabel>
377
- <div className="field" style={{ position: "relative" }}>
378
- <div style={{ position: "absolute", left: "12px", top: "50%", transform: "translateY(-50%)", zIndex: 1, opacity: 0.6 }}>
379
- <MailIcon size={18} />
380
- </div>
381
- <TextInput
382
- value={email}
383
- onChange={(e) => setEmail(e.target.value)}
384
- placeholder={t("EKYC_EMAIL_ADDRESS_PLACEHOLDER") || "example@email.com"}
385
- textInputStyle={{ paddingLeft: "40px" }}
386
- />
471
+ <IconInput
472
+ icon={<WhatsappIcon size={15} />}
473
+ value={whatsappNumber}
474
+ onChange={(e) => setWhatsappNumber(e.target.value)}
475
+ placeholder="+91 XXXXX XXXXX"
476
+ />
477
+ </div>
478
+ <div>
479
+ <div className="ekyc-field-label">
480
+ {t("EKYC_EMAIL_ADDRESS") || "Email Address"}
481
+ <span style={styles.optionalTag}>{t("EKYC_OPTIONAL") || "Optional"}</span>
387
482
  </div>
388
- </LabelFieldPair>
483
+ <IconInput
484
+ icon={<MailIcon size={15} />}
485
+ value={email}
486
+ onChange={(e) => setEmail(e.target.value)}
487
+ placeholder={t("EKYC_EMAIL_ADDRESS_PLACEHOLDER") || "example@email.com"}
488
+ />
489
+ </div>
389
490
  </div>
390
491
 
391
- <hr style={{ margin: "32px 0", border: "0", borderTop: "1px solid #EAECF0" }} />
492
+ <hr style={{ margin: "24px 0", border: 0, borderTop: "1px solid #EAECF0" }} />
392
493
 
393
- {/* Section 3: Family Details */}
394
- <CardHeader style={{ fontSize: "20px", marginBottom: "16px" }}>{t("EKYC_FAMILY_DETAILS_HEADER") || "Family Details"}</CardHeader>
494
+ {/* ── Section 3: Family Details ── */}
495
+ <SectionHead
496
+ icon={<UsersIcon size={16} />}
497
+ label={t("EKYC_FAMILY_DETAILS_HEADER") || "Family Details"}
498
+ />
395
499
 
500
+ <div className="ekyc-field-label">
501
+ {t("EKYC_NO_OF_PERSONS") || "Number of Family Members"}
502
+ </div>
396
503
  <LabelFieldPair>
397
- <CardLabel style={{ fontWeight: "600" }}>{t("EKYC_NO_OF_PERSONS") || "Number of Family Members"}</CardLabel>
398
- <div className="field" style={{ position: "relative" }}>
399
- <div style={{ position: "absolute", left: "12px", top: "50%", transform: "translateY(-50%)", zIndex: 1, opacity: 0.6 }}>
400
- <UsersIcon size={18} />
401
- </div>
402
- <TextInput
504
+ <div className="field">
505
+ <IconInput
506
+ icon={<UsersIcon size={15} />}
403
507
  value={noOfPersons}
404
508
  onChange={(e) => {
405
509
  if (/^\d*$/.test(e.target.value)) setNoOfPersons(e.target.value);
406
510
  }}
407
511
  placeholder={t("EKYC_ENTER_NO_OF_PERSONS") || "Enter total number of persons"}
408
- textInputStyle={{ paddingLeft: "40px" }}
409
512
  />
410
513
  </div>
411
514
  </LabelFieldPair>
412
515
 
516
+ {/* Save & Continue (Non-sticky, at form end) */}
413
517
  {!showAddressSection && (
414
- <ActionBar>
415
- <SubmitBar label={t("ES_COMMON_SAVE_CONTINUE") || "Save & Continue"} onSubmit={handleSaveAndContinueAadhaar} />
416
- </ActionBar>
518
+ <div style={{ marginTop: "24px" }}>
519
+ <SubmitBar
520
+ label={t("ES_COMMON_SAVE_CONTINUE") || "Save & Continue"}
521
+ onSubmit={handleSaveAndContinue}
522
+ />
523
+ </div>
417
524
  )}
418
525
 
526
+ {/* Address section (injected inline) */}
419
527
  {showAddressSection && (
420
528
  <div ref={addressSectionRef}>
421
- <AddressDetails isSection={true} onComplete={handleCompleteAll} parentState={{ kNumber, selectedOption, connectionDetails }} />
529
+ <AddressDetails
530
+ isSection={true}
531
+ onComplete={handleCompleteAll}
532
+ parentState={{ kNumber, selectedOption, connectionDetails }}
533
+ />
422
534
  </div>
423
535
  )}
424
536
 
425
- <div style={{ textAlign: "center", marginTop: "24px" }}>
426
- <p style={{ fontSize: "12px", color: "#667085", display: "flex", alignItems: "center", justifyContent: "center", gap: "4px" }}>
427
- <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
428
- <path d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z" />
429
- <path d="M12 11V17M12 7H12.01" strokeLinecap="round" />
430
- </svg>
431
- {t("EKYC_SECURE_DATA_NOTICE") || "Your data is encrypted and secure"}
432
- </p>
537
+ {/* Secure notice */}
538
+ <div style={{
539
+ display: "flex", alignItems: "center", justifyContent: "center",
540
+ gap: "5px", marginTop: "20px",
541
+ fontSize: "11px", color: "#98A2B3",
542
+ }}>
543
+ <LockIcon size={11} />
544
+ {t("EKYC_SECURE_DATA_NOTICE") || "Your data is encrypted and secure"}
433
545
  </div>
546
+
434
547
  </Card>
435
548
  </div>
436
549
  </div>
437
550
  );
438
551
  };
439
552
 
440
- export default AadhaarVerification;
553
+ export default AadhaarVerification;