@redacto.io/consent-sdk-react 3.5.0 → 4.0.0
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/.turbo/turbo-build.log +21 -0
- package/CHANGELOG.md +6 -0
- package/dist/index.d.mts +49 -2
- package/dist/index.d.ts +49 -2
- package/dist/index.js +1785 -243
- package/dist/index.mjs +1784 -243
- package/package.json +1 -1
- package/src/RedactoNoticeConsent/RedactoNoticeConsent.test.tsx +201 -118
- package/src/RedactoNoticeConsent/RedactoNoticeConsent.tsx +1192 -93
- package/src/RedactoNoticeConsent/api/index.ts +333 -206
- package/src/RedactoNoticeConsent/api/types.ts +138 -16
- package/src/RedactoNoticeConsent/components/DigiLockerCallback.tsx +536 -0
- package/src/RedactoNoticeConsent/components/index.ts +7 -0
- package/src/RedactoNoticeConsent/injectStyles.ts +11 -0
- package/src/RedactoNoticeConsent/services/storage.ts +122 -0
- package/src/RedactoNoticeConsent/types.ts +2 -0
- package/src/index.ts +10 -0
package/dist/index.js
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var src_exports = {};
|
|
22
22
|
__export(src_exports, {
|
|
23
|
+
DigiLockerCallback: () => DigiLockerCallback,
|
|
23
24
|
RedactoNoticeConsent: () => RedactoNoticeConsent,
|
|
24
25
|
RedactoNoticeConsentInline: () => RedactoConsentInline
|
|
25
26
|
});
|
|
@@ -66,73 +67,66 @@ var fetchConsentContent = async ({
|
|
|
66
67
|
validate_against = "all",
|
|
67
68
|
include_fully_consented_data = false,
|
|
68
69
|
signal
|
|
69
|
-
// AbortSignal for request cancellation
|
|
70
70
|
}) => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return cachedData;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
const url = new URL(
|
|
92
|
-
`${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/notices/${noticeId}`
|
|
93
|
-
);
|
|
94
|
-
if (specific_uuid) {
|
|
95
|
-
url.searchParams.append("specific_uuid", specific_uuid);
|
|
96
|
-
}
|
|
97
|
-
url.searchParams.append("validate_against", validate_against);
|
|
98
|
-
if (include_fully_consented_data) {
|
|
99
|
-
url.searchParams.append("include_fully_consented_data", "true");
|
|
100
|
-
}
|
|
101
|
-
const response = await fetch(url.toString(), {
|
|
102
|
-
method: "GET",
|
|
103
|
-
headers: {
|
|
104
|
-
Authorization: `Bearer ${accessToken}`,
|
|
105
|
-
"Accept-Language": language,
|
|
106
|
-
"Content-Type": "application/json"
|
|
107
|
-
},
|
|
108
|
-
signal
|
|
109
|
-
// Add abort signal for request cancellation
|
|
110
|
-
});
|
|
111
|
-
if (!response.ok) {
|
|
112
|
-
let errorMessage = `Failed to fetch consent content: ${response.status} ${response.statusText}`;
|
|
113
|
-
if (response.status === 401) {
|
|
114
|
-
errorMessage = "Unauthorized: Invalid or expired token";
|
|
115
|
-
} else if (response.status === 403) {
|
|
116
|
-
errorMessage = "Forbidden: Access denied";
|
|
117
|
-
} else if (response.status === 404) {
|
|
118
|
-
errorMessage = "Notice not found";
|
|
119
|
-
} else if (response.status === 409) {
|
|
120
|
-
errorMessage = "User has already provided consent";
|
|
121
|
-
} else if (response.status >= 500) {
|
|
122
|
-
errorMessage = "Server error: Please try again later";
|
|
123
|
-
}
|
|
124
|
-
const error = new Error(errorMessage);
|
|
125
|
-
error.status = response.status;
|
|
126
|
-
throw error;
|
|
71
|
+
if (!noticeId || !accessToken || !validate_against) {
|
|
72
|
+
throw new Error("noticeId and accessToken are required");
|
|
73
|
+
}
|
|
74
|
+
const decodedToken = decodeTokenSafely(accessToken);
|
|
75
|
+
if (!decodedToken) {
|
|
76
|
+
throw new Error("Invalid access token");
|
|
77
|
+
}
|
|
78
|
+
const { organisation_uuid: ORGANISATION_UUID, workspace_uuid: WORKSPACE_UUID } = decodedToken;
|
|
79
|
+
if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
|
|
80
|
+
throw new Error("Invalid token: missing organization or workspace UUID");
|
|
81
|
+
}
|
|
82
|
+
const apiBaseUrl = baseUrl || BASE_URL;
|
|
83
|
+
const cacheKey = `${accessToken}-${noticeId}-${validate_against}-${language}-${specific_uuid || ""}-${include_fully_consented_data}`;
|
|
84
|
+
if (validate_against === "all" && !specific_uuid) {
|
|
85
|
+
const cachedData = getCachedData(cacheKey);
|
|
86
|
+
if (cachedData) {
|
|
87
|
+
return cachedData;
|
|
127
88
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
89
|
+
}
|
|
90
|
+
const url = new URL(
|
|
91
|
+
`${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/notices/${noticeId}`
|
|
92
|
+
);
|
|
93
|
+
if (specific_uuid) {
|
|
94
|
+
url.searchParams.append("specific_uuid", specific_uuid);
|
|
95
|
+
}
|
|
96
|
+
url.searchParams.append("validate_against", validate_against);
|
|
97
|
+
if (include_fully_consented_data) {
|
|
98
|
+
url.searchParams.append("include_fully_consented_data", "true");
|
|
99
|
+
}
|
|
100
|
+
const response = await fetch(url.toString(), {
|
|
101
|
+
method: "GET",
|
|
102
|
+
headers: {
|
|
103
|
+
Authorization: `Bearer ${accessToken}`,
|
|
104
|
+
"Accept-Language": language
|
|
105
|
+
},
|
|
106
|
+
signal
|
|
107
|
+
});
|
|
108
|
+
if (!response.ok) {
|
|
109
|
+
let errorMessage = `Failed to fetch consent content: ${response.status} ${response.statusText}`;
|
|
110
|
+
if (response.status === 401) {
|
|
111
|
+
errorMessage = "Unauthorized: Invalid or expired token";
|
|
112
|
+
} else if (response.status === 403) {
|
|
113
|
+
errorMessage = "Forbidden: Access denied";
|
|
114
|
+
} else if (response.status === 404) {
|
|
115
|
+
errorMessage = "Notice not found";
|
|
116
|
+
} else if (response.status === 409) {
|
|
117
|
+
errorMessage = "User has already provided consent";
|
|
118
|
+
} else if (response.status >= 500) {
|
|
119
|
+
errorMessage = "Server error: Please try again later";
|
|
131
120
|
}
|
|
132
|
-
|
|
133
|
-
|
|
121
|
+
const error = new Error(errorMessage);
|
|
122
|
+
error.status = response.status;
|
|
134
123
|
throw error;
|
|
135
124
|
}
|
|
125
|
+
const data = await response.json();
|
|
126
|
+
if (validate_against === "all" && !specific_uuid) {
|
|
127
|
+
setCachedData(cacheKey, data);
|
|
128
|
+
}
|
|
129
|
+
return data;
|
|
136
130
|
};
|
|
137
131
|
var submitConsentEvent = async ({
|
|
138
132
|
accessToken,
|
|
@@ -141,100 +135,151 @@ var submitConsentEvent = async ({
|
|
|
141
135
|
purposes,
|
|
142
136
|
declined,
|
|
143
137
|
meta_data,
|
|
138
|
+
guardianVerificationReference,
|
|
139
|
+
selfDeclaredAdult,
|
|
144
140
|
signal
|
|
145
|
-
// AbortSignal for request cancellation
|
|
146
141
|
}) => {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
142
|
+
if (!noticeUuid || !accessToken || !Array.isArray(purposes)) {
|
|
143
|
+
throw new Error("noticeUuid, accessToken, and purposes array are required");
|
|
144
|
+
}
|
|
145
|
+
const decodedToken = decodeTokenSafely(accessToken);
|
|
146
|
+
if (!decodedToken) {
|
|
147
|
+
throw new Error("Invalid access token");
|
|
148
|
+
}
|
|
149
|
+
const { organisation_uuid: ORGANISATION_UUID, workspace_uuid: WORKSPACE_UUID } = decodedToken;
|
|
150
|
+
if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
|
|
151
|
+
throw new Error("Invalid token: missing organization or workspace UUID");
|
|
152
|
+
}
|
|
153
|
+
const apiBaseUrl = baseUrl || BASE_URL;
|
|
154
|
+
const validatedPurposes = purposes.map((purpose) => {
|
|
155
|
+
if (!purpose.uuid) {
|
|
156
|
+
throw new Error(`Invalid purpose data: missing uuid`);
|
|
158
157
|
}
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}));
|
|
168
|
-
return {
|
|
169
|
-
purpose_uuid: purpose.uuid,
|
|
170
|
-
selected: Boolean(purpose.selected),
|
|
171
|
-
data_elements: dataElements.length > 0 ? dataElements : void 0
|
|
172
|
-
};
|
|
173
|
-
});
|
|
174
|
-
const payload = {
|
|
175
|
-
notice_uuid: noticeUuid,
|
|
176
|
-
purposes: validatedPurposes,
|
|
177
|
-
select_all_mandatory: false,
|
|
178
|
-
source: "WEB",
|
|
179
|
-
declined: Boolean(declined),
|
|
180
|
-
meta_data: meta_data ? { specific_uuid: meta_data.specific_uuid } : void 0
|
|
158
|
+
const dataElements = (purpose.data_elements || []).filter((element) => element.enabled).map((element) => ({
|
|
159
|
+
uuid: element.uuid,
|
|
160
|
+
selected: element.required ? true : Boolean(element.selected)
|
|
161
|
+
}));
|
|
162
|
+
return {
|
|
163
|
+
purpose_uuid: purpose.uuid,
|
|
164
|
+
selected: Boolean(purpose.selected),
|
|
165
|
+
data_elements: dataElements.length > 0 ? dataElements : void 0
|
|
181
166
|
};
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
167
|
+
});
|
|
168
|
+
const payload = {
|
|
169
|
+
notice_uuid: noticeUuid,
|
|
170
|
+
purposes: validatedPurposes,
|
|
171
|
+
select_all_mandatory: false,
|
|
172
|
+
source: "WEB",
|
|
173
|
+
declined: Boolean(declined),
|
|
174
|
+
meta_data: meta_data ? { specific_uuid: meta_data.specific_uuid, minor_age: meta_data.minor_age } : void 0,
|
|
175
|
+
guardian_verification_reference: guardianVerificationReference,
|
|
176
|
+
self_declared_adult: selfDeclaredAdult
|
|
177
|
+
};
|
|
178
|
+
const response = await fetch(
|
|
179
|
+
`${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/submit-consent`,
|
|
180
|
+
{
|
|
181
|
+
method: "POST",
|
|
182
|
+
headers: {
|
|
183
|
+
Authorization: `Bearer ${accessToken}`,
|
|
184
|
+
"Content-Type": "application/json"
|
|
185
|
+
},
|
|
186
|
+
body: JSON.stringify(payload),
|
|
187
|
+
signal
|
|
188
|
+
}
|
|
189
|
+
);
|
|
190
|
+
if (!response.ok) {
|
|
191
|
+
let errorMessage = `Failed to submit consent: ${response.status} ${response.statusText}`;
|
|
192
|
+
if (response.status === 400) {
|
|
193
|
+
try {
|
|
194
|
+
const errorData = await response.json();
|
|
195
|
+
errorMessage = errorData.message || "Invalid request data";
|
|
196
|
+
} catch {
|
|
198
197
|
errorMessage = "Invalid request data";
|
|
199
|
-
} else if (response.status === 401) {
|
|
200
|
-
errorMessage = "Unauthorized: Invalid or expired token";
|
|
201
|
-
} else if (response.status === 403) {
|
|
202
|
-
errorMessage = "Forbidden: Access denied";
|
|
203
|
-
} else if (response.status === 404) {
|
|
204
|
-
errorMessage = "Notice not found";
|
|
205
|
-
} else if (response.status >= 500) {
|
|
206
|
-
errorMessage = "Server error: Please try again later";
|
|
207
198
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
199
|
+
} else if (response.status === 401) {
|
|
200
|
+
errorMessage = "Unauthorized: Invalid or expired token";
|
|
201
|
+
} else if (response.status === 403) {
|
|
202
|
+
errorMessage = "Forbidden: Access denied";
|
|
203
|
+
} else if (response.status === 404) {
|
|
204
|
+
errorMessage = "Notice not found";
|
|
205
|
+
} else if (response.status >= 500) {
|
|
206
|
+
errorMessage = "Server error: Please try again later";
|
|
211
207
|
}
|
|
212
|
-
|
|
213
|
-
|
|
208
|
+
const error = new Error(errorMessage);
|
|
209
|
+
error.status = response.status;
|
|
210
|
+
throw error;
|
|
211
|
+
}
|
|
212
|
+
apiCache.clear();
|
|
213
|
+
};
|
|
214
|
+
var fetchTTSAudioUrls = async ({
|
|
215
|
+
accessToken,
|
|
216
|
+
baseUrl,
|
|
217
|
+
noticeUuid,
|
|
218
|
+
language,
|
|
219
|
+
signal
|
|
220
|
+
}) => {
|
|
221
|
+
if (!accessToken || !noticeUuid || !language) {
|
|
222
|
+
throw new Error("accessToken, noticeUuid, and language are required");
|
|
223
|
+
}
|
|
224
|
+
const decodedToken = decodeTokenSafely(accessToken);
|
|
225
|
+
if (!decodedToken) {
|
|
226
|
+
throw new Error("Invalid access token");
|
|
227
|
+
}
|
|
228
|
+
const { organisation_uuid: ORGANISATION_UUID, workspace_uuid: WORKSPACE_UUID } = decodedToken;
|
|
229
|
+
if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
|
|
230
|
+
throw new Error("Invalid token: missing organization or workspace UUID");
|
|
231
|
+
}
|
|
232
|
+
const apiBaseUrl = baseUrl || BASE_URL;
|
|
233
|
+
const url = `${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/notices/${noticeUuid}/audio/${language}`;
|
|
234
|
+
const response = await fetch(url, {
|
|
235
|
+
method: "GET",
|
|
236
|
+
headers: {
|
|
237
|
+
Authorization: `Bearer ${accessToken}`,
|
|
238
|
+
Accept: "application/json"
|
|
239
|
+
},
|
|
240
|
+
signal
|
|
241
|
+
});
|
|
242
|
+
if (!response.ok) {
|
|
243
|
+
let errorMessage = `Failed to fetch TTS audio URLs: ${response.status} ${response.statusText}`;
|
|
244
|
+
if (response.status === 401) {
|
|
245
|
+
errorMessage = "Unauthorized: Invalid or expired token";
|
|
246
|
+
} else if (response.status === 403) {
|
|
247
|
+
errorMessage = "Forbidden: Access denied";
|
|
248
|
+
} else if (response.status === 404) {
|
|
249
|
+
errorMessage = "Notice or audio not found";
|
|
250
|
+
} else if (response.status >= 500) {
|
|
251
|
+
errorMessage = "Server error: Please try again later";
|
|
252
|
+
}
|
|
253
|
+
const error = new Error(errorMessage);
|
|
254
|
+
error.status = response.status;
|
|
214
255
|
throw error;
|
|
215
256
|
}
|
|
257
|
+
const data = await response.json();
|
|
258
|
+
return data;
|
|
216
259
|
};
|
|
217
|
-
var
|
|
260
|
+
var initiateGuardianVerification = async ({
|
|
218
261
|
accessToken,
|
|
219
262
|
baseUrl,
|
|
220
263
|
guardianName,
|
|
221
264
|
guardianContact,
|
|
222
265
|
guardianRelationship,
|
|
266
|
+
frontendCallbackUrl,
|
|
267
|
+
metadata,
|
|
223
268
|
signal
|
|
224
|
-
// AbortSignal for request cancellation
|
|
225
269
|
}) => {
|
|
270
|
+
var _a;
|
|
226
271
|
try {
|
|
227
272
|
if (!accessToken) {
|
|
228
273
|
throw new Error("accessToken is required");
|
|
229
274
|
}
|
|
230
275
|
if (!(guardianName == null ? void 0 : guardianName.trim())) {
|
|
231
|
-
throw new Error("
|
|
276
|
+
throw new Error("Guardian name is required");
|
|
232
277
|
}
|
|
233
278
|
if (!(guardianContact == null ? void 0 : guardianContact.trim())) {
|
|
234
|
-
throw new Error("
|
|
279
|
+
throw new Error("Guardian contact is required");
|
|
235
280
|
}
|
|
236
281
|
if (!(guardianRelationship == null ? void 0 : guardianRelationship.trim())) {
|
|
237
|
-
throw new Error("
|
|
282
|
+
throw new Error("Guardian relationship is required");
|
|
238
283
|
}
|
|
239
284
|
const decodedToken = decodeTokenSafely(accessToken);
|
|
240
285
|
if (!decodedToken) {
|
|
@@ -244,14 +289,20 @@ var submitGuardianInfo = async ({
|
|
|
244
289
|
if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
|
|
245
290
|
throw new Error("Invalid token: missing organization or workspace UUID");
|
|
246
291
|
}
|
|
292
|
+
const apiBaseUrl = baseUrl || BASE_URL;
|
|
247
293
|
const payload = {
|
|
248
294
|
guardian_name: guardianName.trim(),
|
|
249
295
|
guardian_contact: guardianContact.trim(),
|
|
250
296
|
guardian_relationship: guardianRelationship.trim()
|
|
251
297
|
};
|
|
252
|
-
|
|
298
|
+
if (frontendCallbackUrl) {
|
|
299
|
+
payload.frontend_callback_url = frontendCallbackUrl;
|
|
300
|
+
}
|
|
301
|
+
if (metadata) {
|
|
302
|
+
payload.metadata = metadata;
|
|
303
|
+
}
|
|
253
304
|
const response = await fetch(
|
|
254
|
-
`${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/guardian-
|
|
305
|
+
`${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/guardian/initiate-verification`,
|
|
255
306
|
{
|
|
256
307
|
method: "POST",
|
|
257
308
|
headers: {
|
|
@@ -260,24 +311,26 @@ var submitGuardianInfo = async ({
|
|
|
260
311
|
},
|
|
261
312
|
body: JSON.stringify(payload),
|
|
262
313
|
signal
|
|
263
|
-
// Add abort signal for request cancellation
|
|
264
314
|
}
|
|
265
315
|
);
|
|
266
316
|
if (!response.ok) {
|
|
267
|
-
let errorMessage = `Failed to
|
|
317
|
+
let errorMessage = `Failed to initiate verification: ${response.status} ${response.statusText}`;
|
|
268
318
|
if (response.status === 400) {
|
|
269
|
-
|
|
319
|
+
try {
|
|
320
|
+
const errorData = await response.json();
|
|
321
|
+
errorMessage = errorData.message || "Invalid request data";
|
|
322
|
+
} catch {
|
|
323
|
+
errorMessage = "Invalid request data";
|
|
324
|
+
}
|
|
270
325
|
} else if (response.status === 401) {
|
|
271
326
|
errorMessage = "Unauthorized: Invalid or expired token";
|
|
272
|
-
} else if (response.status === 403) {
|
|
273
|
-
errorMessage = "Forbidden: Access denied";
|
|
274
327
|
} else if (response.status === 404) {
|
|
275
328
|
errorMessage = "Organization or workspace not found";
|
|
276
329
|
} else if (response.status === 422) {
|
|
277
330
|
try {
|
|
278
331
|
const errorData = await response.json();
|
|
279
|
-
errorMessage = errorData.message || "Validation error";
|
|
280
|
-
} catch
|
|
332
|
+
errorMessage = errorData.message || "Validation error: Please check your input";
|
|
333
|
+
} catch {
|
|
281
334
|
errorMessage = "Validation error: Please check your input";
|
|
282
335
|
}
|
|
283
336
|
} else if (response.status >= 500) {
|
|
@@ -287,63 +340,98 @@ var submitGuardianInfo = async ({
|
|
|
287
340
|
error.status = response.status;
|
|
288
341
|
throw error;
|
|
289
342
|
}
|
|
343
|
+
const responseData = await response.json();
|
|
344
|
+
const detail = responseData.detail || responseData;
|
|
345
|
+
if (detail.already_verified) {
|
|
346
|
+
return {
|
|
347
|
+
success: true,
|
|
348
|
+
guardian_info_uuid: detail.guardian_info_uuid,
|
|
349
|
+
already_verified: true,
|
|
350
|
+
verification_reference: detail.verification_reference
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
if (!detail.session_token || !detail.digilocker_redirect_url) {
|
|
354
|
+
throw new Error("Invalid response: missing session_token or digilocker_redirect_url");
|
|
355
|
+
}
|
|
356
|
+
return {
|
|
357
|
+
success: (_a = detail.success) != null ? _a : true,
|
|
358
|
+
guardian_info_uuid: detail.guardian_info_uuid,
|
|
359
|
+
already_verified: false,
|
|
360
|
+
session_token: detail.session_token,
|
|
361
|
+
digilocker_redirect_url: detail.digilocker_redirect_url,
|
|
362
|
+
expires_at: detail.expires_at
|
|
363
|
+
};
|
|
290
364
|
} catch (error) {
|
|
291
|
-
console.error("Error
|
|
365
|
+
console.error("Error initiating guardian verification:", error instanceof Error ? error.message : error);
|
|
292
366
|
throw error;
|
|
293
367
|
}
|
|
294
368
|
};
|
|
295
|
-
var
|
|
369
|
+
var verifyGuardianStatus = async ({
|
|
296
370
|
accessToken,
|
|
297
371
|
baseUrl,
|
|
298
|
-
|
|
299
|
-
language,
|
|
372
|
+
sessionToken,
|
|
300
373
|
signal
|
|
301
|
-
// AbortSignal for request cancellation
|
|
302
374
|
}) => {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
375
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
376
|
+
if (!accessToken || !sessionToken) {
|
|
377
|
+
throw new Error("accessToken and sessionToken are required");
|
|
378
|
+
}
|
|
379
|
+
const decodedToken = decodeTokenSafely(accessToken);
|
|
380
|
+
if (!decodedToken) {
|
|
381
|
+
throw new Error("Invalid access token");
|
|
382
|
+
}
|
|
383
|
+
const { organisation_uuid: ORGANISATION_UUID, workspace_uuid: WORKSPACE_UUID } = decodedToken;
|
|
384
|
+
if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
|
|
385
|
+
throw new Error("Invalid token: missing organization or workspace UUID");
|
|
386
|
+
}
|
|
387
|
+
const apiBaseUrl = baseUrl || BASE_URL;
|
|
388
|
+
const response = await fetch(
|
|
389
|
+
`${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/guardian/verify-status`,
|
|
390
|
+
{
|
|
391
|
+
method: "POST",
|
|
319
392
|
headers: {
|
|
320
393
|
Authorization: `Bearer ${accessToken}`,
|
|
321
|
-
Accept: "application/json",
|
|
322
394
|
"Content-Type": "application/json"
|
|
323
395
|
},
|
|
396
|
+
body: JSON.stringify({
|
|
397
|
+
session_token: sessionToken
|
|
398
|
+
}),
|
|
324
399
|
signal
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
errorMessage =
|
|
333
|
-
}
|
|
334
|
-
errorMessage = "
|
|
335
|
-
} else if (response.status >= 500) {
|
|
336
|
-
errorMessage = "Server error: Please try again later";
|
|
400
|
+
}
|
|
401
|
+
);
|
|
402
|
+
if (!response.ok) {
|
|
403
|
+
let errorMessage = `Failed to check verification status: ${response.status} ${response.statusText}`;
|
|
404
|
+
if (response.status === 400) {
|
|
405
|
+
try {
|
|
406
|
+
const errorData = await response.json();
|
|
407
|
+
errorMessage = errorData.message || ((_a = errorData.detail) == null ? void 0 : _a.message) || "Invalid session token";
|
|
408
|
+
} catch {
|
|
409
|
+
errorMessage = "Invalid session token";
|
|
337
410
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
411
|
+
} else if (response.status === 401) {
|
|
412
|
+
errorMessage = "Unauthorized: Invalid or expired token";
|
|
413
|
+
} else if (response.status === 404) {
|
|
414
|
+
errorMessage = "Verification session not found or expired. Please restart the verification process.";
|
|
415
|
+
} else if (response.status === 410) {
|
|
416
|
+
errorMessage = "Verification session has expired. Please restart the verification process.";
|
|
417
|
+
} else if (response.status >= 500) {
|
|
418
|
+
errorMessage = "Server error: Please try again later";
|
|
341
419
|
}
|
|
342
|
-
const
|
|
343
|
-
|
|
344
|
-
} catch (error) {
|
|
420
|
+
const error = new Error(errorMessage);
|
|
421
|
+
error.status = response.status;
|
|
345
422
|
throw error;
|
|
346
423
|
}
|
|
424
|
+
const responseData = await response.json();
|
|
425
|
+
const detail = responseData.detail || responseData;
|
|
426
|
+
return {
|
|
427
|
+
status: (_b = detail.status) != null ? _b : "in_progress",
|
|
428
|
+
guardian_info_uuid: (_c = detail.guardian_info_uuid) != null ? _c : null,
|
|
429
|
+
verification_reference: (_d = detail.verification_reference) != null ? _d : null,
|
|
430
|
+
guardian_details: (_e = detail.guardian_details) != null ? _e : null,
|
|
431
|
+
error: (_f = detail.error) != null ? _f : null,
|
|
432
|
+
error_code: (_g = detail.error_code) != null ? _g : null,
|
|
433
|
+
can_retry: (_h = detail.can_retry) != null ? _h : true
|
|
434
|
+
};
|
|
347
435
|
};
|
|
348
436
|
|
|
349
437
|
// src/RedactoNoticeConsent/assets/redacto-logo.png
|
|
@@ -491,6 +579,17 @@ var injectCheckboxStyles = () => {
|
|
|
491
579
|
outline: 3px solid #FFF9C4 !important;
|
|
492
580
|
outline-offset: 2px !important;
|
|
493
581
|
}
|
|
582
|
+
|
|
583
|
+
/* Spinner animation for verification screens */
|
|
584
|
+
@keyframes spin {
|
|
585
|
+
from { transform: rotate(0deg); }
|
|
586
|
+
to { transform: rotate(360deg); }
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/* DigiLocker callback retry button hover */
|
|
590
|
+
.redacto-dl-retry-btn:hover {
|
|
591
|
+
background-color: #2563eb !important;
|
|
592
|
+
}
|
|
494
593
|
`;
|
|
495
594
|
document.head.appendChild(style);
|
|
496
595
|
stylesInjected = true;
|
|
@@ -873,6 +972,69 @@ var useMediaQuery = (query) => {
|
|
|
873
972
|
return matches;
|
|
874
973
|
};
|
|
875
974
|
|
|
975
|
+
// src/RedactoNoticeConsent/services/storage.ts
|
|
976
|
+
var STORAGE_KEY = "redacto_consent_sdk_state";
|
|
977
|
+
var STATE_EXPIRY_MS = 30 * 60 * 1e3;
|
|
978
|
+
var isBrowser = () => {
|
|
979
|
+
return typeof window !== "undefined" && typeof window.sessionStorage !== "undefined";
|
|
980
|
+
};
|
|
981
|
+
var saveConsentState = (state) => {
|
|
982
|
+
if (!isBrowser()) {
|
|
983
|
+
console.warn("SessionStorage not available - state not persisted");
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
try {
|
|
987
|
+
const stateWithTimestamp = {
|
|
988
|
+
...state,
|
|
989
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
990
|
+
};
|
|
991
|
+
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(stateWithTimestamp));
|
|
992
|
+
} catch (error) {
|
|
993
|
+
console.error("Failed to save consent state:", error);
|
|
994
|
+
}
|
|
995
|
+
};
|
|
996
|
+
var getConsentState = () => {
|
|
997
|
+
if (!isBrowser()) {
|
|
998
|
+
return null;
|
|
999
|
+
}
|
|
1000
|
+
try {
|
|
1001
|
+
const savedState = sessionStorage.getItem(STORAGE_KEY);
|
|
1002
|
+
if (!savedState) {
|
|
1003
|
+
return null;
|
|
1004
|
+
}
|
|
1005
|
+
const parsed = JSON.parse(savedState);
|
|
1006
|
+
const stateAge = Date.now() - new Date(parsed.timestamp).getTime();
|
|
1007
|
+
if (stateAge > STATE_EXPIRY_MS) {
|
|
1008
|
+
clearConsentState();
|
|
1009
|
+
return null;
|
|
1010
|
+
}
|
|
1011
|
+
return parsed;
|
|
1012
|
+
} catch (error) {
|
|
1013
|
+
console.error("Failed to get consent state:", error);
|
|
1014
|
+
return null;
|
|
1015
|
+
}
|
|
1016
|
+
};
|
|
1017
|
+
var clearConsentState = () => {
|
|
1018
|
+
if (!isBrowser()) {
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
1021
|
+
try {
|
|
1022
|
+
sessionStorage.removeItem(STORAGE_KEY);
|
|
1023
|
+
} catch (error) {
|
|
1024
|
+
console.error("Failed to clear consent state:", error);
|
|
1025
|
+
}
|
|
1026
|
+
};
|
|
1027
|
+
var updateConsentState = (updates) => {
|
|
1028
|
+
const currentState = getConsentState();
|
|
1029
|
+
if (currentState) {
|
|
1030
|
+
saveConsentState({
|
|
1031
|
+
...currentState,
|
|
1032
|
+
...updates,
|
|
1033
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1034
|
+
});
|
|
1035
|
+
}
|
|
1036
|
+
};
|
|
1037
|
+
|
|
876
1038
|
// src/RedactoNoticeConsent/RedactoNoticeConsent.tsx
|
|
877
1039
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
878
1040
|
var PurposeItem = ({
|
|
@@ -1180,6 +1342,12 @@ var PurposeItem = ({
|
|
|
1180
1342
|
)
|
|
1181
1343
|
] }, purpose.uuid);
|
|
1182
1344
|
};
|
|
1345
|
+
var RELATIONSHIP_OPTIONS = [
|
|
1346
|
+
{ value: "Father", label: "Father" },
|
|
1347
|
+
{ value: "Mother", label: "Mother" },
|
|
1348
|
+
{ value: "Legal Guardian", label: "Legal Guardian" },
|
|
1349
|
+
{ value: "Grandparent", label: "Grandparent" }
|
|
1350
|
+
];
|
|
1183
1351
|
var GuardianForm = ({
|
|
1184
1352
|
formData,
|
|
1185
1353
|
errors,
|
|
@@ -1196,34 +1364,128 @@ var GuardianForm = ({
|
|
|
1196
1364
|
declineButtonStyle,
|
|
1197
1365
|
logoUrl
|
|
1198
1366
|
}) => {
|
|
1367
|
+
var _a, _b, _c, _d, _e;
|
|
1368
|
+
const [isDropdownOpen, setIsDropdownOpen] = (0, import_react2.useState)(false);
|
|
1369
|
+
const [focusedIndex, setFocusedIndex] = (0, import_react2.useState)(-1);
|
|
1370
|
+
const [openUpward, setOpenUpward] = (0, import_react2.useState)(false);
|
|
1371
|
+
const dropdownRef = (0, import_react2.useRef)(null);
|
|
1372
|
+
const optionsRef = (0, import_react2.useRef)(null);
|
|
1373
|
+
(0, import_react2.useEffect)(() => {
|
|
1374
|
+
if (!isDropdownOpen) return;
|
|
1375
|
+
const handleClickOutside = (e) => {
|
|
1376
|
+
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
1377
|
+
setIsDropdownOpen(false);
|
|
1378
|
+
setFocusedIndex(-1);
|
|
1379
|
+
}
|
|
1380
|
+
};
|
|
1381
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1382
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1383
|
+
}, [isDropdownOpen]);
|
|
1384
|
+
(0, import_react2.useEffect)(() => {
|
|
1385
|
+
if (!isDropdownOpen || !dropdownRef.current) return;
|
|
1386
|
+
const rect = dropdownRef.current.getBoundingClientRect();
|
|
1387
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
1388
|
+
const dropdownHeight = 220;
|
|
1389
|
+
setOpenUpward(spaceBelow < dropdownHeight && rect.top > dropdownHeight);
|
|
1390
|
+
}, [isDropdownOpen]);
|
|
1391
|
+
const handleSelect = (value) => {
|
|
1392
|
+
onChange("guardianRelationship", value);
|
|
1393
|
+
setIsDropdownOpen(false);
|
|
1394
|
+
setFocusedIndex(-1);
|
|
1395
|
+
};
|
|
1396
|
+
const handleKeyDown = (e) => {
|
|
1397
|
+
if (!isDropdownOpen) {
|
|
1398
|
+
if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
|
|
1399
|
+
e.preventDefault();
|
|
1400
|
+
setIsDropdownOpen(true);
|
|
1401
|
+
setFocusedIndex(0);
|
|
1402
|
+
}
|
|
1403
|
+
return;
|
|
1404
|
+
}
|
|
1405
|
+
switch (e.key) {
|
|
1406
|
+
case "ArrowDown":
|
|
1407
|
+
e.preventDefault();
|
|
1408
|
+
setFocusedIndex((prev) => Math.min(prev + 1, RELATIONSHIP_OPTIONS.length - 1));
|
|
1409
|
+
break;
|
|
1410
|
+
case "ArrowUp":
|
|
1411
|
+
e.preventDefault();
|
|
1412
|
+
setFocusedIndex((prev) => Math.max(prev - 1, 0));
|
|
1413
|
+
break;
|
|
1414
|
+
case "Enter":
|
|
1415
|
+
case " ":
|
|
1416
|
+
e.preventDefault();
|
|
1417
|
+
if (focusedIndex >= 0) handleSelect(RELATIONSHIP_OPTIONS[focusedIndex].value);
|
|
1418
|
+
break;
|
|
1419
|
+
case "Escape":
|
|
1420
|
+
case "Tab":
|
|
1421
|
+
setIsDropdownOpen(false);
|
|
1422
|
+
setFocusedIndex(-1);
|
|
1423
|
+
break;
|
|
1424
|
+
}
|
|
1425
|
+
};
|
|
1426
|
+
(0, import_react2.useEffect)(() => {
|
|
1427
|
+
var _a2;
|
|
1428
|
+
if (focusedIndex >= 0 && optionsRef.current) {
|
|
1429
|
+
const option = optionsRef.current.children[focusedIndex];
|
|
1430
|
+
(_a2 = option == null ? void 0 : option.scrollIntoView) == null ? void 0 : _a2.call(option, { block: "nearest" });
|
|
1431
|
+
}
|
|
1432
|
+
}, [focusedIndex]);
|
|
1433
|
+
const borderColor = (settings == null ? void 0 : settings.borderColor) || "#d0d5dd";
|
|
1434
|
+
const textColor = (settings == null ? void 0 : settings.textColor) || "#344054";
|
|
1435
|
+
const bgColor = (settings == null ? void 0 : settings.backgroundColor) || "#ffffff";
|
|
1436
|
+
const radius = (settings == null ? void 0 : settings.borderRadius) || "8px";
|
|
1437
|
+
const font = (settings == null ? void 0 : settings.font) || "inherit";
|
|
1199
1438
|
const inputStyle = {
|
|
1200
1439
|
width: "100%",
|
|
1201
1440
|
padding: "10px 12px",
|
|
1202
|
-
border: `1px solid ${
|
|
1203
|
-
borderRadius:
|
|
1441
|
+
border: `1px solid ${borderColor}`,
|
|
1442
|
+
borderRadius: radius,
|
|
1204
1443
|
fontSize: "13px",
|
|
1205
|
-
fontFamily:
|
|
1206
|
-
color:
|
|
1207
|
-
backgroundColor:
|
|
1208
|
-
marginBottom: "
|
|
1209
|
-
boxSizing: "border-box"
|
|
1444
|
+
fontFamily: font,
|
|
1445
|
+
color: textColor,
|
|
1446
|
+
backgroundColor: bgColor,
|
|
1447
|
+
marginBottom: "2px",
|
|
1448
|
+
boxSizing: "border-box",
|
|
1449
|
+
outline: "none"
|
|
1210
1450
|
};
|
|
1211
1451
|
const errorStyle = {
|
|
1212
1452
|
color: "#DC2626",
|
|
1213
|
-
fontSize: "
|
|
1453
|
+
fontSize: "11px",
|
|
1214
1454
|
marginTop: "4px",
|
|
1215
|
-
marginBottom: "
|
|
1455
|
+
marginBottom: "0px"
|
|
1216
1456
|
};
|
|
1217
1457
|
const labelStyle = {
|
|
1218
1458
|
...componentTextStyle,
|
|
1219
1459
|
fontSize: "13px",
|
|
1220
1460
|
fontWeight: "500",
|
|
1221
|
-
marginBottom: "
|
|
1461
|
+
marginBottom: "4px",
|
|
1222
1462
|
display: "block"
|
|
1223
1463
|
};
|
|
1464
|
+
const hintStyle = {
|
|
1465
|
+
fontSize: "11px",
|
|
1466
|
+
color: "#667085",
|
|
1467
|
+
marginTop: "2px",
|
|
1468
|
+
marginBottom: "0px",
|
|
1469
|
+
lineHeight: "1.4"
|
|
1470
|
+
};
|
|
1471
|
+
const infoBannerStyle = {
|
|
1472
|
+
display: "flex",
|
|
1473
|
+
alignItems: "flex-start",
|
|
1474
|
+
gap: "8px",
|
|
1475
|
+
padding: "10px 12px",
|
|
1476
|
+
backgroundColor: "#EFF6FF",
|
|
1477
|
+
border: "1px solid #BFDBFE",
|
|
1478
|
+
borderRadius: radius,
|
|
1479
|
+
marginBottom: "16px",
|
|
1480
|
+
fontSize: "12px",
|
|
1481
|
+
lineHeight: "1.5",
|
|
1482
|
+
color: "#1E40AF"
|
|
1483
|
+
};
|
|
1484
|
+
const selectedLabel = (_a = RELATIONSHIP_OPTIONS.find((o) => o.value === formData.guardianRelationship)) == null ? void 0 : _a.label;
|
|
1485
|
+
const hasError = Boolean(errors.guardianRelationship);
|
|
1224
1486
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1225
1487
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...styles3.topSection, ...componentTextStyle }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles3.topLeft, children: [
|
|
1226
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { style: styles3.logo, src: logoUrl, alt: "
|
|
1488
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { style: styles3.logo, src: logoUrl, alt: "Logo" }),
|
|
1227
1489
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1228
1490
|
"h2",
|
|
1229
1491
|
{
|
|
@@ -1235,7 +1497,7 @@ var GuardianForm = ({
|
|
|
1235
1497
|
fontSize: "16px",
|
|
1236
1498
|
fontWeight: 600
|
|
1237
1499
|
},
|
|
1238
|
-
children: "Guardian
|
|
1500
|
+
children: "Guardian Verification"
|
|
1239
1501
|
}
|
|
1240
1502
|
)
|
|
1241
1503
|
] }) }),
|
|
@@ -1255,31 +1517,49 @@ var GuardianForm = ({
|
|
|
1255
1517
|
...styles3.privacyText,
|
|
1256
1518
|
...responsiveStyles.privacyText,
|
|
1257
1519
|
...componentTextStyle,
|
|
1258
|
-
fontSize: "
|
|
1259
|
-
lineHeight: "1.
|
|
1520
|
+
fontSize: "13px",
|
|
1521
|
+
lineHeight: "1.5",
|
|
1522
|
+
marginBottom: "12px"
|
|
1260
1523
|
},
|
|
1261
|
-
children: "
|
|
1524
|
+
children: "Since you are under the age of consent, a legal guardian must verify their identity via DigiLocker before you can proceed."
|
|
1262
1525
|
}
|
|
1263
1526
|
),
|
|
1527
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: infoBannerStyle, children: [
|
|
1528
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1529
|
+
"svg",
|
|
1530
|
+
{
|
|
1531
|
+
width: "16",
|
|
1532
|
+
height: "16",
|
|
1533
|
+
viewBox: "0 0 24 24",
|
|
1534
|
+
fill: "none",
|
|
1535
|
+
stroke: "#2563EB",
|
|
1536
|
+
strokeWidth: "2",
|
|
1537
|
+
strokeLinecap: "round",
|
|
1538
|
+
strokeLinejoin: "round",
|
|
1539
|
+
style: { flexShrink: 0, marginTop: "1px" },
|
|
1540
|
+
children: [
|
|
1541
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
|
|
1542
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
|
|
1543
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", y1: "8", x2: "12.01", y2: "8" })
|
|
1544
|
+
]
|
|
1545
|
+
}
|
|
1546
|
+
),
|
|
1547
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "The guardian's name will be matched against their DigiLocker identity document (e.g. Aadhaar). Please enter the name exactly as it appears on the document." })
|
|
1548
|
+
] }),
|
|
1264
1549
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1265
1550
|
"div",
|
|
1266
1551
|
{
|
|
1267
1552
|
style: {
|
|
1268
1553
|
display: "flex",
|
|
1269
1554
|
flexDirection: "column",
|
|
1270
|
-
gap: "
|
|
1271
|
-
marginTop: "16px"
|
|
1555
|
+
gap: "14px"
|
|
1272
1556
|
},
|
|
1273
1557
|
children: [
|
|
1274
1558
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
1275
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
1276
|
-
"
|
|
1277
|
-
{
|
|
1278
|
-
|
|
1279
|
-
style: { ...labelStyle, marginBottom: "8px", display: "block" },
|
|
1280
|
-
children: "Name of Guardian *"
|
|
1281
|
-
}
|
|
1282
|
-
),
|
|
1559
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { htmlFor: "guardianName", style: labelStyle, children: [
|
|
1560
|
+
"Guardian's Full Name ",
|
|
1561
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: "#DC2626" }, children: "*" })
|
|
1562
|
+
] }),
|
|
1283
1563
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1284
1564
|
"input",
|
|
1285
1565
|
{
|
|
@@ -1289,62 +1569,170 @@ var GuardianForm = ({
|
|
|
1289
1569
|
onChange: (e) => onChange("guardianName", e.target.value),
|
|
1290
1570
|
style: {
|
|
1291
1571
|
...inputStyle,
|
|
1292
|
-
borderColor: errors.guardianName ? "#DC2626" :
|
|
1572
|
+
borderColor: errors.guardianName ? "#DC2626" : borderColor
|
|
1293
1573
|
},
|
|
1294
|
-
placeholder: "
|
|
1574
|
+
placeholder: "e.g. Rajesh Kumar",
|
|
1575
|
+
autoComplete: "name",
|
|
1576
|
+
"aria-describedby": "guardianName-hint"
|
|
1295
1577
|
}
|
|
1296
1578
|
),
|
|
1297
|
-
|
|
1579
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { id: "guardianName-hint", style: hintStyle, children: "Enter the full name as per government ID (Aadhaar, PAN, etc.)" }),
|
|
1580
|
+
errors.guardianName && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: errorStyle, role: "alert", children: errors.guardianName })
|
|
1298
1581
|
] }),
|
|
1299
1582
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
1300
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
1301
|
-
"
|
|
1302
|
-
{
|
|
1303
|
-
|
|
1304
|
-
style: { ...labelStyle, marginBottom: "8px", display: "block" },
|
|
1305
|
-
children: "Contact of Guardian *"
|
|
1306
|
-
}
|
|
1307
|
-
),
|
|
1583
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { htmlFor: "guardianContact", style: labelStyle, children: [
|
|
1584
|
+
"Guardian's Phone Number ",
|
|
1585
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: "#DC2626" }, children: "*" })
|
|
1586
|
+
] }),
|
|
1308
1587
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1309
1588
|
"input",
|
|
1310
1589
|
{
|
|
1311
1590
|
id: "guardianContact",
|
|
1312
|
-
type: "
|
|
1591
|
+
type: "tel",
|
|
1592
|
+
inputMode: "tel",
|
|
1313
1593
|
value: formData.guardianContact,
|
|
1314
1594
|
onChange: (e) => onChange("guardianContact", e.target.value),
|
|
1315
1595
|
style: {
|
|
1316
1596
|
...inputStyle,
|
|
1317
|
-
borderColor: errors.guardianContact ? "#DC2626" :
|
|
1597
|
+
borderColor: errors.guardianContact ? "#DC2626" : borderColor
|
|
1318
1598
|
},
|
|
1319
|
-
placeholder: "
|
|
1599
|
+
placeholder: "e.g. 9876543210",
|
|
1600
|
+
autoComplete: "tel",
|
|
1601
|
+
"aria-describedby": "guardianContact-hint"
|
|
1320
1602
|
}
|
|
1321
1603
|
),
|
|
1322
|
-
|
|
1604
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { id: "guardianContact-hint", style: hintStyle, children: "Mobile number linked to guardian's Aadhaar" }),
|
|
1605
|
+
errors.guardianContact && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: errorStyle, role: "alert", children: errors.guardianContact })
|
|
1323
1606
|
] }),
|
|
1324
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
1325
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
1326
|
-
"
|
|
1607
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ref: dropdownRef, style: { position: "relative" }, children: [
|
|
1608
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { id: "guardianRelationship-label", style: labelStyle, children: [
|
|
1609
|
+
"Relationship ",
|
|
1610
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: "#DC2626" }, children: "*" })
|
|
1611
|
+
] }),
|
|
1612
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1613
|
+
"div",
|
|
1327
1614
|
{
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1615
|
+
role: "combobox",
|
|
1616
|
+
"aria-expanded": isDropdownOpen,
|
|
1617
|
+
"aria-haspopup": "listbox",
|
|
1618
|
+
"aria-labelledby": "guardianRelationship-label",
|
|
1619
|
+
"aria-controls": "guardianRelationship-listbox",
|
|
1620
|
+
"aria-activedescendant": focusedIndex >= 0 ? `guardianRelationship-option-${focusedIndex}` : void 0,
|
|
1621
|
+
tabIndex: 0,
|
|
1622
|
+
onClick: () => {
|
|
1623
|
+
setIsDropdownOpen((prev) => !prev);
|
|
1624
|
+
setFocusedIndex(-1);
|
|
1625
|
+
},
|
|
1626
|
+
onKeyDown: handleKeyDown,
|
|
1627
|
+
style: {
|
|
1628
|
+
...inputStyle,
|
|
1629
|
+
borderColor: hasError ? "#DC2626" : isDropdownOpen ? ((_c = (_b = settings == null ? void 0 : settings.button) == null ? void 0 : _b.accept) == null ? void 0 : _c.backgroundColor) || "#3b82f6" : borderColor,
|
|
1630
|
+
boxShadow: isDropdownOpen ? `0 0 0 1px ${((_e = (_d = settings == null ? void 0 : settings.button) == null ? void 0 : _d.accept) == null ? void 0 : _e.backgroundColor) || "#3b82f6"}` : "none",
|
|
1631
|
+
color: selectedLabel ? textColor : "#9CA3AF",
|
|
1632
|
+
cursor: "pointer",
|
|
1633
|
+
display: "flex",
|
|
1634
|
+
alignItems: "center",
|
|
1635
|
+
justifyContent: "space-between",
|
|
1636
|
+
userSelect: "none",
|
|
1637
|
+
transition: "border-color 0.15s, box-shadow 0.15s"
|
|
1638
|
+
},
|
|
1639
|
+
children: [
|
|
1640
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: selectedLabel || "Select relationship" }),
|
|
1641
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1642
|
+
"svg",
|
|
1643
|
+
{
|
|
1644
|
+
width: "14",
|
|
1645
|
+
height: "14",
|
|
1646
|
+
viewBox: "0 0 24 24",
|
|
1647
|
+
fill: "none",
|
|
1648
|
+
stroke: "#667085",
|
|
1649
|
+
strokeWidth: "2",
|
|
1650
|
+
strokeLinecap: "round",
|
|
1651
|
+
strokeLinejoin: "round",
|
|
1652
|
+
style: {
|
|
1653
|
+
flexShrink: 0,
|
|
1654
|
+
marginLeft: "8px",
|
|
1655
|
+
transform: isDropdownOpen ? "rotate(180deg)" : "rotate(0deg)",
|
|
1656
|
+
transition: "transform 0.2s"
|
|
1657
|
+
},
|
|
1658
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "6 9 12 15 18 9" })
|
|
1659
|
+
}
|
|
1660
|
+
)
|
|
1661
|
+
]
|
|
1331
1662
|
}
|
|
1332
1663
|
),
|
|
1333
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1334
|
-
"
|
|
1664
|
+
isDropdownOpen && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1665
|
+
"div",
|
|
1335
1666
|
{
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1667
|
+
ref: optionsRef,
|
|
1668
|
+
id: "guardianRelationship-listbox",
|
|
1669
|
+
role: "listbox",
|
|
1670
|
+
"aria-labelledby": "guardianRelationship-label",
|
|
1340
1671
|
style: {
|
|
1341
|
-
|
|
1342
|
-
|
|
1672
|
+
position: "absolute",
|
|
1673
|
+
...openUpward ? { bottom: "calc(100% + 4px)" } : { top: "calc(100% + 4px)" },
|
|
1674
|
+
left: 0,
|
|
1675
|
+
right: 0,
|
|
1676
|
+
backgroundColor: bgColor,
|
|
1677
|
+
border: `1px solid ${borderColor}`,
|
|
1678
|
+
borderRadius: radius,
|
|
1679
|
+
boxShadow: openUpward ? "0 -4px 12px rgba(0, 0, 0, 0.1), 0 -1px 3px rgba(0, 0, 0, 0.06)" : "0 4px 12px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.06)",
|
|
1680
|
+
zIndex: 50,
|
|
1681
|
+
overflow: "hidden",
|
|
1682
|
+
padding: "4px 0",
|
|
1683
|
+
maxHeight: "220px",
|
|
1684
|
+
overflowY: "auto"
|
|
1343
1685
|
},
|
|
1344
|
-
|
|
1686
|
+
children: RELATIONSHIP_OPTIONS.map((option, index) => {
|
|
1687
|
+
var _a2, _b2;
|
|
1688
|
+
const isSelected = formData.guardianRelationship === option.value;
|
|
1689
|
+
const isFocused = focusedIndex === index;
|
|
1690
|
+
const accentColor = ((_b2 = (_a2 = settings == null ? void 0 : settings.button) == null ? void 0 : _a2.accept) == null ? void 0 : _b2.backgroundColor) || "#3b82f6";
|
|
1691
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1692
|
+
"div",
|
|
1693
|
+
{
|
|
1694
|
+
id: `guardianRelationship-option-${index}`,
|
|
1695
|
+
role: "option",
|
|
1696
|
+
"aria-selected": isSelected,
|
|
1697
|
+
onClick: () => handleSelect(option.value),
|
|
1698
|
+
onMouseEnter: () => setFocusedIndex(index),
|
|
1699
|
+
style: {
|
|
1700
|
+
padding: "9px 12px",
|
|
1701
|
+
fontSize: "13px",
|
|
1702
|
+
fontFamily: font,
|
|
1703
|
+
color: isSelected ? accentColor : textColor,
|
|
1704
|
+
backgroundColor: isFocused ? "#F3F4F6" : "transparent",
|
|
1705
|
+
cursor: "pointer",
|
|
1706
|
+
display: "flex",
|
|
1707
|
+
alignItems: "center",
|
|
1708
|
+
justifyContent: "space-between",
|
|
1709
|
+
transition: "background-color 0.1s"
|
|
1710
|
+
},
|
|
1711
|
+
children: [
|
|
1712
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: option.label }),
|
|
1713
|
+
isSelected && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1714
|
+
"svg",
|
|
1715
|
+
{
|
|
1716
|
+
width: "14",
|
|
1717
|
+
height: "14",
|
|
1718
|
+
viewBox: "0 0 24 24",
|
|
1719
|
+
fill: "none",
|
|
1720
|
+
stroke: accentColor,
|
|
1721
|
+
strokeWidth: "2.5",
|
|
1722
|
+
strokeLinecap: "round",
|
|
1723
|
+
strokeLinejoin: "round",
|
|
1724
|
+
style: { flexShrink: 0 },
|
|
1725
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "20 6 9 17 4 12" })
|
|
1726
|
+
}
|
|
1727
|
+
)
|
|
1728
|
+
]
|
|
1729
|
+
},
|
|
1730
|
+
option.value
|
|
1731
|
+
);
|
|
1732
|
+
})
|
|
1345
1733
|
}
|
|
1346
1734
|
),
|
|
1347
|
-
errors.guardianRelationship && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: errorStyle, children: errors.guardianRelationship })
|
|
1735
|
+
errors.guardianRelationship && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: errorStyle, role: "alert", children: errors.guardianRelationship })
|
|
1348
1736
|
] })
|
|
1349
1737
|
]
|
|
1350
1738
|
}
|
|
@@ -1355,7 +1743,7 @@ var GuardianForm = ({
|
|
|
1355
1743
|
role: "alert",
|
|
1356
1744
|
style: {
|
|
1357
1745
|
color: "#DC2626",
|
|
1358
|
-
fontSize: "
|
|
1746
|
+
fontSize: "13px",
|
|
1359
1747
|
marginTop: "16px",
|
|
1360
1748
|
padding: "12px",
|
|
1361
1749
|
borderRadius: "6px",
|
|
@@ -1391,8 +1779,8 @@ var GuardianForm = ({
|
|
|
1391
1779
|
onClick: onNext,
|
|
1392
1780
|
disabled: isSubmitting,
|
|
1393
1781
|
type: "button",
|
|
1394
|
-
"aria-label": isSubmitting ? "
|
|
1395
|
-
children: isSubmitting ? "
|
|
1782
|
+
"aria-label": isSubmitting ? "Verifying guardian identity" : "Proceed to guardian verification",
|
|
1783
|
+
children: isSubmitting ? "Verifying..." : "Verify via DigiLocker"
|
|
1396
1784
|
}
|
|
1397
1785
|
),
|
|
1398
1786
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -1406,7 +1794,7 @@ var GuardianForm = ({
|
|
|
1406
1794
|
},
|
|
1407
1795
|
onClick: onDecline,
|
|
1408
1796
|
type: "button",
|
|
1409
|
-
"aria-label": "Cancel
|
|
1797
|
+
"aria-label": "Cancel",
|
|
1410
1798
|
children: "Cancel"
|
|
1411
1799
|
}
|
|
1412
1800
|
)
|
|
@@ -1415,6 +1803,266 @@ var GuardianForm = ({
|
|
|
1415
1803
|
)
|
|
1416
1804
|
] });
|
|
1417
1805
|
};
|
|
1806
|
+
var VerificationScreen = ({
|
|
1807
|
+
onBack,
|
|
1808
|
+
onContinue,
|
|
1809
|
+
isInitiating,
|
|
1810
|
+
isPolling,
|
|
1811
|
+
isVerificationComplete,
|
|
1812
|
+
isAutoTransitioning,
|
|
1813
|
+
error,
|
|
1814
|
+
errorCode,
|
|
1815
|
+
canRetry,
|
|
1816
|
+
styles: styles3,
|
|
1817
|
+
responsiveStyles,
|
|
1818
|
+
settings,
|
|
1819
|
+
componentHeadingStyle,
|
|
1820
|
+
componentTextStyle,
|
|
1821
|
+
acceptButtonStyle,
|
|
1822
|
+
declineButtonStyle,
|
|
1823
|
+
logoUrl
|
|
1824
|
+
}) => {
|
|
1825
|
+
var _a, _b;
|
|
1826
|
+
const errorStyle = {
|
|
1827
|
+
color: "#DC2626",
|
|
1828
|
+
fontSize: "14px",
|
|
1829
|
+
marginTop: "16px",
|
|
1830
|
+
padding: "12px",
|
|
1831
|
+
borderRadius: "6px",
|
|
1832
|
+
border: "1px solid #FCA5A5",
|
|
1833
|
+
backgroundColor: "#FEF2F2",
|
|
1834
|
+
textAlign: "center"
|
|
1835
|
+
};
|
|
1836
|
+
const statusStyle = {
|
|
1837
|
+
color: "#059669",
|
|
1838
|
+
fontSize: "14px",
|
|
1839
|
+
marginTop: "16px",
|
|
1840
|
+
padding: "12px",
|
|
1841
|
+
borderRadius: "6px",
|
|
1842
|
+
border: "1px solid #A7F3D0",
|
|
1843
|
+
backgroundColor: "#D1FAE5",
|
|
1844
|
+
textAlign: "center"
|
|
1845
|
+
};
|
|
1846
|
+
const spinnerStyle = {
|
|
1847
|
+
width: "48px",
|
|
1848
|
+
height: "48px",
|
|
1849
|
+
border: "4px solid #e5e7eb",
|
|
1850
|
+
borderTopColor: ((_b = (_a = settings == null ? void 0 : settings.button) == null ? void 0 : _a.accept) == null ? void 0 : _b.backgroundColor) || "#3b82f6",
|
|
1851
|
+
borderRadius: "50%",
|
|
1852
|
+
animation: "spin 1s linear infinite",
|
|
1853
|
+
margin: "24px auto"
|
|
1854
|
+
};
|
|
1855
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1856
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...styles3.topSection, ...componentTextStyle }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles3.topLeft, children: [
|
|
1857
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { style: styles3.logo, src: logoUrl, alt: "Logo" }),
|
|
1858
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1859
|
+
"h2",
|
|
1860
|
+
{
|
|
1861
|
+
id: "verification-title",
|
|
1862
|
+
style: {
|
|
1863
|
+
...styles3.title,
|
|
1864
|
+
...responsiveStyles.title,
|
|
1865
|
+
...componentHeadingStyle,
|
|
1866
|
+
fontSize: "16px",
|
|
1867
|
+
fontWeight: 600
|
|
1868
|
+
},
|
|
1869
|
+
children: "Guardian Verification"
|
|
1870
|
+
}
|
|
1871
|
+
)
|
|
1872
|
+
] }) }),
|
|
1873
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1874
|
+
"div",
|
|
1875
|
+
{
|
|
1876
|
+
style: {
|
|
1877
|
+
...styles3.middleSection,
|
|
1878
|
+
...responsiveStyles.middleSection,
|
|
1879
|
+
...componentTextStyle,
|
|
1880
|
+
textAlign: "center"
|
|
1881
|
+
},
|
|
1882
|
+
children: [
|
|
1883
|
+
isVerificationComplete && !error ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1884
|
+
"div",
|
|
1885
|
+
{
|
|
1886
|
+
style: {
|
|
1887
|
+
display: "flex",
|
|
1888
|
+
flexDirection: "column",
|
|
1889
|
+
alignItems: "center",
|
|
1890
|
+
justifyContent: "center",
|
|
1891
|
+
flex: 1
|
|
1892
|
+
},
|
|
1893
|
+
children: [
|
|
1894
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1895
|
+
"div",
|
|
1896
|
+
{
|
|
1897
|
+
style: {
|
|
1898
|
+
width: "64px",
|
|
1899
|
+
height: "64px",
|
|
1900
|
+
borderRadius: "50%",
|
|
1901
|
+
backgroundColor: "#D1FAE5",
|
|
1902
|
+
display: "flex",
|
|
1903
|
+
alignItems: "center",
|
|
1904
|
+
justifyContent: "center"
|
|
1905
|
+
},
|
|
1906
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1907
|
+
"svg",
|
|
1908
|
+
{
|
|
1909
|
+
width: "32",
|
|
1910
|
+
height: "32",
|
|
1911
|
+
viewBox: "0 0 24 24",
|
|
1912
|
+
fill: "none",
|
|
1913
|
+
stroke: "#059669",
|
|
1914
|
+
strokeWidth: "2",
|
|
1915
|
+
strokeLinecap: "round",
|
|
1916
|
+
strokeLinejoin: "round",
|
|
1917
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "20 6 9 17 4 12" })
|
|
1918
|
+
}
|
|
1919
|
+
)
|
|
1920
|
+
}
|
|
1921
|
+
),
|
|
1922
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1923
|
+
"p",
|
|
1924
|
+
{
|
|
1925
|
+
style: {
|
|
1926
|
+
...componentHeadingStyle,
|
|
1927
|
+
fontSize: "16px",
|
|
1928
|
+
fontWeight: 600,
|
|
1929
|
+
lineHeight: "1.5",
|
|
1930
|
+
marginTop: "12px",
|
|
1931
|
+
marginBottom: "24px"
|
|
1932
|
+
},
|
|
1933
|
+
children: "Verification Completed"
|
|
1934
|
+
}
|
|
1935
|
+
)
|
|
1936
|
+
]
|
|
1937
|
+
}
|
|
1938
|
+
) : (isInitiating || isPolling) && !error ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1939
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: spinnerStyle }),
|
|
1940
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: statusStyle, children: isInitiating ? "Opening DigiLocker in a new tab..." : "Please complete the verification in the DigiLocker tab. This page will update automatically when verification is complete." })
|
|
1941
|
+
] }) : null,
|
|
1942
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1943
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1944
|
+
"div",
|
|
1945
|
+
{
|
|
1946
|
+
style: {
|
|
1947
|
+
width: "64px",
|
|
1948
|
+
height: "64px",
|
|
1949
|
+
borderRadius: "50%",
|
|
1950
|
+
backgroundColor: "#fee2e2",
|
|
1951
|
+
display: "flex",
|
|
1952
|
+
alignItems: "center",
|
|
1953
|
+
justifyContent: "center",
|
|
1954
|
+
margin: "24px auto"
|
|
1955
|
+
},
|
|
1956
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1957
|
+
"svg",
|
|
1958
|
+
{
|
|
1959
|
+
width: "32",
|
|
1960
|
+
height: "32",
|
|
1961
|
+
viewBox: "0 0 24 24",
|
|
1962
|
+
fill: "none",
|
|
1963
|
+
stroke: "#dc2626",
|
|
1964
|
+
strokeWidth: "2",
|
|
1965
|
+
strokeLinecap: "round",
|
|
1966
|
+
strokeLinejoin: "round",
|
|
1967
|
+
children: [
|
|
1968
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
1969
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
1970
|
+
]
|
|
1971
|
+
}
|
|
1972
|
+
)
|
|
1973
|
+
}
|
|
1974
|
+
),
|
|
1975
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1976
|
+
"p",
|
|
1977
|
+
{
|
|
1978
|
+
style: {
|
|
1979
|
+
...styles3.privacyText,
|
|
1980
|
+
...responsiveStyles.privacyText,
|
|
1981
|
+
...componentTextStyle,
|
|
1982
|
+
fontSize: "14px",
|
|
1983
|
+
lineHeight: "1.5",
|
|
1984
|
+
marginBottom: "12px"
|
|
1985
|
+
},
|
|
1986
|
+
children: "Verification failed"
|
|
1987
|
+
}
|
|
1988
|
+
),
|
|
1989
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: errorStyle, children: error })
|
|
1990
|
+
] })
|
|
1991
|
+
]
|
|
1992
|
+
}
|
|
1993
|
+
),
|
|
1994
|
+
isAutoTransitioning ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1995
|
+
"div",
|
|
1996
|
+
{
|
|
1997
|
+
style: {
|
|
1998
|
+
...styles3.bottomSection,
|
|
1999
|
+
...responsiveStyles.bottomSection,
|
|
2000
|
+
...componentTextStyle,
|
|
2001
|
+
paddingTop: "12px",
|
|
2002
|
+
display: "flex",
|
|
2003
|
+
gap: "12px",
|
|
2004
|
+
justifyContent: "center"
|
|
2005
|
+
},
|
|
2006
|
+
children: isVerificationComplete && !error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2007
|
+
"button",
|
|
2008
|
+
{
|
|
2009
|
+
style: {
|
|
2010
|
+
...styles3.button,
|
|
2011
|
+
...responsiveStyles.button,
|
|
2012
|
+
...acceptButtonStyle
|
|
2013
|
+
},
|
|
2014
|
+
onClick: onContinue,
|
|
2015
|
+
type: "button",
|
|
2016
|
+
"aria-label": "Continue to consent form",
|
|
2017
|
+
children: "Continue"
|
|
2018
|
+
}
|
|
2019
|
+
) : error && canRetry ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2020
|
+
"button",
|
|
2021
|
+
{
|
|
2022
|
+
style: {
|
|
2023
|
+
...styles3.button,
|
|
2024
|
+
...responsiveStyles.button,
|
|
2025
|
+
...styles3.acceptButton,
|
|
2026
|
+
...acceptButtonStyle
|
|
2027
|
+
},
|
|
2028
|
+
onClick: () => onBack(errorCode === "GUARDIAN_UNDER_18"),
|
|
2029
|
+
type: "button",
|
|
2030
|
+
"aria-label": errorCode === "GUARDIAN_UNDER_18" ? "Change guardian details" : "Try verification again",
|
|
2031
|
+
children: errorCode === "GUARDIAN_UNDER_18" ? "Change Guardian" : "Try Again"
|
|
2032
|
+
}
|
|
2033
|
+
) : error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2034
|
+
"button",
|
|
2035
|
+
{
|
|
2036
|
+
style: {
|
|
2037
|
+
...styles3.button,
|
|
2038
|
+
...responsiveStyles.button,
|
|
2039
|
+
...styles3.cancelButton,
|
|
2040
|
+
...declineButtonStyle
|
|
2041
|
+
},
|
|
2042
|
+
onClick: () => onBack(false),
|
|
2043
|
+
type: "button",
|
|
2044
|
+
"aria-label": "Go back",
|
|
2045
|
+
children: "Go Back"
|
|
2046
|
+
}
|
|
2047
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2048
|
+
"button",
|
|
2049
|
+
{
|
|
2050
|
+
style: {
|
|
2051
|
+
...styles3.button,
|
|
2052
|
+
...responsiveStyles.button,
|
|
2053
|
+
...styles3.cancelButton,
|
|
2054
|
+
...declineButtonStyle
|
|
2055
|
+
},
|
|
2056
|
+
onClick: () => onBack(false),
|
|
2057
|
+
type: "button",
|
|
2058
|
+
"aria-label": "Cancel verification",
|
|
2059
|
+
children: "Cancel"
|
|
2060
|
+
}
|
|
2061
|
+
)
|
|
2062
|
+
}
|
|
2063
|
+
)
|
|
2064
|
+
] });
|
|
2065
|
+
};
|
|
1418
2066
|
var AgeVerification = ({
|
|
1419
2067
|
onYes,
|
|
1420
2068
|
onNo,
|
|
@@ -1577,6 +2225,10 @@ var RedactoNoticeConsent = ({
|
|
|
1577
2225
|
settings,
|
|
1578
2226
|
applicationId,
|
|
1579
2227
|
validateAgainst = "all",
|
|
2228
|
+
digilockerMode = "redirect",
|
|
2229
|
+
// Default to full page redirect (DigiLocker blocks iframe embedding)
|
|
2230
|
+
digilockerCallbackUrl = "/digilocker-callback",
|
|
2231
|
+
// Default callback path
|
|
1580
2232
|
includeFullyConsentedData = false,
|
|
1581
2233
|
reviewModeButtonText = "Continue"
|
|
1582
2234
|
}) => {
|
|
@@ -1632,6 +2284,8 @@ var RedactoNoticeConsent = ({
|
|
|
1632
2284
|
const [currentAudioIndex, setCurrentAudioIndex] = (0, import_react2.useState)(0);
|
|
1633
2285
|
const [highlightedElementId, setHighlightedElementId] = (0, import_react2.useState)(null);
|
|
1634
2286
|
const [showAgeVerification, setShowAgeVerification] = (0, import_react2.useState)(false);
|
|
2287
|
+
const [isMinorFlow, setIsMinorFlow] = (0, import_react2.useState)(false);
|
|
2288
|
+
const [selfDeclaredAdult, setSelfDeclaredAdult] = (0, import_react2.useState)(false);
|
|
1635
2289
|
const [showGuardianForm, setShowGuardianForm] = (0, import_react2.useState)(false);
|
|
1636
2290
|
const [isSubmittingGuardian, setIsSubmittingGuardian] = (0, import_react2.useState)(false);
|
|
1637
2291
|
const [guardianFormData, setGuardianFormData] = (0, import_react2.useState)({
|
|
@@ -1640,12 +2294,32 @@ var RedactoNoticeConsent = ({
|
|
|
1640
2294
|
guardianRelationship: ""
|
|
1641
2295
|
});
|
|
1642
2296
|
const [guardianFormErrors, setGuardianFormErrors] = (0, import_react2.useState)({});
|
|
2297
|
+
const [showVerificationScreen, setShowVerificationScreen] = (0, import_react2.useState)(false);
|
|
2298
|
+
const [verificationReference, setVerificationReference] = (0, import_react2.useState)(null);
|
|
2299
|
+
const [isInitiatingVerification, setIsInitiatingVerification] = (0, import_react2.useState)(false);
|
|
2300
|
+
const [verificationError, setVerificationError] = (0, import_react2.useState)(
|
|
2301
|
+
null
|
|
2302
|
+
);
|
|
2303
|
+
const [verificationErrorCode, setVerificationErrorCode] = (0, import_react2.useState)(null);
|
|
2304
|
+
const [canRetryVerification, setCanRetryVerification] = (0, import_react2.useState)(false);
|
|
2305
|
+
const [isPollingStatus, setIsPollingStatus] = (0, import_react2.useState)(false);
|
|
2306
|
+
const [isVerificationComplete, setIsVerificationComplete] = (0, import_react2.useState)(false);
|
|
2307
|
+
const [isAutoTransitioning, setIsAutoTransitioning] = (0, import_react2.useState)(false);
|
|
1643
2308
|
const modalRef = (0, import_react2.useRef)(null);
|
|
1644
2309
|
const firstFocusableRef = (0, import_react2.useRef)(null);
|
|
1645
2310
|
const lastFocusableRef = (0, import_react2.useRef)(null);
|
|
1646
2311
|
const abortControllerRef = (0, import_react2.useRef)(null);
|
|
1647
2312
|
const isRequestInProgressRef = (0, import_react2.useRef)(false);
|
|
1648
2313
|
const currentAudioRef = (0, import_react2.useRef)(null);
|
|
2314
|
+
const popupCheckIntervalRef = (0, import_react2.useRef)(null);
|
|
2315
|
+
const statusPollIntervalRef = (0, import_react2.useRef)(null);
|
|
2316
|
+
const verificationPopupRef = (0, import_react2.useRef)(null);
|
|
2317
|
+
const pollingCleanupRef = (0, import_react2.useRef)(null);
|
|
2318
|
+
const autoTransitionTimerRef = (0, import_react2.useRef)(null);
|
|
2319
|
+
const digilockerRedirectTimeoutRef = (0, import_react2.useRef)(null);
|
|
2320
|
+
const isInitialMountRef = (0, import_react2.useRef)(true);
|
|
2321
|
+
const isPollingStatusRef = (0, import_react2.useRef)(false);
|
|
2322
|
+
const verificationSessionTokenRef = (0, import_react2.useRef)(null);
|
|
1649
2323
|
const isMobile = useMediaQuery("(max-width: 768px)");
|
|
1650
2324
|
const responsiveStyles = (0, import_react2.useMemo)(
|
|
1651
2325
|
() => ({
|
|
@@ -1753,6 +2427,7 @@ var RedactoNoticeConsent = ({
|
|
|
1753
2427
|
}, [content, selectedDataElements]);
|
|
1754
2428
|
const acceptDisabled = isSubmitting || !areAllRequiredElementsChecked;
|
|
1755
2429
|
(0, import_react2.useEffect)(() => {
|
|
2430
|
+
var _a2, _b2;
|
|
1756
2431
|
clearApiCache();
|
|
1757
2432
|
isRequestInProgressRef.current = false;
|
|
1758
2433
|
setContent(null);
|
|
@@ -1768,6 +2443,8 @@ var RedactoNoticeConsent = ({
|
|
|
1768
2443
|
setIsSubmittingAccept(false);
|
|
1769
2444
|
setIsSubmittingDecline(false);
|
|
1770
2445
|
setShowAgeVerification(false);
|
|
2446
|
+
setIsMinorFlow(false);
|
|
2447
|
+
setSelfDeclaredAdult(false);
|
|
1771
2448
|
setShowGuardianForm(false);
|
|
1772
2449
|
setIsSubmittingGuardian(false);
|
|
1773
2450
|
setGuardianFormData({
|
|
@@ -1776,6 +2453,41 @@ var RedactoNoticeConsent = ({
|
|
|
1776
2453
|
guardianRelationship: ""
|
|
1777
2454
|
});
|
|
1778
2455
|
setGuardianFormErrors({});
|
|
2456
|
+
setShowVerificationScreen(false);
|
|
2457
|
+
setVerificationReference(null);
|
|
2458
|
+
setIsInitiatingVerification(false);
|
|
2459
|
+
setVerificationError(null);
|
|
2460
|
+
setVerificationErrorCode(null);
|
|
2461
|
+
setCanRetryVerification(false);
|
|
2462
|
+
setIsVerificationComplete(false);
|
|
2463
|
+
setIsAutoTransitioning(false);
|
|
2464
|
+
setIsPollingStatus(false);
|
|
2465
|
+
isPollingStatusRef.current = false;
|
|
2466
|
+
verificationSessionTokenRef.current = null;
|
|
2467
|
+
if (popupCheckIntervalRef.current) {
|
|
2468
|
+
clearInterval(popupCheckIntervalRef.current);
|
|
2469
|
+
popupCheckIntervalRef.current = null;
|
|
2470
|
+
}
|
|
2471
|
+
if (statusPollIntervalRef.current) {
|
|
2472
|
+
clearTimeout(statusPollIntervalRef.current);
|
|
2473
|
+
statusPollIntervalRef.current = null;
|
|
2474
|
+
}
|
|
2475
|
+
(_a2 = pollingCleanupRef.current) == null ? void 0 : _a2.call(pollingCleanupRef);
|
|
2476
|
+
pollingCleanupRef.current = null;
|
|
2477
|
+
(_b2 = verificationPopupRef.current) == null ? void 0 : _b2.close();
|
|
2478
|
+
verificationPopupRef.current = null;
|
|
2479
|
+
if (autoTransitionTimerRef.current) {
|
|
2480
|
+
clearTimeout(autoTransitionTimerRef.current);
|
|
2481
|
+
autoTransitionTimerRef.current = null;
|
|
2482
|
+
}
|
|
2483
|
+
if (digilockerRedirectTimeoutRef.current) {
|
|
2484
|
+
clearTimeout(digilockerRedirectTimeoutRef.current);
|
|
2485
|
+
digilockerRedirectTimeoutRef.current = null;
|
|
2486
|
+
}
|
|
2487
|
+
if (!isInitialMountRef.current) {
|
|
2488
|
+
clearConsentState();
|
|
2489
|
+
}
|
|
2490
|
+
isInitialMountRef.current = false;
|
|
1779
2491
|
}, [accessToken]);
|
|
1780
2492
|
(0, import_react2.useEffect)(() => {
|
|
1781
2493
|
if (hasAlreadyConsented) {
|
|
@@ -1984,7 +2696,11 @@ var RedactoNoticeConsent = ({
|
|
|
1984
2696
|
setInitialDataElementSelections({});
|
|
1985
2697
|
}
|
|
1986
2698
|
if (consentContentData.detail.is_minor) {
|
|
1987
|
-
|
|
2699
|
+
setIsMinorFlow(true);
|
|
2700
|
+
const persistedState = getConsentState();
|
|
2701
|
+
if (!(persistedState == null ? void 0 : persistedState.sessionToken) && !(persistedState == null ? void 0 : persistedState.verificationReference)) {
|
|
2702
|
+
setShowAgeVerification(true);
|
|
2703
|
+
}
|
|
1988
2704
|
}
|
|
1989
2705
|
setIsLoading(false);
|
|
1990
2706
|
} catch (err) {
|
|
@@ -2083,6 +2799,10 @@ var RedactoNoticeConsent = ({
|
|
|
2083
2799
|
const handleAccept = async () => {
|
|
2084
2800
|
const submitController = new AbortController();
|
|
2085
2801
|
try {
|
|
2802
|
+
if (isMinorFlow && !verificationReference) {
|
|
2803
|
+
setErrorMessage("Guardian verification is required before consent can be submitted.");
|
|
2804
|
+
return;
|
|
2805
|
+
}
|
|
2086
2806
|
setIsSubmittingAccept(true);
|
|
2087
2807
|
setIsSubmitting(true);
|
|
2088
2808
|
setErrorMessage(null);
|
|
@@ -2118,6 +2838,8 @@ var RedactoNoticeConsent = ({
|
|
|
2118
2838
|
}),
|
|
2119
2839
|
declined: false,
|
|
2120
2840
|
meta_data: applicationId ? { specific_uuid: applicationId } : void 0,
|
|
2841
|
+
guardianVerificationReference: verificationReference || void 0,
|
|
2842
|
+
selfDeclaredAdult: selfDeclaredAdult || void 0,
|
|
2121
2843
|
signal: submitController.signal
|
|
2122
2844
|
});
|
|
2123
2845
|
}
|
|
@@ -2182,17 +2904,102 @@ var RedactoNoticeConsent = ({
|
|
|
2182
2904
|
try {
|
|
2183
2905
|
setIsSubmittingGuardian(true);
|
|
2184
2906
|
setGuardianFormErrors({});
|
|
2185
|
-
|
|
2907
|
+
setVerificationError(null);
|
|
2908
|
+
const callbackUrl = digilockerMode === "popup" ? new URL(digilockerCallbackUrl, window.location.origin).href : void 0;
|
|
2909
|
+
const response = await initiateGuardianVerification({
|
|
2186
2910
|
accessToken,
|
|
2187
2911
|
baseUrl,
|
|
2188
2912
|
guardianName: guardianFormData.guardianName,
|
|
2189
2913
|
guardianContact: guardianFormData.guardianContact,
|
|
2190
2914
|
guardianRelationship: guardianFormData.guardianRelationship,
|
|
2915
|
+
frontendCallbackUrl: callbackUrl,
|
|
2916
|
+
// Only for popup mode
|
|
2191
2917
|
signal: guardianController.signal
|
|
2192
2918
|
});
|
|
2919
|
+
setIsSubmittingGuardian(false);
|
|
2920
|
+
if (response.already_verified && response.verification_reference) {
|
|
2921
|
+
setVerificationReference(response.verification_reference);
|
|
2922
|
+
setShowGuardianForm(false);
|
|
2923
|
+
setShowVerificationScreen(true);
|
|
2924
|
+
setIsInitiatingVerification(false);
|
|
2925
|
+
setIsVerificationComplete(true);
|
|
2926
|
+
setIsAutoTransitioning(true);
|
|
2927
|
+
autoTransitionTimerRef.current = setTimeout(() => {
|
|
2928
|
+
setShowVerificationScreen(false);
|
|
2929
|
+
setIsVerificationComplete(false);
|
|
2930
|
+
setIsAutoTransitioning(false);
|
|
2931
|
+
autoTransitionTimerRef.current = null;
|
|
2932
|
+
}, 1e3);
|
|
2933
|
+
return;
|
|
2934
|
+
}
|
|
2935
|
+
if (!response.session_token || !response.digilocker_redirect_url) {
|
|
2936
|
+
throw new Error("Invalid response from server: missing required fields");
|
|
2937
|
+
}
|
|
2193
2938
|
setShowGuardianForm(false);
|
|
2939
|
+
setShowVerificationScreen(true);
|
|
2940
|
+
setIsInitiatingVerification(true);
|
|
2941
|
+
if (digilockerMode === "redirect") {
|
|
2942
|
+
saveConsentState({
|
|
2943
|
+
flowState: "digilocker-pending",
|
|
2944
|
+
sessionToken: response.session_token,
|
|
2945
|
+
guardianInfoUuid: response.guardian_info_uuid,
|
|
2946
|
+
selectedPurposes,
|
|
2947
|
+
selectedDataElements,
|
|
2948
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2949
|
+
originalUrl: window.location.href,
|
|
2950
|
+
noticeId,
|
|
2951
|
+
baseUrl
|
|
2952
|
+
});
|
|
2953
|
+
try {
|
|
2954
|
+
const openedWindow = window.open(
|
|
2955
|
+
response.digilocker_redirect_url,
|
|
2956
|
+
"_blank"
|
|
2957
|
+
);
|
|
2958
|
+
if (!openedWindow) {
|
|
2959
|
+
console.warn("Popup blocked \u2014 cannot open DigiLocker in new tab");
|
|
2960
|
+
setIsInitiatingVerification(false);
|
|
2961
|
+
setVerificationError(
|
|
2962
|
+
"Unable to open DigiLocker in a new tab. Please allow popups for this site and try again."
|
|
2963
|
+
);
|
|
2964
|
+
return;
|
|
2965
|
+
}
|
|
2966
|
+
try {
|
|
2967
|
+
openedWindow.opener = null;
|
|
2968
|
+
} catch {
|
|
2969
|
+
}
|
|
2970
|
+
} catch (error) {
|
|
2971
|
+
console.error("Failed to open DigiLocker in new tab:", error);
|
|
2972
|
+
setIsInitiatingVerification(false);
|
|
2973
|
+
setVerificationError(
|
|
2974
|
+
"Unable to open DigiLocker. Please allow popups for this site and try again."
|
|
2975
|
+
);
|
|
2976
|
+
return;
|
|
2977
|
+
}
|
|
2978
|
+
setIsInitiatingVerification(false);
|
|
2979
|
+
setIsPollingStatus(true);
|
|
2980
|
+
isPollingStatusRef.current = true;
|
|
2981
|
+
startStatusPolling(response.session_token);
|
|
2982
|
+
} else {
|
|
2983
|
+
setIsInitiatingVerification(true);
|
|
2984
|
+
const popup = window.open(
|
|
2985
|
+
response.digilocker_redirect_url,
|
|
2986
|
+
"digilocker_verification",
|
|
2987
|
+
"width=600,height=700,scrollbars=yes,resizable=yes"
|
|
2988
|
+
);
|
|
2989
|
+
if (popup) {
|
|
2990
|
+
verificationPopupRef.current = popup;
|
|
2991
|
+
startPopupMonitoring(popup);
|
|
2992
|
+
startStatusPolling(response.session_token);
|
|
2993
|
+
} else {
|
|
2994
|
+
setIsInitiatingVerification(false);
|
|
2995
|
+
setVerificationError(
|
|
2996
|
+
"Popup blocked. Please allow popups for this site or use redirect mode."
|
|
2997
|
+
);
|
|
2998
|
+
}
|
|
2999
|
+
}
|
|
2194
3000
|
} catch (error) {
|
|
2195
3001
|
const err = error;
|
|
3002
|
+
setIsInitiatingVerification(false);
|
|
2196
3003
|
if (err.status === 422) {
|
|
2197
3004
|
if (err.message.includes("guardian_contact")) {
|
|
2198
3005
|
setGuardianFormErrors({ guardianContact: err.message });
|
|
@@ -2203,23 +3010,265 @@ var RedactoNoticeConsent = ({
|
|
|
2203
3010
|
} else {
|
|
2204
3011
|
setGuardianFormErrors({ general: err.message });
|
|
2205
3012
|
}
|
|
3013
|
+
setShowVerificationScreen(false);
|
|
3014
|
+
setShowGuardianForm(true);
|
|
2206
3015
|
} else {
|
|
2207
3016
|
setGuardianFormErrors({
|
|
2208
|
-
general: err.message || "Failed to
|
|
3017
|
+
general: err.message || "Failed to initiate verification. Please try again."
|
|
2209
3018
|
});
|
|
3019
|
+
setShowVerificationScreen(false);
|
|
3020
|
+
setShowGuardianForm(true);
|
|
2210
3021
|
onError == null ? void 0 : onError(err);
|
|
2211
3022
|
}
|
|
2212
3023
|
} finally {
|
|
2213
3024
|
setIsSubmittingGuardian(false);
|
|
2214
3025
|
}
|
|
2215
|
-
}, [accessToken, baseUrl, guardianFormData, onError]);
|
|
3026
|
+
}, [accessToken, baseUrl, guardianFormData, digilockerMode, digilockerCallbackUrl, selectedPurposes, selectedDataElements, noticeId, onError]);
|
|
2216
3027
|
const handleAgeVerificationYes = (0, import_react2.useCallback)(() => {
|
|
2217
3028
|
setShowAgeVerification(false);
|
|
3029
|
+
setIsMinorFlow(false);
|
|
3030
|
+
setSelfDeclaredAdult(true);
|
|
2218
3031
|
}, []);
|
|
2219
3032
|
const handleAgeVerificationNo = (0, import_react2.useCallback)(() => {
|
|
2220
3033
|
setShowAgeVerification(false);
|
|
2221
3034
|
setShowGuardianForm(true);
|
|
2222
3035
|
}, []);
|
|
3036
|
+
const handleVerificationContinue = (0, import_react2.useCallback)(() => {
|
|
3037
|
+
setShowVerificationScreen(false);
|
|
3038
|
+
setIsVerificationComplete(false);
|
|
3039
|
+
}, []);
|
|
3040
|
+
const handlePopupClosed = (0, import_react2.useCallback)(async () => {
|
|
3041
|
+
var _a2, _b2;
|
|
3042
|
+
if (popupCheckIntervalRef.current) {
|
|
3043
|
+
clearInterval(popupCheckIntervalRef.current);
|
|
3044
|
+
popupCheckIntervalRef.current = null;
|
|
3045
|
+
}
|
|
3046
|
+
if (statusPollIntervalRef.current) {
|
|
3047
|
+
clearTimeout(statusPollIntervalRef.current);
|
|
3048
|
+
statusPollIntervalRef.current = null;
|
|
3049
|
+
}
|
|
3050
|
+
(_a2 = pollingCleanupRef.current) == null ? void 0 : _a2.call(pollingCleanupRef);
|
|
3051
|
+
pollingCleanupRef.current = null;
|
|
3052
|
+
verificationPopupRef.current = null;
|
|
3053
|
+
if (!isPollingStatusRef.current) return;
|
|
3054
|
+
const sessionToken = verificationSessionTokenRef.current;
|
|
3055
|
+
if (sessionToken) {
|
|
3056
|
+
try {
|
|
3057
|
+
const response = await verifyGuardianStatus({
|
|
3058
|
+
accessToken,
|
|
3059
|
+
baseUrl,
|
|
3060
|
+
sessionToken
|
|
3061
|
+
});
|
|
3062
|
+
if (response.status === "verified") {
|
|
3063
|
+
const ref = response.verification_reference || ((_b2 = response.guardian_details) == null ? void 0 : _b2.verification_reference);
|
|
3064
|
+
if (ref) {
|
|
3065
|
+
setVerificationReference(ref);
|
|
3066
|
+
setIsVerificationComplete(true);
|
|
3067
|
+
setIsPollingStatus(false);
|
|
3068
|
+
isPollingStatusRef.current = false;
|
|
3069
|
+
setIsInitiatingVerification(false);
|
|
3070
|
+
clearConsentState();
|
|
3071
|
+
return;
|
|
3072
|
+
}
|
|
3073
|
+
}
|
|
3074
|
+
} catch {
|
|
3075
|
+
}
|
|
3076
|
+
}
|
|
3077
|
+
setVerificationError(
|
|
3078
|
+
"Verification window was closed. Please try again."
|
|
3079
|
+
);
|
|
3080
|
+
setIsPollingStatus(false);
|
|
3081
|
+
isPollingStatusRef.current = false;
|
|
3082
|
+
setIsInitiatingVerification(false);
|
|
3083
|
+
}, [accessToken, baseUrl]);
|
|
3084
|
+
const startPopupMonitoring = (0, import_react2.useCallback)((popup) => {
|
|
3085
|
+
popupCheckIntervalRef.current = window.setInterval(() => {
|
|
3086
|
+
if (popup.closed) {
|
|
3087
|
+
handlePopupClosed();
|
|
3088
|
+
}
|
|
3089
|
+
}, 500);
|
|
3090
|
+
}, [handlePopupClosed]);
|
|
3091
|
+
const getVerificationErrorMessage = (0, import_react2.useCallback)(
|
|
3092
|
+
(errorCode, fallbackError) => {
|
|
3093
|
+
switch (errorCode) {
|
|
3094
|
+
case "GUARDIAN_UNDER_18":
|
|
3095
|
+
return "The guardian must be 18 years or older. Please provide details of a different guardian.";
|
|
3096
|
+
case "TOKEN_FAILED":
|
|
3097
|
+
return "DigiLocker verification could not be completed. Please try again.";
|
|
3098
|
+
case "DIGILOCKER_AUTH_FAILED":
|
|
3099
|
+
return "DigiLocker authorization was cancelled or failed. Please try again.";
|
|
3100
|
+
case "NO_AUTH_CODE":
|
|
3101
|
+
return "DigiLocker did not return an authorization code. Please try again.";
|
|
3102
|
+
case "SESSION_EXPIRED":
|
|
3103
|
+
return "Verification session has expired. Please try again.";
|
|
3104
|
+
default:
|
|
3105
|
+
return fallbackError || "Verification failed. Please try again.";
|
|
3106
|
+
}
|
|
3107
|
+
},
|
|
3108
|
+
[]
|
|
3109
|
+
);
|
|
3110
|
+
const startStatusPolling = (0, import_react2.useCallback)(
|
|
3111
|
+
(token) => {
|
|
3112
|
+
verificationSessionTokenRef.current = token;
|
|
3113
|
+
setIsPollingStatus(true);
|
|
3114
|
+
isPollingStatusRef.current = true;
|
|
3115
|
+
setVerificationError(null);
|
|
3116
|
+
setVerificationErrorCode(null);
|
|
3117
|
+
setCanRetryVerification(false);
|
|
3118
|
+
let attempts = 0;
|
|
3119
|
+
let consecutiveErrors = 0;
|
|
3120
|
+
let paused = false;
|
|
3121
|
+
const MAX_ATTEMPTS = 40;
|
|
3122
|
+
const MAX_CONSECUTIVE_ERRORS = 3;
|
|
3123
|
+
const POLL_INTERVAL = 3e3;
|
|
3124
|
+
const stopPolling = () => {
|
|
3125
|
+
var _a2;
|
|
3126
|
+
if (statusPollIntervalRef.current) {
|
|
3127
|
+
clearTimeout(statusPollIntervalRef.current);
|
|
3128
|
+
statusPollIntervalRef.current = null;
|
|
3129
|
+
}
|
|
3130
|
+
if (popupCheckIntervalRef.current) {
|
|
3131
|
+
clearInterval(popupCheckIntervalRef.current);
|
|
3132
|
+
popupCheckIntervalRef.current = null;
|
|
3133
|
+
}
|
|
3134
|
+
(_a2 = verificationPopupRef.current) == null ? void 0 : _a2.close();
|
|
3135
|
+
verificationPopupRef.current = null;
|
|
3136
|
+
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
3137
|
+
pollingCleanupRef.current = null;
|
|
3138
|
+
setIsPollingStatus(false);
|
|
3139
|
+
isPollingStatusRef.current = false;
|
|
3140
|
+
setIsInitiatingVerification(false);
|
|
3141
|
+
};
|
|
3142
|
+
const setError = (message, errorCode, canRetry) => {
|
|
3143
|
+
stopPolling();
|
|
3144
|
+
setVerificationError(message);
|
|
3145
|
+
setVerificationErrorCode(errorCode);
|
|
3146
|
+
setCanRetryVerification(canRetry);
|
|
3147
|
+
};
|
|
3148
|
+
const poll = async () => {
|
|
3149
|
+
var _a2;
|
|
3150
|
+
if (paused) return;
|
|
3151
|
+
attempts++;
|
|
3152
|
+
if (attempts > MAX_ATTEMPTS) {
|
|
3153
|
+
setError(
|
|
3154
|
+
"Verification is taking longer than expected. Please try again.",
|
|
3155
|
+
"SESSION_EXPIRED",
|
|
3156
|
+
true
|
|
3157
|
+
);
|
|
3158
|
+
return;
|
|
3159
|
+
}
|
|
3160
|
+
try {
|
|
3161
|
+
const response = await verifyGuardianStatus({
|
|
3162
|
+
accessToken,
|
|
3163
|
+
baseUrl,
|
|
3164
|
+
sessionToken: token
|
|
3165
|
+
});
|
|
3166
|
+
consecutiveErrors = 0;
|
|
3167
|
+
if (response.status === "verified") {
|
|
3168
|
+
stopPolling();
|
|
3169
|
+
const ref = response.verification_reference || ((_a2 = response.guardian_details) == null ? void 0 : _a2.verification_reference);
|
|
3170
|
+
if (!ref) {
|
|
3171
|
+
setError(
|
|
3172
|
+
"Verification completed but no reference received. Please try again.",
|
|
3173
|
+
null,
|
|
3174
|
+
true
|
|
3175
|
+
);
|
|
3176
|
+
return;
|
|
3177
|
+
}
|
|
3178
|
+
setVerificationReference(ref);
|
|
3179
|
+
setIsVerificationComplete(true);
|
|
3180
|
+
clearConsentState();
|
|
3181
|
+
return;
|
|
3182
|
+
}
|
|
3183
|
+
if (response.status === "failed" || response.status === "expired") {
|
|
3184
|
+
setError(
|
|
3185
|
+
getVerificationErrorMessage(response.error_code, response.error),
|
|
3186
|
+
response.error_code,
|
|
3187
|
+
response.can_retry
|
|
3188
|
+
);
|
|
3189
|
+
return;
|
|
3190
|
+
}
|
|
3191
|
+
if (!paused) {
|
|
3192
|
+
statusPollIntervalRef.current = window.setTimeout(poll, POLL_INTERVAL);
|
|
3193
|
+
}
|
|
3194
|
+
} catch (error) {
|
|
3195
|
+
const err = error;
|
|
3196
|
+
if (err.status === 404 || err.status === 410) {
|
|
3197
|
+
setError(
|
|
3198
|
+
"Verification session not found or expired. Please try again.",
|
|
3199
|
+
"SESSION_EXPIRED",
|
|
3200
|
+
true
|
|
3201
|
+
);
|
|
3202
|
+
return;
|
|
3203
|
+
}
|
|
3204
|
+
consecutiveErrors++;
|
|
3205
|
+
if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
|
|
3206
|
+
setError(
|
|
3207
|
+
err.message || "Unable to check verification status. Please try again.",
|
|
3208
|
+
null,
|
|
3209
|
+
true
|
|
3210
|
+
);
|
|
3211
|
+
return;
|
|
3212
|
+
}
|
|
3213
|
+
statusPollIntervalRef.current = window.setTimeout(poll, POLL_INTERVAL);
|
|
3214
|
+
}
|
|
3215
|
+
};
|
|
3216
|
+
const onVisibilityChange = () => {
|
|
3217
|
+
if (document.hidden) {
|
|
3218
|
+
paused = true;
|
|
3219
|
+
if (statusPollIntervalRef.current) {
|
|
3220
|
+
clearTimeout(statusPollIntervalRef.current);
|
|
3221
|
+
statusPollIntervalRef.current = null;
|
|
3222
|
+
}
|
|
3223
|
+
} else {
|
|
3224
|
+
paused = false;
|
|
3225
|
+
poll();
|
|
3226
|
+
}
|
|
3227
|
+
};
|
|
3228
|
+
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
3229
|
+
pollingCleanupRef.current = () => {
|
|
3230
|
+
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
3231
|
+
};
|
|
3232
|
+
statusPollIntervalRef.current = window.setTimeout(poll, POLL_INTERVAL);
|
|
3233
|
+
},
|
|
3234
|
+
[accessToken, baseUrl, getVerificationErrorMessage]
|
|
3235
|
+
);
|
|
3236
|
+
const handleBackToGuardianForm = (0, import_react2.useCallback)((clearName = false) => {
|
|
3237
|
+
var _a2, _b2;
|
|
3238
|
+
(_a2 = verificationPopupRef.current) == null ? void 0 : _a2.close();
|
|
3239
|
+
verificationPopupRef.current = null;
|
|
3240
|
+
if (popupCheckIntervalRef.current) {
|
|
3241
|
+
clearInterval(popupCheckIntervalRef.current);
|
|
3242
|
+
popupCheckIntervalRef.current = null;
|
|
3243
|
+
}
|
|
3244
|
+
if (statusPollIntervalRef.current) {
|
|
3245
|
+
clearTimeout(statusPollIntervalRef.current);
|
|
3246
|
+
statusPollIntervalRef.current = null;
|
|
3247
|
+
}
|
|
3248
|
+
if (autoTransitionTimerRef.current) {
|
|
3249
|
+
clearTimeout(autoTransitionTimerRef.current);
|
|
3250
|
+
autoTransitionTimerRef.current = null;
|
|
3251
|
+
}
|
|
3252
|
+
if (digilockerRedirectTimeoutRef.current) {
|
|
3253
|
+
clearTimeout(digilockerRedirectTimeoutRef.current);
|
|
3254
|
+
digilockerRedirectTimeoutRef.current = null;
|
|
3255
|
+
}
|
|
3256
|
+
(_b2 = pollingCleanupRef.current) == null ? void 0 : _b2.call(pollingCleanupRef);
|
|
3257
|
+
pollingCleanupRef.current = null;
|
|
3258
|
+
setShowVerificationScreen(false);
|
|
3259
|
+
setShowGuardianForm(true);
|
|
3260
|
+
setVerificationError(null);
|
|
3261
|
+
setVerificationErrorCode(null);
|
|
3262
|
+
setCanRetryVerification(false);
|
|
3263
|
+
setIsInitiatingVerification(false);
|
|
3264
|
+
setIsPollingStatus(false);
|
|
3265
|
+
isPollingStatusRef.current = false;
|
|
3266
|
+
setIsVerificationComplete(false);
|
|
3267
|
+
if (clearName) {
|
|
3268
|
+
setGuardianFormData((prev) => ({ ...prev, guardianName: "" }));
|
|
3269
|
+
}
|
|
3270
|
+
clearConsentState();
|
|
3271
|
+
}, []);
|
|
2223
3272
|
const availableLanguages = (0, import_react2.useMemo)(() => {
|
|
2224
3273
|
if (!content) return [language];
|
|
2225
3274
|
const languages = ["English"];
|
|
@@ -2629,12 +3678,67 @@ var RedactoNoticeConsent = ({
|
|
|
2629
3678
|
}, [content, stopAudio]);
|
|
2630
3679
|
(0, import_react2.useEffect)(() => {
|
|
2631
3680
|
return () => {
|
|
3681
|
+
var _a2, _b2;
|
|
2632
3682
|
if (abortControllerRef.current) {
|
|
2633
3683
|
abortControllerRef.current.abort();
|
|
2634
3684
|
}
|
|
2635
3685
|
stopAudio();
|
|
3686
|
+
if (popupCheckIntervalRef.current) {
|
|
3687
|
+
clearInterval(popupCheckIntervalRef.current);
|
|
3688
|
+
}
|
|
3689
|
+
if (statusPollIntervalRef.current) {
|
|
3690
|
+
clearTimeout(statusPollIntervalRef.current);
|
|
3691
|
+
}
|
|
3692
|
+
(_a2 = pollingCleanupRef.current) == null ? void 0 : _a2.call(pollingCleanupRef);
|
|
3693
|
+
pollingCleanupRef.current = null;
|
|
3694
|
+
(_b2 = verificationPopupRef.current) == null ? void 0 : _b2.close();
|
|
3695
|
+
if (autoTransitionTimerRef.current) {
|
|
3696
|
+
clearTimeout(autoTransitionTimerRef.current);
|
|
3697
|
+
autoTransitionTimerRef.current = null;
|
|
3698
|
+
}
|
|
3699
|
+
if (digilockerRedirectTimeoutRef.current) {
|
|
3700
|
+
clearTimeout(digilockerRedirectTimeoutRef.current);
|
|
3701
|
+
digilockerRedirectTimeoutRef.current = null;
|
|
3702
|
+
}
|
|
2636
3703
|
};
|
|
2637
3704
|
}, [stopAudio]);
|
|
3705
|
+
(0, import_react2.useEffect)(() => {
|
|
3706
|
+
const persistedState = getConsentState();
|
|
3707
|
+
if (!persistedState) return;
|
|
3708
|
+
if (persistedState.noticeId && persistedState.noticeId !== noticeId) {
|
|
3709
|
+
clearConsentState();
|
|
3710
|
+
return;
|
|
3711
|
+
}
|
|
3712
|
+
const REDIRECT_STATE_MAX_AGE_MS = 15 * 60 * 1e3;
|
|
3713
|
+
if (persistedState.timestamp) {
|
|
3714
|
+
const stateAge = Date.now() - new Date(persistedState.timestamp).getTime();
|
|
3715
|
+
if (stateAge > REDIRECT_STATE_MAX_AGE_MS) {
|
|
3716
|
+
clearConsentState();
|
|
3717
|
+
return;
|
|
3718
|
+
}
|
|
3719
|
+
}
|
|
3720
|
+
if (persistedState.flowState === "digilocker-pending" && persistedState.sessionToken) {
|
|
3721
|
+
setShowVerificationScreen(true);
|
|
3722
|
+
setShowGuardianForm(false);
|
|
3723
|
+
setShowAgeVerification(false);
|
|
3724
|
+
startStatusPolling(persistedState.sessionToken);
|
|
3725
|
+
} else if (persistedState.verificationResult === "verified" && persistedState.verificationReference) {
|
|
3726
|
+
setVerificationReference(persistedState.verificationReference);
|
|
3727
|
+
setShowVerificationScreen(true);
|
|
3728
|
+
setIsVerificationComplete(true);
|
|
3729
|
+
setShowGuardianForm(false);
|
|
3730
|
+
setShowAgeVerification(false);
|
|
3731
|
+
clearConsentState();
|
|
3732
|
+
} else if (persistedState.verificationResult === "failed" || persistedState.verificationResult === "expired") {
|
|
3733
|
+
setShowVerificationScreen(true);
|
|
3734
|
+
setShowGuardianForm(false);
|
|
3735
|
+
setShowAgeVerification(false);
|
|
3736
|
+
setVerificationError(
|
|
3737
|
+
persistedState.verificationResult === "expired" ? "Verification session has expired. Please try again." : "Verification failed. Please try again."
|
|
3738
|
+
);
|
|
3739
|
+
clearConsentState();
|
|
3740
|
+
}
|
|
3741
|
+
}, [startStatusPolling, noticeId]);
|
|
2638
3742
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: hasAlreadyConsented ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2639
3743
|
blockUI && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2640
3744
|
"div",
|
|
@@ -2820,6 +3924,27 @@ var RedactoNoticeConsent = ({
|
|
|
2820
3924
|
declineButtonStyle,
|
|
2821
3925
|
logoUrl: (content == null ? void 0 : content.logo_url) || redacto_logo_default
|
|
2822
3926
|
}
|
|
3927
|
+
) }) : showVerificationScreen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...styles.content, ...responsiveStyles.content }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
3928
|
+
VerificationScreen,
|
|
3929
|
+
{
|
|
3930
|
+
onBack: handleBackToGuardianForm,
|
|
3931
|
+
onContinue: handleVerificationContinue,
|
|
3932
|
+
isInitiating: isInitiatingVerification,
|
|
3933
|
+
isPolling: isPollingStatus,
|
|
3934
|
+
isVerificationComplete,
|
|
3935
|
+
isAutoTransitioning,
|
|
3936
|
+
error: verificationError,
|
|
3937
|
+
errorCode: verificationErrorCode,
|
|
3938
|
+
canRetry: canRetryVerification,
|
|
3939
|
+
styles,
|
|
3940
|
+
responsiveStyles,
|
|
3941
|
+
settings,
|
|
3942
|
+
componentHeadingStyle,
|
|
3943
|
+
componentTextStyle,
|
|
3944
|
+
acceptButtonStyle,
|
|
3945
|
+
declineButtonStyle,
|
|
3946
|
+
logoUrl: (content == null ? void 0 : content.logo_url) || redacto_logo_default
|
|
3947
|
+
}
|
|
2823
3948
|
) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...styles.content, ...responsiveStyles.content }, children: [
|
|
2824
3949
|
errorMessage && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
2825
3950
|
"div",
|
|
@@ -4423,8 +5548,425 @@ var RedactoConsentInlineComponent = ({
|
|
|
4423
5548
|
};
|
|
4424
5549
|
RedactoConsentInlineComponent.displayName = "RedactoConsentInline";
|
|
4425
5550
|
var RedactoConsentInline = (0, import_react4.memo)(RedactoConsentInlineComponent);
|
|
5551
|
+
|
|
5552
|
+
// src/RedactoNoticeConsent/components/DigiLockerCallback.tsx
|
|
5553
|
+
var import_react5 = require("react");
|
|
5554
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
5555
|
+
var DigiLockerCallback = ({
|
|
5556
|
+
accessToken: propAccessToken,
|
|
5557
|
+
baseUrl,
|
|
5558
|
+
onSuccess,
|
|
5559
|
+
onError
|
|
5560
|
+
}) => {
|
|
5561
|
+
const [status, setStatus] = (0, import_react5.useState)("processing");
|
|
5562
|
+
const [message, setMessage] = (0, import_react5.useState)("Verifying your guardian...");
|
|
5563
|
+
const [errorDetail, setErrorDetail] = (0, import_react5.useState)(null);
|
|
5564
|
+
const retryTimeoutRef = (0, import_react5.useRef)(null);
|
|
5565
|
+
const redirectTimeoutRef = (0, import_react5.useRef)(null);
|
|
5566
|
+
const isMountedRef = (0, import_react5.useRef)(true);
|
|
5567
|
+
const getErrorMessage = (errorCode) => {
|
|
5568
|
+
switch (errorCode) {
|
|
5569
|
+
case "GUARDIAN_UNDER_18":
|
|
5570
|
+
return "Guardian verification failed: The guardian must be 18 years or older.";
|
|
5571
|
+
case "SESSION_EXPIRED":
|
|
5572
|
+
return "Verification session has expired. Please restart the verification process.";
|
|
5573
|
+
case "TOKEN_FAILED":
|
|
5574
|
+
return "DigiLocker authentication failed. Please try again.";
|
|
5575
|
+
case "DIGILOCKER_AUTH_FAILED":
|
|
5576
|
+
return "DigiLocker authorization was cancelled or failed. Please try again.";
|
|
5577
|
+
case "NO_AUTH_CODE":
|
|
5578
|
+
return "Missing authorization code from DigiLocker. Please try again.";
|
|
5579
|
+
default:
|
|
5580
|
+
return "Verification failed. Please try again.";
|
|
5581
|
+
}
|
|
5582
|
+
};
|
|
5583
|
+
const redirectToOriginalPage = (0, import_react5.useCallback)(
|
|
5584
|
+
(originalUrl, verificationResult, verificationReference) => {
|
|
5585
|
+
updateConsentState({
|
|
5586
|
+
verificationResult,
|
|
5587
|
+
verificationReference,
|
|
5588
|
+
flowState: verificationResult === "verified" ? "consent-form" : "error"
|
|
5589
|
+
});
|
|
5590
|
+
redirectTimeoutRef.current = setTimeout(() => {
|
|
5591
|
+
window.location.href = originalUrl;
|
|
5592
|
+
}, 1500);
|
|
5593
|
+
},
|
|
5594
|
+
[]
|
|
5595
|
+
);
|
|
5596
|
+
const handleCallback = (0, import_react5.useCallback)(async () => {
|
|
5597
|
+
var _a, _b;
|
|
5598
|
+
try {
|
|
5599
|
+
const params = new URLSearchParams(window.location.search);
|
|
5600
|
+
const sessionToken = params.get("session_token");
|
|
5601
|
+
const urlStatus = params.get("status");
|
|
5602
|
+
const verificationReference = params.get("verification_reference");
|
|
5603
|
+
const errorCode = params.get("error_code");
|
|
5604
|
+
const persistedState = getConsentState();
|
|
5605
|
+
const originalUrl = (persistedState == null ? void 0 : persistedState.originalUrl) || "/";
|
|
5606
|
+
const storedBaseUrl = persistedState == null ? void 0 : persistedState.baseUrl;
|
|
5607
|
+
const storedSessionToken = persistedState == null ? void 0 : persistedState.sessionToken;
|
|
5608
|
+
const accessToken = propAccessToken;
|
|
5609
|
+
if (!accessToken) {
|
|
5610
|
+
throw new Error("Access token not provided. Please pass accessToken as a prop.");
|
|
5611
|
+
}
|
|
5612
|
+
const activeSessionToken = sessionToken || storedSessionToken;
|
|
5613
|
+
if (!activeSessionToken) {
|
|
5614
|
+
throw new Error("Session token not found. Please restart the verification process.");
|
|
5615
|
+
}
|
|
5616
|
+
let isInIframe = false;
|
|
5617
|
+
try {
|
|
5618
|
+
isInIframe = window.self !== window.top;
|
|
5619
|
+
} catch {
|
|
5620
|
+
isInIframe = true;
|
|
5621
|
+
}
|
|
5622
|
+
if (urlStatus === "verified" && verificationReference) {
|
|
5623
|
+
setStatus("success");
|
|
5624
|
+
setMessage("Guardian verified successfully! Redirecting...");
|
|
5625
|
+
onSuccess == null ? void 0 : onSuccess(verificationReference);
|
|
5626
|
+
if (isInIframe && window.parent) {
|
|
5627
|
+
window.parent.postMessage(
|
|
5628
|
+
{
|
|
5629
|
+
type: "DIGILOCKER_VERIFICATION_STATUS",
|
|
5630
|
+
status: "verified",
|
|
5631
|
+
verificationReference
|
|
5632
|
+
},
|
|
5633
|
+
window.location.origin
|
|
5634
|
+
);
|
|
5635
|
+
return;
|
|
5636
|
+
}
|
|
5637
|
+
redirectToOriginalPage(originalUrl, "verified", verificationReference);
|
|
5638
|
+
return;
|
|
5639
|
+
}
|
|
5640
|
+
if (urlStatus === "failed" || urlStatus === "expired") {
|
|
5641
|
+
const urlErrorCode = errorCode != null ? errorCode : void 0;
|
|
5642
|
+
const errorMessage = getErrorMessage(urlErrorCode);
|
|
5643
|
+
setStatus("error");
|
|
5644
|
+
setMessage("Verification failed");
|
|
5645
|
+
setErrorDetail(errorMessage);
|
|
5646
|
+
onError == null ? void 0 : onError(new Error(errorMessage), urlErrorCode);
|
|
5647
|
+
if (isInIframe && window.parent) {
|
|
5648
|
+
window.parent.postMessage(
|
|
5649
|
+
{
|
|
5650
|
+
type: "DIGILOCKER_VERIFICATION_STATUS",
|
|
5651
|
+
status: urlStatus,
|
|
5652
|
+
errorCode: urlErrorCode,
|
|
5653
|
+
error: errorMessage
|
|
5654
|
+
},
|
|
5655
|
+
window.location.origin
|
|
5656
|
+
);
|
|
5657
|
+
return;
|
|
5658
|
+
}
|
|
5659
|
+
redirectToOriginalPage(originalUrl, urlStatus);
|
|
5660
|
+
return;
|
|
5661
|
+
}
|
|
5662
|
+
setMessage("Processing verification...");
|
|
5663
|
+
const apiBaseUrl = baseUrl || storedBaseUrl;
|
|
5664
|
+
const response = await verifyGuardianStatus({
|
|
5665
|
+
accessToken,
|
|
5666
|
+
baseUrl: apiBaseUrl,
|
|
5667
|
+
sessionToken: activeSessionToken
|
|
5668
|
+
});
|
|
5669
|
+
if (!isMountedRef.current) return;
|
|
5670
|
+
if (response.status === "verified") {
|
|
5671
|
+
const verificationRef = response.verification_reference || ((_a = response.guardian_details) == null ? void 0 : _a.verification_reference) || void 0;
|
|
5672
|
+
if (!verificationRef) {
|
|
5673
|
+
setStatus("error");
|
|
5674
|
+
setMessage("Verification failed");
|
|
5675
|
+
setErrorDetail("Verification completed but no reference received. Please try again.");
|
|
5676
|
+
onError == null ? void 0 : onError(new Error("Verification completed but no reference received."));
|
|
5677
|
+
redirectToOriginalPage(originalUrl, "failed");
|
|
5678
|
+
return;
|
|
5679
|
+
}
|
|
5680
|
+
setStatus("success");
|
|
5681
|
+
setMessage("Guardian verified successfully! Redirecting...");
|
|
5682
|
+
onSuccess == null ? void 0 : onSuccess(verificationRef);
|
|
5683
|
+
if (isInIframe && window.parent) {
|
|
5684
|
+
window.parent.postMessage(
|
|
5685
|
+
{
|
|
5686
|
+
type: "DIGILOCKER_VERIFICATION_STATUS",
|
|
5687
|
+
status: "verified",
|
|
5688
|
+
verificationReference: verificationRef
|
|
5689
|
+
},
|
|
5690
|
+
window.location.origin
|
|
5691
|
+
);
|
|
5692
|
+
return;
|
|
5693
|
+
}
|
|
5694
|
+
redirectToOriginalPage(originalUrl, "verified", verificationRef);
|
|
5695
|
+
} else if (response.status === "failed" || response.status === "expired") {
|
|
5696
|
+
const responseErrorCode = (_b = response.error_code) != null ? _b : void 0;
|
|
5697
|
+
const errorMessage = response.error || getErrorMessage(responseErrorCode);
|
|
5698
|
+
setStatus("error");
|
|
5699
|
+
setMessage("Verification failed");
|
|
5700
|
+
setErrorDetail(errorMessage);
|
|
5701
|
+
onError == null ? void 0 : onError(new Error(errorMessage), responseErrorCode);
|
|
5702
|
+
if (isInIframe && window.parent) {
|
|
5703
|
+
window.parent.postMessage(
|
|
5704
|
+
{
|
|
5705
|
+
type: "DIGILOCKER_VERIFICATION_STATUS",
|
|
5706
|
+
status: response.status,
|
|
5707
|
+
errorCode: responseErrorCode,
|
|
5708
|
+
error: errorMessage
|
|
5709
|
+
},
|
|
5710
|
+
window.location.origin
|
|
5711
|
+
);
|
|
5712
|
+
return;
|
|
5713
|
+
}
|
|
5714
|
+
redirectToOriginalPage(originalUrl, response.status);
|
|
5715
|
+
} else {
|
|
5716
|
+
setMessage("Verification is still in progress. Please wait...");
|
|
5717
|
+
const MAX_RETRIES = 3;
|
|
5718
|
+
let retryCount = 0;
|
|
5719
|
+
const attemptRetry = () => {
|
|
5720
|
+
retryCount++;
|
|
5721
|
+
const delay = 3e3 * Math.pow(2, retryCount - 1);
|
|
5722
|
+
retryTimeoutRef.current = setTimeout(async () => {
|
|
5723
|
+
var _a2, _b2;
|
|
5724
|
+
if (!isMountedRef.current) return;
|
|
5725
|
+
try {
|
|
5726
|
+
const retryResponse = await verifyGuardianStatus({
|
|
5727
|
+
accessToken,
|
|
5728
|
+
baseUrl: apiBaseUrl,
|
|
5729
|
+
sessionToken: activeSessionToken
|
|
5730
|
+
});
|
|
5731
|
+
if (!isMountedRef.current) return;
|
|
5732
|
+
const retryRef = retryResponse.verification_reference || ((_a2 = retryResponse.guardian_details) == null ? void 0 : _a2.verification_reference) || void 0;
|
|
5733
|
+
if (retryResponse.status === "verified" && retryRef) {
|
|
5734
|
+
setStatus("success");
|
|
5735
|
+
setMessage("Guardian verified successfully! Redirecting...");
|
|
5736
|
+
onSuccess == null ? void 0 : onSuccess(retryRef);
|
|
5737
|
+
if (isInIframe && window.parent) {
|
|
5738
|
+
window.parent.postMessage(
|
|
5739
|
+
{
|
|
5740
|
+
type: "DIGILOCKER_VERIFICATION_STATUS",
|
|
5741
|
+
status: "verified",
|
|
5742
|
+
verificationReference: retryRef
|
|
5743
|
+
},
|
|
5744
|
+
window.location.origin
|
|
5745
|
+
);
|
|
5746
|
+
return;
|
|
5747
|
+
}
|
|
5748
|
+
redirectToOriginalPage(originalUrl, "verified", retryRef);
|
|
5749
|
+
} else if (retryResponse.status === "failed" || retryResponse.status === "expired") {
|
|
5750
|
+
const retryErrorCode = (_b2 = retryResponse.error_code) != null ? _b2 : void 0;
|
|
5751
|
+
const retryErrorMessage = retryResponse.error || getErrorMessage(retryErrorCode) || "Verification could not be completed. Please try again.";
|
|
5752
|
+
setStatus("error");
|
|
5753
|
+
setMessage("Verification failed");
|
|
5754
|
+
setErrorDetail(retryErrorMessage);
|
|
5755
|
+
onError == null ? void 0 : onError(new Error(retryErrorMessage), retryErrorCode);
|
|
5756
|
+
if (isInIframe && window.parent) {
|
|
5757
|
+
window.parent.postMessage(
|
|
5758
|
+
{
|
|
5759
|
+
type: "DIGILOCKER_VERIFICATION_STATUS",
|
|
5760
|
+
status: retryResponse.status,
|
|
5761
|
+
errorCode: retryErrorCode,
|
|
5762
|
+
error: retryErrorMessage
|
|
5763
|
+
},
|
|
5764
|
+
window.location.origin
|
|
5765
|
+
);
|
|
5766
|
+
return;
|
|
5767
|
+
}
|
|
5768
|
+
redirectToOriginalPage(originalUrl, retryResponse.status);
|
|
5769
|
+
} else if (retryCount < MAX_RETRIES) {
|
|
5770
|
+
setMessage("Verification taking longer than expected. Please wait...");
|
|
5771
|
+
attemptRetry();
|
|
5772
|
+
} else {
|
|
5773
|
+
const timeoutMessage = "Verification could not be completed in time. Please try again.";
|
|
5774
|
+
setStatus("error");
|
|
5775
|
+
setMessage("Verification failed");
|
|
5776
|
+
setErrorDetail(timeoutMessage);
|
|
5777
|
+
onError == null ? void 0 : onError(new Error(timeoutMessage));
|
|
5778
|
+
redirectToOriginalPage(originalUrl, "failed");
|
|
5779
|
+
}
|
|
5780
|
+
} catch (retryErr) {
|
|
5781
|
+
if (!isMountedRef.current) return;
|
|
5782
|
+
if (retryCount < MAX_RETRIES) {
|
|
5783
|
+
attemptRetry();
|
|
5784
|
+
} else {
|
|
5785
|
+
setStatus("error");
|
|
5786
|
+
setMessage("Verification failed");
|
|
5787
|
+
setErrorDetail(retryErr.message);
|
|
5788
|
+
onError == null ? void 0 : onError(retryErr);
|
|
5789
|
+
redirectToOriginalPage(originalUrl, "failed");
|
|
5790
|
+
}
|
|
5791
|
+
}
|
|
5792
|
+
}, delay);
|
|
5793
|
+
};
|
|
5794
|
+
attemptRetry();
|
|
5795
|
+
}
|
|
5796
|
+
} catch (error) {
|
|
5797
|
+
console.error("DigiLocker callback error:", error);
|
|
5798
|
+
setStatus("error");
|
|
5799
|
+
const err = error;
|
|
5800
|
+
setMessage("Verification failed");
|
|
5801
|
+
setErrorDetail(err.message || "An error occurred during verification");
|
|
5802
|
+
onError == null ? void 0 : onError(err);
|
|
5803
|
+
const persistedState = getConsentState();
|
|
5804
|
+
if (persistedState == null ? void 0 : persistedState.originalUrl) {
|
|
5805
|
+
redirectTimeoutRef.current = setTimeout(() => {
|
|
5806
|
+
redirectToOriginalPage(persistedState.originalUrl, "failed");
|
|
5807
|
+
}, 3e3);
|
|
5808
|
+
}
|
|
5809
|
+
}
|
|
5810
|
+
}, [propAccessToken, baseUrl, onSuccess, onError, redirectToOriginalPage]);
|
|
5811
|
+
(0, import_react5.useEffect)(() => {
|
|
5812
|
+
injectCheckboxStyles();
|
|
5813
|
+
handleCallback();
|
|
5814
|
+
return () => {
|
|
5815
|
+
isMountedRef.current = false;
|
|
5816
|
+
if (retryTimeoutRef.current) clearTimeout(retryTimeoutRef.current);
|
|
5817
|
+
if (redirectTimeoutRef.current) clearTimeout(redirectTimeoutRef.current);
|
|
5818
|
+
};
|
|
5819
|
+
}, [handleCallback]);
|
|
5820
|
+
const handleRetry = (0, import_react5.useCallback)(() => {
|
|
5821
|
+
const persistedState = getConsentState();
|
|
5822
|
+
if (persistedState == null ? void 0 : persistedState.originalUrl) {
|
|
5823
|
+
clearConsentState();
|
|
5824
|
+
window.location.href = persistedState.originalUrl;
|
|
5825
|
+
} else {
|
|
5826
|
+
window.location.href = "/";
|
|
5827
|
+
}
|
|
5828
|
+
}, []);
|
|
5829
|
+
const containerStyle = {
|
|
5830
|
+
display: "flex",
|
|
5831
|
+
alignItems: "center",
|
|
5832
|
+
justifyContent: "center",
|
|
5833
|
+
minHeight: "100vh",
|
|
5834
|
+
backgroundColor: "#f9fafb",
|
|
5835
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
|
5836
|
+
padding: "20px",
|
|
5837
|
+
boxSizing: "border-box"
|
|
5838
|
+
};
|
|
5839
|
+
const cardStyle = {
|
|
5840
|
+
backgroundColor: "#ffffff",
|
|
5841
|
+
borderRadius: "12px",
|
|
5842
|
+
boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
|
|
5843
|
+
padding: "40px",
|
|
5844
|
+
textAlign: "center",
|
|
5845
|
+
maxWidth: "400px",
|
|
5846
|
+
width: "100%"
|
|
5847
|
+
};
|
|
5848
|
+
const spinnerStyle = {
|
|
5849
|
+
width: "48px",
|
|
5850
|
+
height: "48px",
|
|
5851
|
+
border: "4px solid #e5e7eb",
|
|
5852
|
+
borderTopColor: "#3b82f6",
|
|
5853
|
+
borderRadius: "50%",
|
|
5854
|
+
animation: "spin 1s linear infinite",
|
|
5855
|
+
margin: "0 auto 24px"
|
|
5856
|
+
};
|
|
5857
|
+
const iconStyle = {
|
|
5858
|
+
width: "64px",
|
|
5859
|
+
height: "64px",
|
|
5860
|
+
borderRadius: "50%",
|
|
5861
|
+
display: "flex",
|
|
5862
|
+
alignItems: "center",
|
|
5863
|
+
justifyContent: "center",
|
|
5864
|
+
margin: "0 auto 24px"
|
|
5865
|
+
};
|
|
5866
|
+
const successIconStyle = {
|
|
5867
|
+
...iconStyle,
|
|
5868
|
+
backgroundColor: "#d1fae5",
|
|
5869
|
+
color: "#059669"
|
|
5870
|
+
};
|
|
5871
|
+
const errorIconStyle = {
|
|
5872
|
+
...iconStyle,
|
|
5873
|
+
backgroundColor: "#fee2e2",
|
|
5874
|
+
color: "#dc2626"
|
|
5875
|
+
};
|
|
5876
|
+
const titleStyle = {
|
|
5877
|
+
fontSize: "20px",
|
|
5878
|
+
fontWeight: 600,
|
|
5879
|
+
color: "#111827",
|
|
5880
|
+
margin: "0 0 12px 0"
|
|
5881
|
+
};
|
|
5882
|
+
const messageStyle = {
|
|
5883
|
+
fontSize: "14px",
|
|
5884
|
+
color: "#6b7280",
|
|
5885
|
+
marginBottom: "8px",
|
|
5886
|
+
lineHeight: 1.5
|
|
5887
|
+
};
|
|
5888
|
+
const errorDetailStyle = {
|
|
5889
|
+
fontSize: "13px",
|
|
5890
|
+
color: "#dc2626",
|
|
5891
|
+
marginTop: "12px",
|
|
5892
|
+
padding: "12px",
|
|
5893
|
+
backgroundColor: "#fef2f2",
|
|
5894
|
+
borderRadius: "6px",
|
|
5895
|
+
border: "1px solid #fecaca"
|
|
5896
|
+
};
|
|
5897
|
+
const buttonStyle = {
|
|
5898
|
+
marginTop: "20px",
|
|
5899
|
+
padding: "10px 24px",
|
|
5900
|
+
backgroundColor: "#3b82f6",
|
|
5901
|
+
color: "#ffffff",
|
|
5902
|
+
border: "none",
|
|
5903
|
+
borderRadius: "6px",
|
|
5904
|
+
fontSize: "14px",
|
|
5905
|
+
fontWeight: 500,
|
|
5906
|
+
cursor: "pointer",
|
|
5907
|
+
transition: "background-color 0.2s"
|
|
5908
|
+
};
|
|
5909
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: containerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: cardStyle, children: [
|
|
5910
|
+
status === "processing" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
5911
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: spinnerStyle }),
|
|
5912
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { style: titleStyle, children: "Processing Verification" }),
|
|
5913
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: messageStyle, children: message }),
|
|
5914
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: { ...messageStyle, fontSize: "12px", color: "#9ca3af" }, children: "Please wait while we verify your guardian's identity..." })
|
|
5915
|
+
] }),
|
|
5916
|
+
status === "success" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
5917
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: successIconStyle, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
5918
|
+
"svg",
|
|
5919
|
+
{
|
|
5920
|
+
width: "32",
|
|
5921
|
+
height: "32",
|
|
5922
|
+
viewBox: "0 0 24 24",
|
|
5923
|
+
fill: "none",
|
|
5924
|
+
stroke: "currentColor",
|
|
5925
|
+
strokeWidth: "2",
|
|
5926
|
+
strokeLinecap: "round",
|
|
5927
|
+
strokeLinejoin: "round",
|
|
5928
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("polyline", { points: "20 6 9 17 4 12" })
|
|
5929
|
+
}
|
|
5930
|
+
) }),
|
|
5931
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { style: titleStyle, children: "Verification Successful" }),
|
|
5932
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: messageStyle, children: message })
|
|
5933
|
+
] }),
|
|
5934
|
+
status === "error" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
5935
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: errorIconStyle, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
5936
|
+
"svg",
|
|
5937
|
+
{
|
|
5938
|
+
width: "32",
|
|
5939
|
+
height: "32",
|
|
5940
|
+
viewBox: "0 0 24 24",
|
|
5941
|
+
fill: "none",
|
|
5942
|
+
stroke: "currentColor",
|
|
5943
|
+
strokeWidth: "2",
|
|
5944
|
+
strokeLinecap: "round",
|
|
5945
|
+
strokeLinejoin: "round",
|
|
5946
|
+
children: [
|
|
5947
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
5948
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
5949
|
+
]
|
|
5950
|
+
}
|
|
5951
|
+
) }),
|
|
5952
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { style: titleStyle, children: "Verification Failed" }),
|
|
5953
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: messageStyle, children: message }),
|
|
5954
|
+
errorDetail && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: errorDetailStyle, children: errorDetail }),
|
|
5955
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
5956
|
+
"button",
|
|
5957
|
+
{
|
|
5958
|
+
className: "redacto-dl-retry-btn",
|
|
5959
|
+
style: buttonStyle,
|
|
5960
|
+
onClick: handleRetry,
|
|
5961
|
+
children: "Try Again"
|
|
5962
|
+
}
|
|
5963
|
+
)
|
|
5964
|
+
] })
|
|
5965
|
+
] }) });
|
|
5966
|
+
};
|
|
4426
5967
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4427
5968
|
0 && (module.exports = {
|
|
5969
|
+
DigiLockerCallback,
|
|
4428
5970
|
RedactoNoticeConsent,
|
|
4429
5971
|
RedactoNoticeConsentInline
|
|
4430
5972
|
});
|