@redacto.io/consent-sdk-react 3.4.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 +12 -0
- package/dist/index.d.mts +49 -2
- package/dist/index.d.ts +49 -2
- package/dist/index.js +1806 -345
- package/dist/index.mjs +1805 -345
- 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 +335 -246
- package/src/RedactoNoticeConsent/api/types.ts +138 -41
- 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/RedactoNoticeConsentInline/api/index.ts +26 -64
- package/src/RedactoNoticeConsentInline/api/types.ts +0 -25
- package/src/index.ts +10 -0
- package/src/utils/isLegacyApi.ts +0 -12
package/dist/index.mjs
CHANGED
|
@@ -3,21 +3,6 @@ import { useCallback, useEffect as useEffect2, useMemo, useRef, useState as useS
|
|
|
3
3
|
|
|
4
4
|
// src/RedactoNoticeConsent/api/index.ts
|
|
5
5
|
import { jwtDecode } from "jwt-decode";
|
|
6
|
-
|
|
7
|
-
// src/utils/isLegacyApi.ts
|
|
8
|
-
function isLegacyApi(baseUrl) {
|
|
9
|
-
try {
|
|
10
|
-
return new URL(baseUrl).hostname.endsWith(".redacto.io");
|
|
11
|
-
} catch {
|
|
12
|
-
try {
|
|
13
|
-
return new URL(`https://${baseUrl}`).hostname.endsWith(".redacto.io");
|
|
14
|
-
} catch {
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// src/RedactoNoticeConsent/api/index.ts
|
|
21
6
|
var BASE_URL = "https://api.redacto.io/consent";
|
|
22
7
|
var apiCache = /* @__PURE__ */ new Map();
|
|
23
8
|
var CACHE_TTL = 5 * 60 * 1e3;
|
|
@@ -54,73 +39,66 @@ var fetchConsentContent = async ({
|
|
|
54
39
|
validate_against = "all",
|
|
55
40
|
include_fully_consented_data = false,
|
|
56
41
|
signal
|
|
57
|
-
// AbortSignal for request cancellation
|
|
58
42
|
}) => {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
return cachedData;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
const url = new URL(
|
|
80
|
-
`${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/notices/${noticeId}`
|
|
81
|
-
);
|
|
82
|
-
if (specific_uuid) {
|
|
83
|
-
url.searchParams.append("specific_uuid", specific_uuid);
|
|
84
|
-
}
|
|
85
|
-
url.searchParams.append("validate_against", validate_against);
|
|
86
|
-
if (include_fully_consented_data) {
|
|
87
|
-
url.searchParams.append("include_fully_consented_data", "true");
|
|
88
|
-
}
|
|
89
|
-
const response = await fetch(url.toString(), {
|
|
90
|
-
method: "GET",
|
|
91
|
-
headers: {
|
|
92
|
-
Authorization: `Bearer ${accessToken}`,
|
|
93
|
-
"Accept-Language": language,
|
|
94
|
-
"Content-Type": "application/json"
|
|
95
|
-
},
|
|
96
|
-
signal
|
|
97
|
-
// Add abort signal for request cancellation
|
|
98
|
-
});
|
|
99
|
-
if (!response.ok) {
|
|
100
|
-
let errorMessage = `Failed to fetch consent content: ${response.status} ${response.statusText}`;
|
|
101
|
-
if (response.status === 401) {
|
|
102
|
-
errorMessage = "Unauthorized: Invalid or expired token";
|
|
103
|
-
} else if (response.status === 403) {
|
|
104
|
-
errorMessage = "Forbidden: Access denied";
|
|
105
|
-
} else if (response.status === 404) {
|
|
106
|
-
errorMessage = "Notice not found";
|
|
107
|
-
} else if (response.status === 409) {
|
|
108
|
-
errorMessage = "User has already provided consent";
|
|
109
|
-
} else if (response.status >= 500) {
|
|
110
|
-
errorMessage = "Server error: Please try again later";
|
|
111
|
-
}
|
|
112
|
-
const error = new Error(errorMessage);
|
|
113
|
-
error.status = response.status;
|
|
114
|
-
throw error;
|
|
43
|
+
if (!noticeId || !accessToken || !validate_against) {
|
|
44
|
+
throw new Error("noticeId and accessToken are required");
|
|
45
|
+
}
|
|
46
|
+
const decodedToken = decodeTokenSafely(accessToken);
|
|
47
|
+
if (!decodedToken) {
|
|
48
|
+
throw new Error("Invalid access token");
|
|
49
|
+
}
|
|
50
|
+
const { organisation_uuid: ORGANISATION_UUID, workspace_uuid: WORKSPACE_UUID } = decodedToken;
|
|
51
|
+
if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
|
|
52
|
+
throw new Error("Invalid token: missing organization or workspace UUID");
|
|
53
|
+
}
|
|
54
|
+
const apiBaseUrl = baseUrl || BASE_URL;
|
|
55
|
+
const cacheKey = `${accessToken}-${noticeId}-${validate_against}-${language}-${specific_uuid || ""}-${include_fully_consented_data}`;
|
|
56
|
+
if (validate_against === "all" && !specific_uuid) {
|
|
57
|
+
const cachedData = getCachedData(cacheKey);
|
|
58
|
+
if (cachedData) {
|
|
59
|
+
return cachedData;
|
|
115
60
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
61
|
+
}
|
|
62
|
+
const url = new URL(
|
|
63
|
+
`${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/notices/${noticeId}`
|
|
64
|
+
);
|
|
65
|
+
if (specific_uuid) {
|
|
66
|
+
url.searchParams.append("specific_uuid", specific_uuid);
|
|
67
|
+
}
|
|
68
|
+
url.searchParams.append("validate_against", validate_against);
|
|
69
|
+
if (include_fully_consented_data) {
|
|
70
|
+
url.searchParams.append("include_fully_consented_data", "true");
|
|
71
|
+
}
|
|
72
|
+
const response = await fetch(url.toString(), {
|
|
73
|
+
method: "GET",
|
|
74
|
+
headers: {
|
|
75
|
+
Authorization: `Bearer ${accessToken}`,
|
|
76
|
+
"Accept-Language": language
|
|
77
|
+
},
|
|
78
|
+
signal
|
|
79
|
+
});
|
|
80
|
+
if (!response.ok) {
|
|
81
|
+
let errorMessage = `Failed to fetch consent content: ${response.status} ${response.statusText}`;
|
|
82
|
+
if (response.status === 401) {
|
|
83
|
+
errorMessage = "Unauthorized: Invalid or expired token";
|
|
84
|
+
} else if (response.status === 403) {
|
|
85
|
+
errorMessage = "Forbidden: Access denied";
|
|
86
|
+
} else if (response.status === 404) {
|
|
87
|
+
errorMessage = "Notice not found";
|
|
88
|
+
} else if (response.status === 409) {
|
|
89
|
+
errorMessage = "User has already provided consent";
|
|
90
|
+
} else if (response.status >= 500) {
|
|
91
|
+
errorMessage = "Server error: Please try again later";
|
|
119
92
|
}
|
|
120
|
-
|
|
121
|
-
|
|
93
|
+
const error = new Error(errorMessage);
|
|
94
|
+
error.status = response.status;
|
|
122
95
|
throw error;
|
|
123
96
|
}
|
|
97
|
+
const data = await response.json();
|
|
98
|
+
if (validate_against === "all" && !specific_uuid) {
|
|
99
|
+
setCachedData(cacheKey, data);
|
|
100
|
+
}
|
|
101
|
+
return data;
|
|
124
102
|
};
|
|
125
103
|
var submitConsentEvent = async ({
|
|
126
104
|
accessToken,
|
|
@@ -129,133 +107,151 @@ var submitConsentEvent = async ({
|
|
|
129
107
|
purposes,
|
|
130
108
|
declined,
|
|
131
109
|
meta_data,
|
|
110
|
+
guardianVerificationReference,
|
|
111
|
+
selfDeclaredAdult,
|
|
132
112
|
signal
|
|
133
|
-
// AbortSignal for request cancellation
|
|
134
113
|
}) => {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
114
|
+
if (!noticeUuid || !accessToken || !Array.isArray(purposes)) {
|
|
115
|
+
throw new Error("noticeUuid, accessToken, and purposes array are required");
|
|
116
|
+
}
|
|
117
|
+
const decodedToken = decodeTokenSafely(accessToken);
|
|
118
|
+
if (!decodedToken) {
|
|
119
|
+
throw new Error("Invalid access token");
|
|
120
|
+
}
|
|
121
|
+
const { organisation_uuid: ORGANISATION_UUID, workspace_uuid: WORKSPACE_UUID } = decodedToken;
|
|
122
|
+
if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
|
|
123
|
+
throw new Error("Invalid token: missing organization or workspace UUID");
|
|
124
|
+
}
|
|
125
|
+
const apiBaseUrl = baseUrl || BASE_URL;
|
|
126
|
+
const validatedPurposes = purposes.map((purpose) => {
|
|
127
|
+
if (!purpose.uuid) {
|
|
128
|
+
throw new Error(`Invalid purpose data: missing uuid`);
|
|
146
129
|
}
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
meta_data: meta_data ? { specific_uuid: meta_data.specific_uuid } : void 0
|
|
178
|
-
};
|
|
179
|
-
} else {
|
|
180
|
-
const validatedPurposes = purposes.map((purpose) => {
|
|
181
|
-
if (!purpose.uuid) {
|
|
182
|
-
throw new Error(`Invalid purpose data: missing uuid`);
|
|
183
|
-
}
|
|
184
|
-
const dataElements = (purpose.data_elements || []).filter((element) => element.enabled).map((element) => ({
|
|
185
|
-
uuid: element.uuid,
|
|
186
|
-
selected: element.required ? true : Boolean(element.selected)
|
|
187
|
-
}));
|
|
188
|
-
return {
|
|
189
|
-
purpose_uuid: purpose.uuid,
|
|
190
|
-
selected: Boolean(purpose.selected),
|
|
191
|
-
data_elements: dataElements.length > 0 ? dataElements : void 0
|
|
192
|
-
};
|
|
193
|
-
});
|
|
194
|
-
payload = {
|
|
195
|
-
notice_uuid: noticeUuid,
|
|
196
|
-
purposes: validatedPurposes,
|
|
197
|
-
select_all_mandatory: false,
|
|
198
|
-
source: "WEB",
|
|
199
|
-
declined: Boolean(declined),
|
|
200
|
-
meta_data: meta_data ? { specific_uuid: meta_data.specific_uuid } : void 0
|
|
201
|
-
};
|
|
130
|
+
const dataElements = (purpose.data_elements || []).filter((element) => element.enabled).map((element) => ({
|
|
131
|
+
uuid: element.uuid,
|
|
132
|
+
selected: element.required ? true : Boolean(element.selected)
|
|
133
|
+
}));
|
|
134
|
+
return {
|
|
135
|
+
purpose_uuid: purpose.uuid,
|
|
136
|
+
selected: Boolean(purpose.selected),
|
|
137
|
+
data_elements: dataElements.length > 0 ? dataElements : void 0
|
|
138
|
+
};
|
|
139
|
+
});
|
|
140
|
+
const payload = {
|
|
141
|
+
notice_uuid: noticeUuid,
|
|
142
|
+
purposes: validatedPurposes,
|
|
143
|
+
select_all_mandatory: false,
|
|
144
|
+
source: "WEB",
|
|
145
|
+
declined: Boolean(declined),
|
|
146
|
+
meta_data: meta_data ? { specific_uuid: meta_data.specific_uuid, minor_age: meta_data.minor_age } : void 0,
|
|
147
|
+
guardian_verification_reference: guardianVerificationReference,
|
|
148
|
+
self_declared_adult: selfDeclaredAdult
|
|
149
|
+
};
|
|
150
|
+
const response = await fetch(
|
|
151
|
+
`${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/submit-consent`,
|
|
152
|
+
{
|
|
153
|
+
method: "POST",
|
|
154
|
+
headers: {
|
|
155
|
+
Authorization: `Bearer ${accessToken}`,
|
|
156
|
+
"Content-Type": "application/json"
|
|
157
|
+
},
|
|
158
|
+
body: JSON.stringify(payload),
|
|
159
|
+
signal
|
|
202
160
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
body: JSON.stringify(payload),
|
|
212
|
-
signal
|
|
213
|
-
// Add abort signal for request cancellation
|
|
214
|
-
}
|
|
215
|
-
);
|
|
216
|
-
if (!response.ok) {
|
|
217
|
-
let errorMessage = `Failed to submit consent: ${response.status} ${response.statusText}`;
|
|
218
|
-
if (response.status === 400) {
|
|
161
|
+
);
|
|
162
|
+
if (!response.ok) {
|
|
163
|
+
let errorMessage = `Failed to submit consent: ${response.status} ${response.statusText}`;
|
|
164
|
+
if (response.status === 400) {
|
|
165
|
+
try {
|
|
166
|
+
const errorData = await response.json();
|
|
167
|
+
errorMessage = errorData.message || "Invalid request data";
|
|
168
|
+
} catch {
|
|
219
169
|
errorMessage = "Invalid request data";
|
|
220
|
-
} else if (response.status === 401) {
|
|
221
|
-
errorMessage = "Unauthorized: Invalid or expired token";
|
|
222
|
-
} else if (response.status === 403) {
|
|
223
|
-
errorMessage = "Forbidden: Access denied";
|
|
224
|
-
} else if (response.status === 404) {
|
|
225
|
-
errorMessage = "Notice not found";
|
|
226
|
-
} else if (response.status >= 500) {
|
|
227
|
-
errorMessage = "Server error: Please try again later";
|
|
228
170
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
171
|
+
} else if (response.status === 401) {
|
|
172
|
+
errorMessage = "Unauthorized: Invalid or expired token";
|
|
173
|
+
} else if (response.status === 403) {
|
|
174
|
+
errorMessage = "Forbidden: Access denied";
|
|
175
|
+
} else if (response.status === 404) {
|
|
176
|
+
errorMessage = "Notice not found";
|
|
177
|
+
} else if (response.status >= 500) {
|
|
178
|
+
errorMessage = "Server error: Please try again later";
|
|
232
179
|
}
|
|
233
|
-
|
|
234
|
-
|
|
180
|
+
const error = new Error(errorMessage);
|
|
181
|
+
error.status = response.status;
|
|
235
182
|
throw error;
|
|
236
183
|
}
|
|
184
|
+
apiCache.clear();
|
|
237
185
|
};
|
|
238
|
-
var
|
|
186
|
+
var fetchTTSAudioUrls = async ({
|
|
187
|
+
accessToken,
|
|
188
|
+
baseUrl,
|
|
189
|
+
noticeUuid,
|
|
190
|
+
language,
|
|
191
|
+
signal
|
|
192
|
+
}) => {
|
|
193
|
+
if (!accessToken || !noticeUuid || !language) {
|
|
194
|
+
throw new Error("accessToken, noticeUuid, and language are required");
|
|
195
|
+
}
|
|
196
|
+
const decodedToken = decodeTokenSafely(accessToken);
|
|
197
|
+
if (!decodedToken) {
|
|
198
|
+
throw new Error("Invalid access token");
|
|
199
|
+
}
|
|
200
|
+
const { organisation_uuid: ORGANISATION_UUID, workspace_uuid: WORKSPACE_UUID } = decodedToken;
|
|
201
|
+
if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
|
|
202
|
+
throw new Error("Invalid token: missing organization or workspace UUID");
|
|
203
|
+
}
|
|
204
|
+
const apiBaseUrl = baseUrl || BASE_URL;
|
|
205
|
+
const url = `${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/notices/${noticeUuid}/audio/${language}`;
|
|
206
|
+
const response = await fetch(url, {
|
|
207
|
+
method: "GET",
|
|
208
|
+
headers: {
|
|
209
|
+
Authorization: `Bearer ${accessToken}`,
|
|
210
|
+
Accept: "application/json"
|
|
211
|
+
},
|
|
212
|
+
signal
|
|
213
|
+
});
|
|
214
|
+
if (!response.ok) {
|
|
215
|
+
let errorMessage = `Failed to fetch TTS audio URLs: ${response.status} ${response.statusText}`;
|
|
216
|
+
if (response.status === 401) {
|
|
217
|
+
errorMessage = "Unauthorized: Invalid or expired token";
|
|
218
|
+
} else if (response.status === 403) {
|
|
219
|
+
errorMessage = "Forbidden: Access denied";
|
|
220
|
+
} else if (response.status === 404) {
|
|
221
|
+
errorMessage = "Notice or audio not found";
|
|
222
|
+
} else if (response.status >= 500) {
|
|
223
|
+
errorMessage = "Server error: Please try again later";
|
|
224
|
+
}
|
|
225
|
+
const error = new Error(errorMessage);
|
|
226
|
+
error.status = response.status;
|
|
227
|
+
throw error;
|
|
228
|
+
}
|
|
229
|
+
const data = await response.json();
|
|
230
|
+
return data;
|
|
231
|
+
};
|
|
232
|
+
var initiateGuardianVerification = async ({
|
|
239
233
|
accessToken,
|
|
240
234
|
baseUrl,
|
|
241
235
|
guardianName,
|
|
242
236
|
guardianContact,
|
|
243
237
|
guardianRelationship,
|
|
238
|
+
frontendCallbackUrl,
|
|
239
|
+
metadata,
|
|
244
240
|
signal
|
|
245
|
-
// AbortSignal for request cancellation
|
|
246
241
|
}) => {
|
|
242
|
+
var _a;
|
|
247
243
|
try {
|
|
248
244
|
if (!accessToken) {
|
|
249
245
|
throw new Error("accessToken is required");
|
|
250
246
|
}
|
|
251
247
|
if (!(guardianName == null ? void 0 : guardianName.trim())) {
|
|
252
|
-
throw new Error("
|
|
248
|
+
throw new Error("Guardian name is required");
|
|
253
249
|
}
|
|
254
250
|
if (!(guardianContact == null ? void 0 : guardianContact.trim())) {
|
|
255
|
-
throw new Error("
|
|
251
|
+
throw new Error("Guardian contact is required");
|
|
256
252
|
}
|
|
257
253
|
if (!(guardianRelationship == null ? void 0 : guardianRelationship.trim())) {
|
|
258
|
-
throw new Error("
|
|
254
|
+
throw new Error("Guardian relationship is required");
|
|
259
255
|
}
|
|
260
256
|
const decodedToken = decodeTokenSafely(accessToken);
|
|
261
257
|
if (!decodedToken) {
|
|
@@ -265,14 +261,20 @@ var submitGuardianInfo = async ({
|
|
|
265
261
|
if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
|
|
266
262
|
throw new Error("Invalid token: missing organization or workspace UUID");
|
|
267
263
|
}
|
|
264
|
+
const apiBaseUrl = baseUrl || BASE_URL;
|
|
268
265
|
const payload = {
|
|
269
266
|
guardian_name: guardianName.trim(),
|
|
270
267
|
guardian_contact: guardianContact.trim(),
|
|
271
268
|
guardian_relationship: guardianRelationship.trim()
|
|
272
269
|
};
|
|
273
|
-
|
|
270
|
+
if (frontendCallbackUrl) {
|
|
271
|
+
payload.frontend_callback_url = frontendCallbackUrl;
|
|
272
|
+
}
|
|
273
|
+
if (metadata) {
|
|
274
|
+
payload.metadata = metadata;
|
|
275
|
+
}
|
|
274
276
|
const response = await fetch(
|
|
275
|
-
`${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/guardian-
|
|
277
|
+
`${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/guardian/initiate-verification`,
|
|
276
278
|
{
|
|
277
279
|
method: "POST",
|
|
278
280
|
headers: {
|
|
@@ -281,24 +283,26 @@ var submitGuardianInfo = async ({
|
|
|
281
283
|
},
|
|
282
284
|
body: JSON.stringify(payload),
|
|
283
285
|
signal
|
|
284
|
-
// Add abort signal for request cancellation
|
|
285
286
|
}
|
|
286
287
|
);
|
|
287
288
|
if (!response.ok) {
|
|
288
|
-
let errorMessage = `Failed to
|
|
289
|
+
let errorMessage = `Failed to initiate verification: ${response.status} ${response.statusText}`;
|
|
289
290
|
if (response.status === 400) {
|
|
290
|
-
|
|
291
|
+
try {
|
|
292
|
+
const errorData = await response.json();
|
|
293
|
+
errorMessage = errorData.message || "Invalid request data";
|
|
294
|
+
} catch {
|
|
295
|
+
errorMessage = "Invalid request data";
|
|
296
|
+
}
|
|
291
297
|
} else if (response.status === 401) {
|
|
292
298
|
errorMessage = "Unauthorized: Invalid or expired token";
|
|
293
|
-
} else if (response.status === 403) {
|
|
294
|
-
errorMessage = "Forbidden: Access denied";
|
|
295
299
|
} else if (response.status === 404) {
|
|
296
300
|
errorMessage = "Organization or workspace not found";
|
|
297
301
|
} else if (response.status === 422) {
|
|
298
302
|
try {
|
|
299
303
|
const errorData = await response.json();
|
|
300
|
-
errorMessage = errorData.message || "Validation error";
|
|
301
|
-
} catch
|
|
304
|
+
errorMessage = errorData.message || "Validation error: Please check your input";
|
|
305
|
+
} catch {
|
|
302
306
|
errorMessage = "Validation error: Please check your input";
|
|
303
307
|
}
|
|
304
308
|
} else if (response.status >= 500) {
|
|
@@ -308,63 +312,98 @@ var submitGuardianInfo = async ({
|
|
|
308
312
|
error.status = response.status;
|
|
309
313
|
throw error;
|
|
310
314
|
}
|
|
315
|
+
const responseData = await response.json();
|
|
316
|
+
const detail = responseData.detail || responseData;
|
|
317
|
+
if (detail.already_verified) {
|
|
318
|
+
return {
|
|
319
|
+
success: true,
|
|
320
|
+
guardian_info_uuid: detail.guardian_info_uuid,
|
|
321
|
+
already_verified: true,
|
|
322
|
+
verification_reference: detail.verification_reference
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
if (!detail.session_token || !detail.digilocker_redirect_url) {
|
|
326
|
+
throw new Error("Invalid response: missing session_token or digilocker_redirect_url");
|
|
327
|
+
}
|
|
328
|
+
return {
|
|
329
|
+
success: (_a = detail.success) != null ? _a : true,
|
|
330
|
+
guardian_info_uuid: detail.guardian_info_uuid,
|
|
331
|
+
already_verified: false,
|
|
332
|
+
session_token: detail.session_token,
|
|
333
|
+
digilocker_redirect_url: detail.digilocker_redirect_url,
|
|
334
|
+
expires_at: detail.expires_at
|
|
335
|
+
};
|
|
311
336
|
} catch (error) {
|
|
312
|
-
console.error("Error
|
|
337
|
+
console.error("Error initiating guardian verification:", error instanceof Error ? error.message : error);
|
|
313
338
|
throw error;
|
|
314
339
|
}
|
|
315
340
|
};
|
|
316
|
-
var
|
|
341
|
+
var verifyGuardianStatus = async ({
|
|
317
342
|
accessToken,
|
|
318
343
|
baseUrl,
|
|
319
|
-
|
|
320
|
-
language,
|
|
344
|
+
sessionToken,
|
|
321
345
|
signal
|
|
322
|
-
// AbortSignal for request cancellation
|
|
323
346
|
}) => {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
347
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
348
|
+
if (!accessToken || !sessionToken) {
|
|
349
|
+
throw new Error("accessToken and sessionToken are required");
|
|
350
|
+
}
|
|
351
|
+
const decodedToken = decodeTokenSafely(accessToken);
|
|
352
|
+
if (!decodedToken) {
|
|
353
|
+
throw new Error("Invalid access token");
|
|
354
|
+
}
|
|
355
|
+
const { organisation_uuid: ORGANISATION_UUID, workspace_uuid: WORKSPACE_UUID } = decodedToken;
|
|
356
|
+
if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
|
|
357
|
+
throw new Error("Invalid token: missing organization or workspace UUID");
|
|
358
|
+
}
|
|
359
|
+
const apiBaseUrl = baseUrl || BASE_URL;
|
|
360
|
+
const response = await fetch(
|
|
361
|
+
`${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/guardian/verify-status`,
|
|
362
|
+
{
|
|
363
|
+
method: "POST",
|
|
340
364
|
headers: {
|
|
341
365
|
Authorization: `Bearer ${accessToken}`,
|
|
342
|
-
Accept: "application/json",
|
|
343
366
|
"Content-Type": "application/json"
|
|
344
367
|
},
|
|
368
|
+
body: JSON.stringify({
|
|
369
|
+
session_token: sessionToken
|
|
370
|
+
}),
|
|
345
371
|
signal
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
errorMessage =
|
|
354
|
-
}
|
|
355
|
-
errorMessage = "
|
|
356
|
-
} else if (response.status >= 500) {
|
|
357
|
-
errorMessage = "Server error: Please try again later";
|
|
372
|
+
}
|
|
373
|
+
);
|
|
374
|
+
if (!response.ok) {
|
|
375
|
+
let errorMessage = `Failed to check verification status: ${response.status} ${response.statusText}`;
|
|
376
|
+
if (response.status === 400) {
|
|
377
|
+
try {
|
|
378
|
+
const errorData = await response.json();
|
|
379
|
+
errorMessage = errorData.message || ((_a = errorData.detail) == null ? void 0 : _a.message) || "Invalid session token";
|
|
380
|
+
} catch {
|
|
381
|
+
errorMessage = "Invalid session token";
|
|
358
382
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
383
|
+
} else if (response.status === 401) {
|
|
384
|
+
errorMessage = "Unauthorized: Invalid or expired token";
|
|
385
|
+
} else if (response.status === 404) {
|
|
386
|
+
errorMessage = "Verification session not found or expired. Please restart the verification process.";
|
|
387
|
+
} else if (response.status === 410) {
|
|
388
|
+
errorMessage = "Verification session has expired. Please restart the verification process.";
|
|
389
|
+
} else if (response.status >= 500) {
|
|
390
|
+
errorMessage = "Server error: Please try again later";
|
|
362
391
|
}
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
} catch (error) {
|
|
392
|
+
const error = new Error(errorMessage);
|
|
393
|
+
error.status = response.status;
|
|
366
394
|
throw error;
|
|
367
395
|
}
|
|
396
|
+
const responseData = await response.json();
|
|
397
|
+
const detail = responseData.detail || responseData;
|
|
398
|
+
return {
|
|
399
|
+
status: (_b = detail.status) != null ? _b : "in_progress",
|
|
400
|
+
guardian_info_uuid: (_c = detail.guardian_info_uuid) != null ? _c : null,
|
|
401
|
+
verification_reference: (_d = detail.verification_reference) != null ? _d : null,
|
|
402
|
+
guardian_details: (_e = detail.guardian_details) != null ? _e : null,
|
|
403
|
+
error: (_f = detail.error) != null ? _f : null,
|
|
404
|
+
error_code: (_g = detail.error_code) != null ? _g : null,
|
|
405
|
+
can_retry: (_h = detail.can_retry) != null ? _h : true
|
|
406
|
+
};
|
|
368
407
|
};
|
|
369
408
|
|
|
370
409
|
// src/RedactoNoticeConsent/assets/redacto-logo.png
|
|
@@ -512,6 +551,17 @@ var injectCheckboxStyles = () => {
|
|
|
512
551
|
outline: 3px solid #FFF9C4 !important;
|
|
513
552
|
outline-offset: 2px !important;
|
|
514
553
|
}
|
|
554
|
+
|
|
555
|
+
/* Spinner animation for verification screens */
|
|
556
|
+
@keyframes spin {
|
|
557
|
+
from { transform: rotate(0deg); }
|
|
558
|
+
to { transform: rotate(360deg); }
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/* DigiLocker callback retry button hover */
|
|
562
|
+
.redacto-dl-retry-btn:hover {
|
|
563
|
+
background-color: #2563eb !important;
|
|
564
|
+
}
|
|
515
565
|
`;
|
|
516
566
|
document.head.appendChild(style);
|
|
517
567
|
stylesInjected = true;
|
|
@@ -894,6 +944,69 @@ var useMediaQuery = (query) => {
|
|
|
894
944
|
return matches;
|
|
895
945
|
};
|
|
896
946
|
|
|
947
|
+
// src/RedactoNoticeConsent/services/storage.ts
|
|
948
|
+
var STORAGE_KEY = "redacto_consent_sdk_state";
|
|
949
|
+
var STATE_EXPIRY_MS = 30 * 60 * 1e3;
|
|
950
|
+
var isBrowser = () => {
|
|
951
|
+
return typeof window !== "undefined" && typeof window.sessionStorage !== "undefined";
|
|
952
|
+
};
|
|
953
|
+
var saveConsentState = (state) => {
|
|
954
|
+
if (!isBrowser()) {
|
|
955
|
+
console.warn("SessionStorage not available - state not persisted");
|
|
956
|
+
return;
|
|
957
|
+
}
|
|
958
|
+
try {
|
|
959
|
+
const stateWithTimestamp = {
|
|
960
|
+
...state,
|
|
961
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
962
|
+
};
|
|
963
|
+
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(stateWithTimestamp));
|
|
964
|
+
} catch (error) {
|
|
965
|
+
console.error("Failed to save consent state:", error);
|
|
966
|
+
}
|
|
967
|
+
};
|
|
968
|
+
var getConsentState = () => {
|
|
969
|
+
if (!isBrowser()) {
|
|
970
|
+
return null;
|
|
971
|
+
}
|
|
972
|
+
try {
|
|
973
|
+
const savedState = sessionStorage.getItem(STORAGE_KEY);
|
|
974
|
+
if (!savedState) {
|
|
975
|
+
return null;
|
|
976
|
+
}
|
|
977
|
+
const parsed = JSON.parse(savedState);
|
|
978
|
+
const stateAge = Date.now() - new Date(parsed.timestamp).getTime();
|
|
979
|
+
if (stateAge > STATE_EXPIRY_MS) {
|
|
980
|
+
clearConsentState();
|
|
981
|
+
return null;
|
|
982
|
+
}
|
|
983
|
+
return parsed;
|
|
984
|
+
} catch (error) {
|
|
985
|
+
console.error("Failed to get consent state:", error);
|
|
986
|
+
return null;
|
|
987
|
+
}
|
|
988
|
+
};
|
|
989
|
+
var clearConsentState = () => {
|
|
990
|
+
if (!isBrowser()) {
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
try {
|
|
994
|
+
sessionStorage.removeItem(STORAGE_KEY);
|
|
995
|
+
} catch (error) {
|
|
996
|
+
console.error("Failed to clear consent state:", error);
|
|
997
|
+
}
|
|
998
|
+
};
|
|
999
|
+
var updateConsentState = (updates) => {
|
|
1000
|
+
const currentState = getConsentState();
|
|
1001
|
+
if (currentState) {
|
|
1002
|
+
saveConsentState({
|
|
1003
|
+
...currentState,
|
|
1004
|
+
...updates,
|
|
1005
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1006
|
+
});
|
|
1007
|
+
}
|
|
1008
|
+
};
|
|
1009
|
+
|
|
897
1010
|
// src/RedactoNoticeConsent/RedactoNoticeConsent.tsx
|
|
898
1011
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
899
1012
|
var PurposeItem = ({
|
|
@@ -1201,6 +1314,12 @@ var PurposeItem = ({
|
|
|
1201
1314
|
)
|
|
1202
1315
|
] }, purpose.uuid);
|
|
1203
1316
|
};
|
|
1317
|
+
var RELATIONSHIP_OPTIONS = [
|
|
1318
|
+
{ value: "Father", label: "Father" },
|
|
1319
|
+
{ value: "Mother", label: "Mother" },
|
|
1320
|
+
{ value: "Legal Guardian", label: "Legal Guardian" },
|
|
1321
|
+
{ value: "Grandparent", label: "Grandparent" }
|
|
1322
|
+
];
|
|
1204
1323
|
var GuardianForm = ({
|
|
1205
1324
|
formData,
|
|
1206
1325
|
errors,
|
|
@@ -1217,34 +1336,128 @@ var GuardianForm = ({
|
|
|
1217
1336
|
declineButtonStyle,
|
|
1218
1337
|
logoUrl
|
|
1219
1338
|
}) => {
|
|
1339
|
+
var _a, _b, _c, _d, _e;
|
|
1340
|
+
const [isDropdownOpen, setIsDropdownOpen] = useState2(false);
|
|
1341
|
+
const [focusedIndex, setFocusedIndex] = useState2(-1);
|
|
1342
|
+
const [openUpward, setOpenUpward] = useState2(false);
|
|
1343
|
+
const dropdownRef = useRef(null);
|
|
1344
|
+
const optionsRef = useRef(null);
|
|
1345
|
+
useEffect2(() => {
|
|
1346
|
+
if (!isDropdownOpen) return;
|
|
1347
|
+
const handleClickOutside = (e) => {
|
|
1348
|
+
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
1349
|
+
setIsDropdownOpen(false);
|
|
1350
|
+
setFocusedIndex(-1);
|
|
1351
|
+
}
|
|
1352
|
+
};
|
|
1353
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1354
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1355
|
+
}, [isDropdownOpen]);
|
|
1356
|
+
useEffect2(() => {
|
|
1357
|
+
if (!isDropdownOpen || !dropdownRef.current) return;
|
|
1358
|
+
const rect = dropdownRef.current.getBoundingClientRect();
|
|
1359
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
1360
|
+
const dropdownHeight = 220;
|
|
1361
|
+
setOpenUpward(spaceBelow < dropdownHeight && rect.top > dropdownHeight);
|
|
1362
|
+
}, [isDropdownOpen]);
|
|
1363
|
+
const handleSelect = (value) => {
|
|
1364
|
+
onChange("guardianRelationship", value);
|
|
1365
|
+
setIsDropdownOpen(false);
|
|
1366
|
+
setFocusedIndex(-1);
|
|
1367
|
+
};
|
|
1368
|
+
const handleKeyDown = (e) => {
|
|
1369
|
+
if (!isDropdownOpen) {
|
|
1370
|
+
if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
|
|
1371
|
+
e.preventDefault();
|
|
1372
|
+
setIsDropdownOpen(true);
|
|
1373
|
+
setFocusedIndex(0);
|
|
1374
|
+
}
|
|
1375
|
+
return;
|
|
1376
|
+
}
|
|
1377
|
+
switch (e.key) {
|
|
1378
|
+
case "ArrowDown":
|
|
1379
|
+
e.preventDefault();
|
|
1380
|
+
setFocusedIndex((prev) => Math.min(prev + 1, RELATIONSHIP_OPTIONS.length - 1));
|
|
1381
|
+
break;
|
|
1382
|
+
case "ArrowUp":
|
|
1383
|
+
e.preventDefault();
|
|
1384
|
+
setFocusedIndex((prev) => Math.max(prev - 1, 0));
|
|
1385
|
+
break;
|
|
1386
|
+
case "Enter":
|
|
1387
|
+
case " ":
|
|
1388
|
+
e.preventDefault();
|
|
1389
|
+
if (focusedIndex >= 0) handleSelect(RELATIONSHIP_OPTIONS[focusedIndex].value);
|
|
1390
|
+
break;
|
|
1391
|
+
case "Escape":
|
|
1392
|
+
case "Tab":
|
|
1393
|
+
setIsDropdownOpen(false);
|
|
1394
|
+
setFocusedIndex(-1);
|
|
1395
|
+
break;
|
|
1396
|
+
}
|
|
1397
|
+
};
|
|
1398
|
+
useEffect2(() => {
|
|
1399
|
+
var _a2;
|
|
1400
|
+
if (focusedIndex >= 0 && optionsRef.current) {
|
|
1401
|
+
const option = optionsRef.current.children[focusedIndex];
|
|
1402
|
+
(_a2 = option == null ? void 0 : option.scrollIntoView) == null ? void 0 : _a2.call(option, { block: "nearest" });
|
|
1403
|
+
}
|
|
1404
|
+
}, [focusedIndex]);
|
|
1405
|
+
const borderColor = (settings == null ? void 0 : settings.borderColor) || "#d0d5dd";
|
|
1406
|
+
const textColor = (settings == null ? void 0 : settings.textColor) || "#344054";
|
|
1407
|
+
const bgColor = (settings == null ? void 0 : settings.backgroundColor) || "#ffffff";
|
|
1408
|
+
const radius = (settings == null ? void 0 : settings.borderRadius) || "8px";
|
|
1409
|
+
const font = (settings == null ? void 0 : settings.font) || "inherit";
|
|
1220
1410
|
const inputStyle = {
|
|
1221
1411
|
width: "100%",
|
|
1222
1412
|
padding: "10px 12px",
|
|
1223
|
-
border: `1px solid ${
|
|
1224
|
-
borderRadius:
|
|
1413
|
+
border: `1px solid ${borderColor}`,
|
|
1414
|
+
borderRadius: radius,
|
|
1225
1415
|
fontSize: "13px",
|
|
1226
|
-
fontFamily:
|
|
1227
|
-
color:
|
|
1228
|
-
backgroundColor:
|
|
1229
|
-
marginBottom: "
|
|
1230
|
-
boxSizing: "border-box"
|
|
1416
|
+
fontFamily: font,
|
|
1417
|
+
color: textColor,
|
|
1418
|
+
backgroundColor: bgColor,
|
|
1419
|
+
marginBottom: "2px",
|
|
1420
|
+
boxSizing: "border-box",
|
|
1421
|
+
outline: "none"
|
|
1231
1422
|
};
|
|
1232
1423
|
const errorStyle = {
|
|
1233
1424
|
color: "#DC2626",
|
|
1234
|
-
fontSize: "
|
|
1425
|
+
fontSize: "11px",
|
|
1235
1426
|
marginTop: "4px",
|
|
1236
|
-
marginBottom: "
|
|
1427
|
+
marginBottom: "0px"
|
|
1237
1428
|
};
|
|
1238
1429
|
const labelStyle = {
|
|
1239
1430
|
...componentTextStyle,
|
|
1240
1431
|
fontSize: "13px",
|
|
1241
1432
|
fontWeight: "500",
|
|
1242
|
-
marginBottom: "
|
|
1433
|
+
marginBottom: "4px",
|
|
1243
1434
|
display: "block"
|
|
1244
1435
|
};
|
|
1436
|
+
const hintStyle = {
|
|
1437
|
+
fontSize: "11px",
|
|
1438
|
+
color: "#667085",
|
|
1439
|
+
marginTop: "2px",
|
|
1440
|
+
marginBottom: "0px",
|
|
1441
|
+
lineHeight: "1.4"
|
|
1442
|
+
};
|
|
1443
|
+
const infoBannerStyle = {
|
|
1444
|
+
display: "flex",
|
|
1445
|
+
alignItems: "flex-start",
|
|
1446
|
+
gap: "8px",
|
|
1447
|
+
padding: "10px 12px",
|
|
1448
|
+
backgroundColor: "#EFF6FF",
|
|
1449
|
+
border: "1px solid #BFDBFE",
|
|
1450
|
+
borderRadius: radius,
|
|
1451
|
+
marginBottom: "16px",
|
|
1452
|
+
fontSize: "12px",
|
|
1453
|
+
lineHeight: "1.5",
|
|
1454
|
+
color: "#1E40AF"
|
|
1455
|
+
};
|
|
1456
|
+
const selectedLabel = (_a = RELATIONSHIP_OPTIONS.find((o) => o.value === formData.guardianRelationship)) == null ? void 0 : _a.label;
|
|
1457
|
+
const hasError = Boolean(errors.guardianRelationship);
|
|
1245
1458
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1246
1459
|
/* @__PURE__ */ jsx("div", { style: { ...styles3.topSection, ...componentTextStyle }, children: /* @__PURE__ */ jsxs("div", { style: styles3.topLeft, children: [
|
|
1247
|
-
/* @__PURE__ */ jsx("img", { style: styles3.logo, src: logoUrl, alt: "
|
|
1460
|
+
/* @__PURE__ */ jsx("img", { style: styles3.logo, src: logoUrl, alt: "Logo" }),
|
|
1248
1461
|
/* @__PURE__ */ jsx(
|
|
1249
1462
|
"h2",
|
|
1250
1463
|
{
|
|
@@ -1256,7 +1469,7 @@ var GuardianForm = ({
|
|
|
1256
1469
|
fontSize: "16px",
|
|
1257
1470
|
fontWeight: 600
|
|
1258
1471
|
},
|
|
1259
|
-
children: "Guardian
|
|
1472
|
+
children: "Guardian Verification"
|
|
1260
1473
|
}
|
|
1261
1474
|
)
|
|
1262
1475
|
] }) }),
|
|
@@ -1276,31 +1489,49 @@ var GuardianForm = ({
|
|
|
1276
1489
|
...styles3.privacyText,
|
|
1277
1490
|
...responsiveStyles.privacyText,
|
|
1278
1491
|
...componentTextStyle,
|
|
1279
|
-
fontSize: "
|
|
1280
|
-
lineHeight: "1.
|
|
1492
|
+
fontSize: "13px",
|
|
1493
|
+
lineHeight: "1.5",
|
|
1494
|
+
marginBottom: "12px"
|
|
1281
1495
|
},
|
|
1282
|
-
children: "
|
|
1496
|
+
children: "Since you are under the age of consent, a legal guardian must verify their identity via DigiLocker before you can proceed."
|
|
1283
1497
|
}
|
|
1284
1498
|
),
|
|
1499
|
+
/* @__PURE__ */ jsxs("div", { style: infoBannerStyle, children: [
|
|
1500
|
+
/* @__PURE__ */ jsxs(
|
|
1501
|
+
"svg",
|
|
1502
|
+
{
|
|
1503
|
+
width: "16",
|
|
1504
|
+
height: "16",
|
|
1505
|
+
viewBox: "0 0 24 24",
|
|
1506
|
+
fill: "none",
|
|
1507
|
+
stroke: "#2563EB",
|
|
1508
|
+
strokeWidth: "2",
|
|
1509
|
+
strokeLinecap: "round",
|
|
1510
|
+
strokeLinejoin: "round",
|
|
1511
|
+
style: { flexShrink: 0, marginTop: "1px" },
|
|
1512
|
+
children: [
|
|
1513
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
|
|
1514
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
|
|
1515
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "8", x2: "12.01", y2: "8" })
|
|
1516
|
+
]
|
|
1517
|
+
}
|
|
1518
|
+
),
|
|
1519
|
+
/* @__PURE__ */ 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." })
|
|
1520
|
+
] }),
|
|
1285
1521
|
/* @__PURE__ */ jsxs(
|
|
1286
1522
|
"div",
|
|
1287
1523
|
{
|
|
1288
1524
|
style: {
|
|
1289
1525
|
display: "flex",
|
|
1290
1526
|
flexDirection: "column",
|
|
1291
|
-
gap: "
|
|
1292
|
-
marginTop: "16px"
|
|
1527
|
+
gap: "14px"
|
|
1293
1528
|
},
|
|
1294
1529
|
children: [
|
|
1295
1530
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
1296
|
-
/* @__PURE__ */
|
|
1297
|
-
"
|
|
1298
|
-
{
|
|
1299
|
-
|
|
1300
|
-
style: { ...labelStyle, marginBottom: "8px", display: "block" },
|
|
1301
|
-
children: "Name of Guardian *"
|
|
1302
|
-
}
|
|
1303
|
-
),
|
|
1531
|
+
/* @__PURE__ */ jsxs("label", { htmlFor: "guardianName", style: labelStyle, children: [
|
|
1532
|
+
"Guardian's Full Name ",
|
|
1533
|
+
/* @__PURE__ */ jsx("span", { style: { color: "#DC2626" }, children: "*" })
|
|
1534
|
+
] }),
|
|
1304
1535
|
/* @__PURE__ */ jsx(
|
|
1305
1536
|
"input",
|
|
1306
1537
|
{
|
|
@@ -1310,62 +1541,170 @@ var GuardianForm = ({
|
|
|
1310
1541
|
onChange: (e) => onChange("guardianName", e.target.value),
|
|
1311
1542
|
style: {
|
|
1312
1543
|
...inputStyle,
|
|
1313
|
-
borderColor: errors.guardianName ? "#DC2626" :
|
|
1544
|
+
borderColor: errors.guardianName ? "#DC2626" : borderColor
|
|
1314
1545
|
},
|
|
1315
|
-
placeholder: "
|
|
1546
|
+
placeholder: "e.g. Rajesh Kumar",
|
|
1547
|
+
autoComplete: "name",
|
|
1548
|
+
"aria-describedby": "guardianName-hint"
|
|
1316
1549
|
}
|
|
1317
1550
|
),
|
|
1318
|
-
|
|
1551
|
+
/* @__PURE__ */ jsx("p", { id: "guardianName-hint", style: hintStyle, children: "Enter the full name as per government ID (Aadhaar, PAN, etc.)" }),
|
|
1552
|
+
errors.guardianName && /* @__PURE__ */ jsx("div", { style: errorStyle, role: "alert", children: errors.guardianName })
|
|
1319
1553
|
] }),
|
|
1320
1554
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
1321
|
-
/* @__PURE__ */
|
|
1322
|
-
"
|
|
1323
|
-
{
|
|
1324
|
-
|
|
1325
|
-
style: { ...labelStyle, marginBottom: "8px", display: "block" },
|
|
1326
|
-
children: "Contact of Guardian *"
|
|
1327
|
-
}
|
|
1328
|
-
),
|
|
1555
|
+
/* @__PURE__ */ jsxs("label", { htmlFor: "guardianContact", style: labelStyle, children: [
|
|
1556
|
+
"Guardian's Phone Number ",
|
|
1557
|
+
/* @__PURE__ */ jsx("span", { style: { color: "#DC2626" }, children: "*" })
|
|
1558
|
+
] }),
|
|
1329
1559
|
/* @__PURE__ */ jsx(
|
|
1330
1560
|
"input",
|
|
1331
1561
|
{
|
|
1332
1562
|
id: "guardianContact",
|
|
1333
|
-
type: "
|
|
1563
|
+
type: "tel",
|
|
1564
|
+
inputMode: "tel",
|
|
1334
1565
|
value: formData.guardianContact,
|
|
1335
1566
|
onChange: (e) => onChange("guardianContact", e.target.value),
|
|
1336
1567
|
style: {
|
|
1337
1568
|
...inputStyle,
|
|
1338
|
-
borderColor: errors.guardianContact ? "#DC2626" :
|
|
1569
|
+
borderColor: errors.guardianContact ? "#DC2626" : borderColor
|
|
1339
1570
|
},
|
|
1340
|
-
placeholder: "
|
|
1571
|
+
placeholder: "e.g. 9876543210",
|
|
1572
|
+
autoComplete: "tel",
|
|
1573
|
+
"aria-describedby": "guardianContact-hint"
|
|
1341
1574
|
}
|
|
1342
1575
|
),
|
|
1343
|
-
|
|
1576
|
+
/* @__PURE__ */ jsx("p", { id: "guardianContact-hint", style: hintStyle, children: "Mobile number linked to guardian's Aadhaar" }),
|
|
1577
|
+
errors.guardianContact && /* @__PURE__ */ jsx("div", { style: errorStyle, role: "alert", children: errors.guardianContact })
|
|
1344
1578
|
] }),
|
|
1345
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1346
|
-
/* @__PURE__ */
|
|
1347
|
-
"
|
|
1579
|
+
/* @__PURE__ */ jsxs("div", { ref: dropdownRef, style: { position: "relative" }, children: [
|
|
1580
|
+
/* @__PURE__ */ jsxs("label", { id: "guardianRelationship-label", style: labelStyle, children: [
|
|
1581
|
+
"Relationship ",
|
|
1582
|
+
/* @__PURE__ */ jsx("span", { style: { color: "#DC2626" }, children: "*" })
|
|
1583
|
+
] }),
|
|
1584
|
+
/* @__PURE__ */ jsxs(
|
|
1585
|
+
"div",
|
|
1348
1586
|
{
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1587
|
+
role: "combobox",
|
|
1588
|
+
"aria-expanded": isDropdownOpen,
|
|
1589
|
+
"aria-haspopup": "listbox",
|
|
1590
|
+
"aria-labelledby": "guardianRelationship-label",
|
|
1591
|
+
"aria-controls": "guardianRelationship-listbox",
|
|
1592
|
+
"aria-activedescendant": focusedIndex >= 0 ? `guardianRelationship-option-${focusedIndex}` : void 0,
|
|
1593
|
+
tabIndex: 0,
|
|
1594
|
+
onClick: () => {
|
|
1595
|
+
setIsDropdownOpen((prev) => !prev);
|
|
1596
|
+
setFocusedIndex(-1);
|
|
1597
|
+
},
|
|
1598
|
+
onKeyDown: handleKeyDown,
|
|
1599
|
+
style: {
|
|
1600
|
+
...inputStyle,
|
|
1601
|
+
borderColor: hasError ? "#DC2626" : isDropdownOpen ? ((_c = (_b = settings == null ? void 0 : settings.button) == null ? void 0 : _b.accept) == null ? void 0 : _c.backgroundColor) || "#3b82f6" : borderColor,
|
|
1602
|
+
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",
|
|
1603
|
+
color: selectedLabel ? textColor : "#9CA3AF",
|
|
1604
|
+
cursor: "pointer",
|
|
1605
|
+
display: "flex",
|
|
1606
|
+
alignItems: "center",
|
|
1607
|
+
justifyContent: "space-between",
|
|
1608
|
+
userSelect: "none",
|
|
1609
|
+
transition: "border-color 0.15s, box-shadow 0.15s"
|
|
1610
|
+
},
|
|
1611
|
+
children: [
|
|
1612
|
+
/* @__PURE__ */ jsx("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: selectedLabel || "Select relationship" }),
|
|
1613
|
+
/* @__PURE__ */ jsx(
|
|
1614
|
+
"svg",
|
|
1615
|
+
{
|
|
1616
|
+
width: "14",
|
|
1617
|
+
height: "14",
|
|
1618
|
+
viewBox: "0 0 24 24",
|
|
1619
|
+
fill: "none",
|
|
1620
|
+
stroke: "#667085",
|
|
1621
|
+
strokeWidth: "2",
|
|
1622
|
+
strokeLinecap: "round",
|
|
1623
|
+
strokeLinejoin: "round",
|
|
1624
|
+
style: {
|
|
1625
|
+
flexShrink: 0,
|
|
1626
|
+
marginLeft: "8px",
|
|
1627
|
+
transform: isDropdownOpen ? "rotate(180deg)" : "rotate(0deg)",
|
|
1628
|
+
transition: "transform 0.2s"
|
|
1629
|
+
},
|
|
1630
|
+
children: /* @__PURE__ */ jsx("polyline", { points: "6 9 12 15 18 9" })
|
|
1631
|
+
}
|
|
1632
|
+
)
|
|
1633
|
+
]
|
|
1352
1634
|
}
|
|
1353
1635
|
),
|
|
1354
|
-
/* @__PURE__ */ jsx(
|
|
1355
|
-
"
|
|
1636
|
+
isDropdownOpen && /* @__PURE__ */ jsx(
|
|
1637
|
+
"div",
|
|
1356
1638
|
{
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1639
|
+
ref: optionsRef,
|
|
1640
|
+
id: "guardianRelationship-listbox",
|
|
1641
|
+
role: "listbox",
|
|
1642
|
+
"aria-labelledby": "guardianRelationship-label",
|
|
1361
1643
|
style: {
|
|
1362
|
-
|
|
1363
|
-
|
|
1644
|
+
position: "absolute",
|
|
1645
|
+
...openUpward ? { bottom: "calc(100% + 4px)" } : { top: "calc(100% + 4px)" },
|
|
1646
|
+
left: 0,
|
|
1647
|
+
right: 0,
|
|
1648
|
+
backgroundColor: bgColor,
|
|
1649
|
+
border: `1px solid ${borderColor}`,
|
|
1650
|
+
borderRadius: radius,
|
|
1651
|
+
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)",
|
|
1652
|
+
zIndex: 50,
|
|
1653
|
+
overflow: "hidden",
|
|
1654
|
+
padding: "4px 0",
|
|
1655
|
+
maxHeight: "220px",
|
|
1656
|
+
overflowY: "auto"
|
|
1364
1657
|
},
|
|
1365
|
-
|
|
1658
|
+
children: RELATIONSHIP_OPTIONS.map((option, index) => {
|
|
1659
|
+
var _a2, _b2;
|
|
1660
|
+
const isSelected = formData.guardianRelationship === option.value;
|
|
1661
|
+
const isFocused = focusedIndex === index;
|
|
1662
|
+
const accentColor = ((_b2 = (_a2 = settings == null ? void 0 : settings.button) == null ? void 0 : _a2.accept) == null ? void 0 : _b2.backgroundColor) || "#3b82f6";
|
|
1663
|
+
return /* @__PURE__ */ jsxs(
|
|
1664
|
+
"div",
|
|
1665
|
+
{
|
|
1666
|
+
id: `guardianRelationship-option-${index}`,
|
|
1667
|
+
role: "option",
|
|
1668
|
+
"aria-selected": isSelected,
|
|
1669
|
+
onClick: () => handleSelect(option.value),
|
|
1670
|
+
onMouseEnter: () => setFocusedIndex(index),
|
|
1671
|
+
style: {
|
|
1672
|
+
padding: "9px 12px",
|
|
1673
|
+
fontSize: "13px",
|
|
1674
|
+
fontFamily: font,
|
|
1675
|
+
color: isSelected ? accentColor : textColor,
|
|
1676
|
+
backgroundColor: isFocused ? "#F3F4F6" : "transparent",
|
|
1677
|
+
cursor: "pointer",
|
|
1678
|
+
display: "flex",
|
|
1679
|
+
alignItems: "center",
|
|
1680
|
+
justifyContent: "space-between",
|
|
1681
|
+
transition: "background-color 0.1s"
|
|
1682
|
+
},
|
|
1683
|
+
children: [
|
|
1684
|
+
/* @__PURE__ */ jsx("span", { children: option.label }),
|
|
1685
|
+
isSelected && /* @__PURE__ */ jsx(
|
|
1686
|
+
"svg",
|
|
1687
|
+
{
|
|
1688
|
+
width: "14",
|
|
1689
|
+
height: "14",
|
|
1690
|
+
viewBox: "0 0 24 24",
|
|
1691
|
+
fill: "none",
|
|
1692
|
+
stroke: accentColor,
|
|
1693
|
+
strokeWidth: "2.5",
|
|
1694
|
+
strokeLinecap: "round",
|
|
1695
|
+
strokeLinejoin: "round",
|
|
1696
|
+
style: { flexShrink: 0 },
|
|
1697
|
+
children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" })
|
|
1698
|
+
}
|
|
1699
|
+
)
|
|
1700
|
+
]
|
|
1701
|
+
},
|
|
1702
|
+
option.value
|
|
1703
|
+
);
|
|
1704
|
+
})
|
|
1366
1705
|
}
|
|
1367
1706
|
),
|
|
1368
|
-
errors.guardianRelationship && /* @__PURE__ */ jsx("div", { style: errorStyle, children: errors.guardianRelationship })
|
|
1707
|
+
errors.guardianRelationship && /* @__PURE__ */ jsx("div", { style: errorStyle, role: "alert", children: errors.guardianRelationship })
|
|
1369
1708
|
] })
|
|
1370
1709
|
]
|
|
1371
1710
|
}
|
|
@@ -1376,7 +1715,7 @@ var GuardianForm = ({
|
|
|
1376
1715
|
role: "alert",
|
|
1377
1716
|
style: {
|
|
1378
1717
|
color: "#DC2626",
|
|
1379
|
-
fontSize: "
|
|
1718
|
+
fontSize: "13px",
|
|
1380
1719
|
marginTop: "16px",
|
|
1381
1720
|
padding: "12px",
|
|
1382
1721
|
borderRadius: "6px",
|
|
@@ -1412,8 +1751,8 @@ var GuardianForm = ({
|
|
|
1412
1751
|
onClick: onNext,
|
|
1413
1752
|
disabled: isSubmitting,
|
|
1414
1753
|
type: "button",
|
|
1415
|
-
"aria-label": isSubmitting ? "
|
|
1416
|
-
children: isSubmitting ? "
|
|
1754
|
+
"aria-label": isSubmitting ? "Verifying guardian identity" : "Proceed to guardian verification",
|
|
1755
|
+
children: isSubmitting ? "Verifying..." : "Verify via DigiLocker"
|
|
1417
1756
|
}
|
|
1418
1757
|
),
|
|
1419
1758
|
/* @__PURE__ */ jsx(
|
|
@@ -1427,7 +1766,7 @@ var GuardianForm = ({
|
|
|
1427
1766
|
},
|
|
1428
1767
|
onClick: onDecline,
|
|
1429
1768
|
type: "button",
|
|
1430
|
-
"aria-label": "Cancel
|
|
1769
|
+
"aria-label": "Cancel",
|
|
1431
1770
|
children: "Cancel"
|
|
1432
1771
|
}
|
|
1433
1772
|
)
|
|
@@ -1436,6 +1775,266 @@ var GuardianForm = ({
|
|
|
1436
1775
|
)
|
|
1437
1776
|
] });
|
|
1438
1777
|
};
|
|
1778
|
+
var VerificationScreen = ({
|
|
1779
|
+
onBack,
|
|
1780
|
+
onContinue,
|
|
1781
|
+
isInitiating,
|
|
1782
|
+
isPolling,
|
|
1783
|
+
isVerificationComplete,
|
|
1784
|
+
isAutoTransitioning,
|
|
1785
|
+
error,
|
|
1786
|
+
errorCode,
|
|
1787
|
+
canRetry,
|
|
1788
|
+
styles: styles3,
|
|
1789
|
+
responsiveStyles,
|
|
1790
|
+
settings,
|
|
1791
|
+
componentHeadingStyle,
|
|
1792
|
+
componentTextStyle,
|
|
1793
|
+
acceptButtonStyle,
|
|
1794
|
+
declineButtonStyle,
|
|
1795
|
+
logoUrl
|
|
1796
|
+
}) => {
|
|
1797
|
+
var _a, _b;
|
|
1798
|
+
const errorStyle = {
|
|
1799
|
+
color: "#DC2626",
|
|
1800
|
+
fontSize: "14px",
|
|
1801
|
+
marginTop: "16px",
|
|
1802
|
+
padding: "12px",
|
|
1803
|
+
borderRadius: "6px",
|
|
1804
|
+
border: "1px solid #FCA5A5",
|
|
1805
|
+
backgroundColor: "#FEF2F2",
|
|
1806
|
+
textAlign: "center"
|
|
1807
|
+
};
|
|
1808
|
+
const statusStyle = {
|
|
1809
|
+
color: "#059669",
|
|
1810
|
+
fontSize: "14px",
|
|
1811
|
+
marginTop: "16px",
|
|
1812
|
+
padding: "12px",
|
|
1813
|
+
borderRadius: "6px",
|
|
1814
|
+
border: "1px solid #A7F3D0",
|
|
1815
|
+
backgroundColor: "#D1FAE5",
|
|
1816
|
+
textAlign: "center"
|
|
1817
|
+
};
|
|
1818
|
+
const spinnerStyle = {
|
|
1819
|
+
width: "48px",
|
|
1820
|
+
height: "48px",
|
|
1821
|
+
border: "4px solid #e5e7eb",
|
|
1822
|
+
borderTopColor: ((_b = (_a = settings == null ? void 0 : settings.button) == null ? void 0 : _a.accept) == null ? void 0 : _b.backgroundColor) || "#3b82f6",
|
|
1823
|
+
borderRadius: "50%",
|
|
1824
|
+
animation: "spin 1s linear infinite",
|
|
1825
|
+
margin: "24px auto"
|
|
1826
|
+
};
|
|
1827
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1828
|
+
/* @__PURE__ */ jsx("div", { style: { ...styles3.topSection, ...componentTextStyle }, children: /* @__PURE__ */ jsxs("div", { style: styles3.topLeft, children: [
|
|
1829
|
+
/* @__PURE__ */ jsx("img", { style: styles3.logo, src: logoUrl, alt: "Logo" }),
|
|
1830
|
+
/* @__PURE__ */ jsx(
|
|
1831
|
+
"h2",
|
|
1832
|
+
{
|
|
1833
|
+
id: "verification-title",
|
|
1834
|
+
style: {
|
|
1835
|
+
...styles3.title,
|
|
1836
|
+
...responsiveStyles.title,
|
|
1837
|
+
...componentHeadingStyle,
|
|
1838
|
+
fontSize: "16px",
|
|
1839
|
+
fontWeight: 600
|
|
1840
|
+
},
|
|
1841
|
+
children: "Guardian Verification"
|
|
1842
|
+
}
|
|
1843
|
+
)
|
|
1844
|
+
] }) }),
|
|
1845
|
+
/* @__PURE__ */ jsxs(
|
|
1846
|
+
"div",
|
|
1847
|
+
{
|
|
1848
|
+
style: {
|
|
1849
|
+
...styles3.middleSection,
|
|
1850
|
+
...responsiveStyles.middleSection,
|
|
1851
|
+
...componentTextStyle,
|
|
1852
|
+
textAlign: "center"
|
|
1853
|
+
},
|
|
1854
|
+
children: [
|
|
1855
|
+
isVerificationComplete && !error ? /* @__PURE__ */ jsxs(
|
|
1856
|
+
"div",
|
|
1857
|
+
{
|
|
1858
|
+
style: {
|
|
1859
|
+
display: "flex",
|
|
1860
|
+
flexDirection: "column",
|
|
1861
|
+
alignItems: "center",
|
|
1862
|
+
justifyContent: "center",
|
|
1863
|
+
flex: 1
|
|
1864
|
+
},
|
|
1865
|
+
children: [
|
|
1866
|
+
/* @__PURE__ */ jsx(
|
|
1867
|
+
"div",
|
|
1868
|
+
{
|
|
1869
|
+
style: {
|
|
1870
|
+
width: "64px",
|
|
1871
|
+
height: "64px",
|
|
1872
|
+
borderRadius: "50%",
|
|
1873
|
+
backgroundColor: "#D1FAE5",
|
|
1874
|
+
display: "flex",
|
|
1875
|
+
alignItems: "center",
|
|
1876
|
+
justifyContent: "center"
|
|
1877
|
+
},
|
|
1878
|
+
children: /* @__PURE__ */ jsx(
|
|
1879
|
+
"svg",
|
|
1880
|
+
{
|
|
1881
|
+
width: "32",
|
|
1882
|
+
height: "32",
|
|
1883
|
+
viewBox: "0 0 24 24",
|
|
1884
|
+
fill: "none",
|
|
1885
|
+
stroke: "#059669",
|
|
1886
|
+
strokeWidth: "2",
|
|
1887
|
+
strokeLinecap: "round",
|
|
1888
|
+
strokeLinejoin: "round",
|
|
1889
|
+
children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" })
|
|
1890
|
+
}
|
|
1891
|
+
)
|
|
1892
|
+
}
|
|
1893
|
+
),
|
|
1894
|
+
/* @__PURE__ */ jsx(
|
|
1895
|
+
"p",
|
|
1896
|
+
{
|
|
1897
|
+
style: {
|
|
1898
|
+
...componentHeadingStyle,
|
|
1899
|
+
fontSize: "16px",
|
|
1900
|
+
fontWeight: 600,
|
|
1901
|
+
lineHeight: "1.5",
|
|
1902
|
+
marginTop: "12px",
|
|
1903
|
+
marginBottom: "24px"
|
|
1904
|
+
},
|
|
1905
|
+
children: "Verification Completed"
|
|
1906
|
+
}
|
|
1907
|
+
)
|
|
1908
|
+
]
|
|
1909
|
+
}
|
|
1910
|
+
) : (isInitiating || isPolling) && !error ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1911
|
+
/* @__PURE__ */ jsx("div", { style: spinnerStyle }),
|
|
1912
|
+
/* @__PURE__ */ 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." })
|
|
1913
|
+
] }) : null,
|
|
1914
|
+
error && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1915
|
+
/* @__PURE__ */ jsx(
|
|
1916
|
+
"div",
|
|
1917
|
+
{
|
|
1918
|
+
style: {
|
|
1919
|
+
width: "64px",
|
|
1920
|
+
height: "64px",
|
|
1921
|
+
borderRadius: "50%",
|
|
1922
|
+
backgroundColor: "#fee2e2",
|
|
1923
|
+
display: "flex",
|
|
1924
|
+
alignItems: "center",
|
|
1925
|
+
justifyContent: "center",
|
|
1926
|
+
margin: "24px auto"
|
|
1927
|
+
},
|
|
1928
|
+
children: /* @__PURE__ */ jsxs(
|
|
1929
|
+
"svg",
|
|
1930
|
+
{
|
|
1931
|
+
width: "32",
|
|
1932
|
+
height: "32",
|
|
1933
|
+
viewBox: "0 0 24 24",
|
|
1934
|
+
fill: "none",
|
|
1935
|
+
stroke: "#dc2626",
|
|
1936
|
+
strokeWidth: "2",
|
|
1937
|
+
strokeLinecap: "round",
|
|
1938
|
+
strokeLinejoin: "round",
|
|
1939
|
+
children: [
|
|
1940
|
+
/* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
1941
|
+
/* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
1942
|
+
]
|
|
1943
|
+
}
|
|
1944
|
+
)
|
|
1945
|
+
}
|
|
1946
|
+
),
|
|
1947
|
+
/* @__PURE__ */ jsx(
|
|
1948
|
+
"p",
|
|
1949
|
+
{
|
|
1950
|
+
style: {
|
|
1951
|
+
...styles3.privacyText,
|
|
1952
|
+
...responsiveStyles.privacyText,
|
|
1953
|
+
...componentTextStyle,
|
|
1954
|
+
fontSize: "14px",
|
|
1955
|
+
lineHeight: "1.5",
|
|
1956
|
+
marginBottom: "12px"
|
|
1957
|
+
},
|
|
1958
|
+
children: "Verification failed"
|
|
1959
|
+
}
|
|
1960
|
+
),
|
|
1961
|
+
/* @__PURE__ */ jsx("div", { style: errorStyle, children: error })
|
|
1962
|
+
] })
|
|
1963
|
+
]
|
|
1964
|
+
}
|
|
1965
|
+
),
|
|
1966
|
+
isAutoTransitioning ? null : /* @__PURE__ */ jsx(
|
|
1967
|
+
"div",
|
|
1968
|
+
{
|
|
1969
|
+
style: {
|
|
1970
|
+
...styles3.bottomSection,
|
|
1971
|
+
...responsiveStyles.bottomSection,
|
|
1972
|
+
...componentTextStyle,
|
|
1973
|
+
paddingTop: "12px",
|
|
1974
|
+
display: "flex",
|
|
1975
|
+
gap: "12px",
|
|
1976
|
+
justifyContent: "center"
|
|
1977
|
+
},
|
|
1978
|
+
children: isVerificationComplete && !error ? /* @__PURE__ */ jsx(
|
|
1979
|
+
"button",
|
|
1980
|
+
{
|
|
1981
|
+
style: {
|
|
1982
|
+
...styles3.button,
|
|
1983
|
+
...responsiveStyles.button,
|
|
1984
|
+
...acceptButtonStyle
|
|
1985
|
+
},
|
|
1986
|
+
onClick: onContinue,
|
|
1987
|
+
type: "button",
|
|
1988
|
+
"aria-label": "Continue to consent form",
|
|
1989
|
+
children: "Continue"
|
|
1990
|
+
}
|
|
1991
|
+
) : error && canRetry ? /* @__PURE__ */ jsx(
|
|
1992
|
+
"button",
|
|
1993
|
+
{
|
|
1994
|
+
style: {
|
|
1995
|
+
...styles3.button,
|
|
1996
|
+
...responsiveStyles.button,
|
|
1997
|
+
...styles3.acceptButton,
|
|
1998
|
+
...acceptButtonStyle
|
|
1999
|
+
},
|
|
2000
|
+
onClick: () => onBack(errorCode === "GUARDIAN_UNDER_18"),
|
|
2001
|
+
type: "button",
|
|
2002
|
+
"aria-label": errorCode === "GUARDIAN_UNDER_18" ? "Change guardian details" : "Try verification again",
|
|
2003
|
+
children: errorCode === "GUARDIAN_UNDER_18" ? "Change Guardian" : "Try Again"
|
|
2004
|
+
}
|
|
2005
|
+
) : error ? /* @__PURE__ */ jsx(
|
|
2006
|
+
"button",
|
|
2007
|
+
{
|
|
2008
|
+
style: {
|
|
2009
|
+
...styles3.button,
|
|
2010
|
+
...responsiveStyles.button,
|
|
2011
|
+
...styles3.cancelButton,
|
|
2012
|
+
...declineButtonStyle
|
|
2013
|
+
},
|
|
2014
|
+
onClick: () => onBack(false),
|
|
2015
|
+
type: "button",
|
|
2016
|
+
"aria-label": "Go back",
|
|
2017
|
+
children: "Go Back"
|
|
2018
|
+
}
|
|
2019
|
+
) : /* @__PURE__ */ jsx(
|
|
2020
|
+
"button",
|
|
2021
|
+
{
|
|
2022
|
+
style: {
|
|
2023
|
+
...styles3.button,
|
|
2024
|
+
...responsiveStyles.button,
|
|
2025
|
+
...styles3.cancelButton,
|
|
2026
|
+
...declineButtonStyle
|
|
2027
|
+
},
|
|
2028
|
+
onClick: () => onBack(false),
|
|
2029
|
+
type: "button",
|
|
2030
|
+
"aria-label": "Cancel verification",
|
|
2031
|
+
children: "Cancel"
|
|
2032
|
+
}
|
|
2033
|
+
)
|
|
2034
|
+
}
|
|
2035
|
+
)
|
|
2036
|
+
] });
|
|
2037
|
+
};
|
|
1439
2038
|
var AgeVerification = ({
|
|
1440
2039
|
onYes,
|
|
1441
2040
|
onNo,
|
|
@@ -1598,6 +2197,10 @@ var RedactoNoticeConsent = ({
|
|
|
1598
2197
|
settings,
|
|
1599
2198
|
applicationId,
|
|
1600
2199
|
validateAgainst = "all",
|
|
2200
|
+
digilockerMode = "redirect",
|
|
2201
|
+
// Default to full page redirect (DigiLocker blocks iframe embedding)
|
|
2202
|
+
digilockerCallbackUrl = "/digilocker-callback",
|
|
2203
|
+
// Default callback path
|
|
1601
2204
|
includeFullyConsentedData = false,
|
|
1602
2205
|
reviewModeButtonText = "Continue"
|
|
1603
2206
|
}) => {
|
|
@@ -1653,6 +2256,8 @@ var RedactoNoticeConsent = ({
|
|
|
1653
2256
|
const [currentAudioIndex, setCurrentAudioIndex] = useState2(0);
|
|
1654
2257
|
const [highlightedElementId, setHighlightedElementId] = useState2(null);
|
|
1655
2258
|
const [showAgeVerification, setShowAgeVerification] = useState2(false);
|
|
2259
|
+
const [isMinorFlow, setIsMinorFlow] = useState2(false);
|
|
2260
|
+
const [selfDeclaredAdult, setSelfDeclaredAdult] = useState2(false);
|
|
1656
2261
|
const [showGuardianForm, setShowGuardianForm] = useState2(false);
|
|
1657
2262
|
const [isSubmittingGuardian, setIsSubmittingGuardian] = useState2(false);
|
|
1658
2263
|
const [guardianFormData, setGuardianFormData] = useState2({
|
|
@@ -1661,12 +2266,32 @@ var RedactoNoticeConsent = ({
|
|
|
1661
2266
|
guardianRelationship: ""
|
|
1662
2267
|
});
|
|
1663
2268
|
const [guardianFormErrors, setGuardianFormErrors] = useState2({});
|
|
2269
|
+
const [showVerificationScreen, setShowVerificationScreen] = useState2(false);
|
|
2270
|
+
const [verificationReference, setVerificationReference] = useState2(null);
|
|
2271
|
+
const [isInitiatingVerification, setIsInitiatingVerification] = useState2(false);
|
|
2272
|
+
const [verificationError, setVerificationError] = useState2(
|
|
2273
|
+
null
|
|
2274
|
+
);
|
|
2275
|
+
const [verificationErrorCode, setVerificationErrorCode] = useState2(null);
|
|
2276
|
+
const [canRetryVerification, setCanRetryVerification] = useState2(false);
|
|
2277
|
+
const [isPollingStatus, setIsPollingStatus] = useState2(false);
|
|
2278
|
+
const [isVerificationComplete, setIsVerificationComplete] = useState2(false);
|
|
2279
|
+
const [isAutoTransitioning, setIsAutoTransitioning] = useState2(false);
|
|
1664
2280
|
const modalRef = useRef(null);
|
|
1665
2281
|
const firstFocusableRef = useRef(null);
|
|
1666
2282
|
const lastFocusableRef = useRef(null);
|
|
1667
2283
|
const abortControllerRef = useRef(null);
|
|
1668
2284
|
const isRequestInProgressRef = useRef(false);
|
|
1669
2285
|
const currentAudioRef = useRef(null);
|
|
2286
|
+
const popupCheckIntervalRef = useRef(null);
|
|
2287
|
+
const statusPollIntervalRef = useRef(null);
|
|
2288
|
+
const verificationPopupRef = useRef(null);
|
|
2289
|
+
const pollingCleanupRef = useRef(null);
|
|
2290
|
+
const autoTransitionTimerRef = useRef(null);
|
|
2291
|
+
const digilockerRedirectTimeoutRef = useRef(null);
|
|
2292
|
+
const isInitialMountRef = useRef(true);
|
|
2293
|
+
const isPollingStatusRef = useRef(false);
|
|
2294
|
+
const verificationSessionTokenRef = useRef(null);
|
|
1670
2295
|
const isMobile = useMediaQuery("(max-width: 768px)");
|
|
1671
2296
|
const responsiveStyles = useMemo(
|
|
1672
2297
|
() => ({
|
|
@@ -1774,6 +2399,7 @@ var RedactoNoticeConsent = ({
|
|
|
1774
2399
|
}, [content, selectedDataElements]);
|
|
1775
2400
|
const acceptDisabled = isSubmitting || !areAllRequiredElementsChecked;
|
|
1776
2401
|
useEffect2(() => {
|
|
2402
|
+
var _a2, _b2;
|
|
1777
2403
|
clearApiCache();
|
|
1778
2404
|
isRequestInProgressRef.current = false;
|
|
1779
2405
|
setContent(null);
|
|
@@ -1789,6 +2415,8 @@ var RedactoNoticeConsent = ({
|
|
|
1789
2415
|
setIsSubmittingAccept(false);
|
|
1790
2416
|
setIsSubmittingDecline(false);
|
|
1791
2417
|
setShowAgeVerification(false);
|
|
2418
|
+
setIsMinorFlow(false);
|
|
2419
|
+
setSelfDeclaredAdult(false);
|
|
1792
2420
|
setShowGuardianForm(false);
|
|
1793
2421
|
setIsSubmittingGuardian(false);
|
|
1794
2422
|
setGuardianFormData({
|
|
@@ -1797,6 +2425,41 @@ var RedactoNoticeConsent = ({
|
|
|
1797
2425
|
guardianRelationship: ""
|
|
1798
2426
|
});
|
|
1799
2427
|
setGuardianFormErrors({});
|
|
2428
|
+
setShowVerificationScreen(false);
|
|
2429
|
+
setVerificationReference(null);
|
|
2430
|
+
setIsInitiatingVerification(false);
|
|
2431
|
+
setVerificationError(null);
|
|
2432
|
+
setVerificationErrorCode(null);
|
|
2433
|
+
setCanRetryVerification(false);
|
|
2434
|
+
setIsVerificationComplete(false);
|
|
2435
|
+
setIsAutoTransitioning(false);
|
|
2436
|
+
setIsPollingStatus(false);
|
|
2437
|
+
isPollingStatusRef.current = false;
|
|
2438
|
+
verificationSessionTokenRef.current = null;
|
|
2439
|
+
if (popupCheckIntervalRef.current) {
|
|
2440
|
+
clearInterval(popupCheckIntervalRef.current);
|
|
2441
|
+
popupCheckIntervalRef.current = null;
|
|
2442
|
+
}
|
|
2443
|
+
if (statusPollIntervalRef.current) {
|
|
2444
|
+
clearTimeout(statusPollIntervalRef.current);
|
|
2445
|
+
statusPollIntervalRef.current = null;
|
|
2446
|
+
}
|
|
2447
|
+
(_a2 = pollingCleanupRef.current) == null ? void 0 : _a2.call(pollingCleanupRef);
|
|
2448
|
+
pollingCleanupRef.current = null;
|
|
2449
|
+
(_b2 = verificationPopupRef.current) == null ? void 0 : _b2.close();
|
|
2450
|
+
verificationPopupRef.current = null;
|
|
2451
|
+
if (autoTransitionTimerRef.current) {
|
|
2452
|
+
clearTimeout(autoTransitionTimerRef.current);
|
|
2453
|
+
autoTransitionTimerRef.current = null;
|
|
2454
|
+
}
|
|
2455
|
+
if (digilockerRedirectTimeoutRef.current) {
|
|
2456
|
+
clearTimeout(digilockerRedirectTimeoutRef.current);
|
|
2457
|
+
digilockerRedirectTimeoutRef.current = null;
|
|
2458
|
+
}
|
|
2459
|
+
if (!isInitialMountRef.current) {
|
|
2460
|
+
clearConsentState();
|
|
2461
|
+
}
|
|
2462
|
+
isInitialMountRef.current = false;
|
|
1800
2463
|
}, [accessToken]);
|
|
1801
2464
|
useEffect2(() => {
|
|
1802
2465
|
if (hasAlreadyConsented) {
|
|
@@ -2005,7 +2668,11 @@ var RedactoNoticeConsent = ({
|
|
|
2005
2668
|
setInitialDataElementSelections({});
|
|
2006
2669
|
}
|
|
2007
2670
|
if (consentContentData.detail.is_minor) {
|
|
2008
|
-
|
|
2671
|
+
setIsMinorFlow(true);
|
|
2672
|
+
const persistedState = getConsentState();
|
|
2673
|
+
if (!(persistedState == null ? void 0 : persistedState.sessionToken) && !(persistedState == null ? void 0 : persistedState.verificationReference)) {
|
|
2674
|
+
setShowAgeVerification(true);
|
|
2675
|
+
}
|
|
2009
2676
|
}
|
|
2010
2677
|
setIsLoading(false);
|
|
2011
2678
|
} catch (err) {
|
|
@@ -2104,6 +2771,10 @@ var RedactoNoticeConsent = ({
|
|
|
2104
2771
|
const handleAccept = async () => {
|
|
2105
2772
|
const submitController = new AbortController();
|
|
2106
2773
|
try {
|
|
2774
|
+
if (isMinorFlow && !verificationReference) {
|
|
2775
|
+
setErrorMessage("Guardian verification is required before consent can be submitted.");
|
|
2776
|
+
return;
|
|
2777
|
+
}
|
|
2107
2778
|
setIsSubmittingAccept(true);
|
|
2108
2779
|
setIsSubmitting(true);
|
|
2109
2780
|
setErrorMessage(null);
|
|
@@ -2139,6 +2810,8 @@ var RedactoNoticeConsent = ({
|
|
|
2139
2810
|
}),
|
|
2140
2811
|
declined: false,
|
|
2141
2812
|
meta_data: applicationId ? { specific_uuid: applicationId } : void 0,
|
|
2813
|
+
guardianVerificationReference: verificationReference || void 0,
|
|
2814
|
+
selfDeclaredAdult: selfDeclaredAdult || void 0,
|
|
2142
2815
|
signal: submitController.signal
|
|
2143
2816
|
});
|
|
2144
2817
|
}
|
|
@@ -2203,17 +2876,102 @@ var RedactoNoticeConsent = ({
|
|
|
2203
2876
|
try {
|
|
2204
2877
|
setIsSubmittingGuardian(true);
|
|
2205
2878
|
setGuardianFormErrors({});
|
|
2206
|
-
|
|
2879
|
+
setVerificationError(null);
|
|
2880
|
+
const callbackUrl = digilockerMode === "popup" ? new URL(digilockerCallbackUrl, window.location.origin).href : void 0;
|
|
2881
|
+
const response = await initiateGuardianVerification({
|
|
2207
2882
|
accessToken,
|
|
2208
2883
|
baseUrl,
|
|
2209
2884
|
guardianName: guardianFormData.guardianName,
|
|
2210
2885
|
guardianContact: guardianFormData.guardianContact,
|
|
2211
2886
|
guardianRelationship: guardianFormData.guardianRelationship,
|
|
2887
|
+
frontendCallbackUrl: callbackUrl,
|
|
2888
|
+
// Only for popup mode
|
|
2212
2889
|
signal: guardianController.signal
|
|
2213
2890
|
});
|
|
2891
|
+
setIsSubmittingGuardian(false);
|
|
2892
|
+
if (response.already_verified && response.verification_reference) {
|
|
2893
|
+
setVerificationReference(response.verification_reference);
|
|
2894
|
+
setShowGuardianForm(false);
|
|
2895
|
+
setShowVerificationScreen(true);
|
|
2896
|
+
setIsInitiatingVerification(false);
|
|
2897
|
+
setIsVerificationComplete(true);
|
|
2898
|
+
setIsAutoTransitioning(true);
|
|
2899
|
+
autoTransitionTimerRef.current = setTimeout(() => {
|
|
2900
|
+
setShowVerificationScreen(false);
|
|
2901
|
+
setIsVerificationComplete(false);
|
|
2902
|
+
setIsAutoTransitioning(false);
|
|
2903
|
+
autoTransitionTimerRef.current = null;
|
|
2904
|
+
}, 1e3);
|
|
2905
|
+
return;
|
|
2906
|
+
}
|
|
2907
|
+
if (!response.session_token || !response.digilocker_redirect_url) {
|
|
2908
|
+
throw new Error("Invalid response from server: missing required fields");
|
|
2909
|
+
}
|
|
2214
2910
|
setShowGuardianForm(false);
|
|
2911
|
+
setShowVerificationScreen(true);
|
|
2912
|
+
setIsInitiatingVerification(true);
|
|
2913
|
+
if (digilockerMode === "redirect") {
|
|
2914
|
+
saveConsentState({
|
|
2915
|
+
flowState: "digilocker-pending",
|
|
2916
|
+
sessionToken: response.session_token,
|
|
2917
|
+
guardianInfoUuid: response.guardian_info_uuid,
|
|
2918
|
+
selectedPurposes,
|
|
2919
|
+
selectedDataElements,
|
|
2920
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2921
|
+
originalUrl: window.location.href,
|
|
2922
|
+
noticeId,
|
|
2923
|
+
baseUrl
|
|
2924
|
+
});
|
|
2925
|
+
try {
|
|
2926
|
+
const openedWindow = window.open(
|
|
2927
|
+
response.digilocker_redirect_url,
|
|
2928
|
+
"_blank"
|
|
2929
|
+
);
|
|
2930
|
+
if (!openedWindow) {
|
|
2931
|
+
console.warn("Popup blocked \u2014 cannot open DigiLocker in new tab");
|
|
2932
|
+
setIsInitiatingVerification(false);
|
|
2933
|
+
setVerificationError(
|
|
2934
|
+
"Unable to open DigiLocker in a new tab. Please allow popups for this site and try again."
|
|
2935
|
+
);
|
|
2936
|
+
return;
|
|
2937
|
+
}
|
|
2938
|
+
try {
|
|
2939
|
+
openedWindow.opener = null;
|
|
2940
|
+
} catch {
|
|
2941
|
+
}
|
|
2942
|
+
} catch (error) {
|
|
2943
|
+
console.error("Failed to open DigiLocker in new tab:", error);
|
|
2944
|
+
setIsInitiatingVerification(false);
|
|
2945
|
+
setVerificationError(
|
|
2946
|
+
"Unable to open DigiLocker. Please allow popups for this site and try again."
|
|
2947
|
+
);
|
|
2948
|
+
return;
|
|
2949
|
+
}
|
|
2950
|
+
setIsInitiatingVerification(false);
|
|
2951
|
+
setIsPollingStatus(true);
|
|
2952
|
+
isPollingStatusRef.current = true;
|
|
2953
|
+
startStatusPolling(response.session_token);
|
|
2954
|
+
} else {
|
|
2955
|
+
setIsInitiatingVerification(true);
|
|
2956
|
+
const popup = window.open(
|
|
2957
|
+
response.digilocker_redirect_url,
|
|
2958
|
+
"digilocker_verification",
|
|
2959
|
+
"width=600,height=700,scrollbars=yes,resizable=yes"
|
|
2960
|
+
);
|
|
2961
|
+
if (popup) {
|
|
2962
|
+
verificationPopupRef.current = popup;
|
|
2963
|
+
startPopupMonitoring(popup);
|
|
2964
|
+
startStatusPolling(response.session_token);
|
|
2965
|
+
} else {
|
|
2966
|
+
setIsInitiatingVerification(false);
|
|
2967
|
+
setVerificationError(
|
|
2968
|
+
"Popup blocked. Please allow popups for this site or use redirect mode."
|
|
2969
|
+
);
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2215
2972
|
} catch (error) {
|
|
2216
2973
|
const err = error;
|
|
2974
|
+
setIsInitiatingVerification(false);
|
|
2217
2975
|
if (err.status === 422) {
|
|
2218
2976
|
if (err.message.includes("guardian_contact")) {
|
|
2219
2977
|
setGuardianFormErrors({ guardianContact: err.message });
|
|
@@ -2224,23 +2982,265 @@ var RedactoNoticeConsent = ({
|
|
|
2224
2982
|
} else {
|
|
2225
2983
|
setGuardianFormErrors({ general: err.message });
|
|
2226
2984
|
}
|
|
2985
|
+
setShowVerificationScreen(false);
|
|
2986
|
+
setShowGuardianForm(true);
|
|
2227
2987
|
} else {
|
|
2228
2988
|
setGuardianFormErrors({
|
|
2229
|
-
general: err.message || "Failed to
|
|
2989
|
+
general: err.message || "Failed to initiate verification. Please try again."
|
|
2230
2990
|
});
|
|
2991
|
+
setShowVerificationScreen(false);
|
|
2992
|
+
setShowGuardianForm(true);
|
|
2231
2993
|
onError == null ? void 0 : onError(err);
|
|
2232
2994
|
}
|
|
2233
2995
|
} finally {
|
|
2234
2996
|
setIsSubmittingGuardian(false);
|
|
2235
2997
|
}
|
|
2236
|
-
}, [accessToken, baseUrl, guardianFormData, onError]);
|
|
2998
|
+
}, [accessToken, baseUrl, guardianFormData, digilockerMode, digilockerCallbackUrl, selectedPurposes, selectedDataElements, noticeId, onError]);
|
|
2237
2999
|
const handleAgeVerificationYes = useCallback(() => {
|
|
2238
3000
|
setShowAgeVerification(false);
|
|
3001
|
+
setIsMinorFlow(false);
|
|
3002
|
+
setSelfDeclaredAdult(true);
|
|
2239
3003
|
}, []);
|
|
2240
3004
|
const handleAgeVerificationNo = useCallback(() => {
|
|
2241
3005
|
setShowAgeVerification(false);
|
|
2242
3006
|
setShowGuardianForm(true);
|
|
2243
3007
|
}, []);
|
|
3008
|
+
const handleVerificationContinue = useCallback(() => {
|
|
3009
|
+
setShowVerificationScreen(false);
|
|
3010
|
+
setIsVerificationComplete(false);
|
|
3011
|
+
}, []);
|
|
3012
|
+
const handlePopupClosed = useCallback(async () => {
|
|
3013
|
+
var _a2, _b2;
|
|
3014
|
+
if (popupCheckIntervalRef.current) {
|
|
3015
|
+
clearInterval(popupCheckIntervalRef.current);
|
|
3016
|
+
popupCheckIntervalRef.current = null;
|
|
3017
|
+
}
|
|
3018
|
+
if (statusPollIntervalRef.current) {
|
|
3019
|
+
clearTimeout(statusPollIntervalRef.current);
|
|
3020
|
+
statusPollIntervalRef.current = null;
|
|
3021
|
+
}
|
|
3022
|
+
(_a2 = pollingCleanupRef.current) == null ? void 0 : _a2.call(pollingCleanupRef);
|
|
3023
|
+
pollingCleanupRef.current = null;
|
|
3024
|
+
verificationPopupRef.current = null;
|
|
3025
|
+
if (!isPollingStatusRef.current) return;
|
|
3026
|
+
const sessionToken = verificationSessionTokenRef.current;
|
|
3027
|
+
if (sessionToken) {
|
|
3028
|
+
try {
|
|
3029
|
+
const response = await verifyGuardianStatus({
|
|
3030
|
+
accessToken,
|
|
3031
|
+
baseUrl,
|
|
3032
|
+
sessionToken
|
|
3033
|
+
});
|
|
3034
|
+
if (response.status === "verified") {
|
|
3035
|
+
const ref = response.verification_reference || ((_b2 = response.guardian_details) == null ? void 0 : _b2.verification_reference);
|
|
3036
|
+
if (ref) {
|
|
3037
|
+
setVerificationReference(ref);
|
|
3038
|
+
setIsVerificationComplete(true);
|
|
3039
|
+
setIsPollingStatus(false);
|
|
3040
|
+
isPollingStatusRef.current = false;
|
|
3041
|
+
setIsInitiatingVerification(false);
|
|
3042
|
+
clearConsentState();
|
|
3043
|
+
return;
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
3046
|
+
} catch {
|
|
3047
|
+
}
|
|
3048
|
+
}
|
|
3049
|
+
setVerificationError(
|
|
3050
|
+
"Verification window was closed. Please try again."
|
|
3051
|
+
);
|
|
3052
|
+
setIsPollingStatus(false);
|
|
3053
|
+
isPollingStatusRef.current = false;
|
|
3054
|
+
setIsInitiatingVerification(false);
|
|
3055
|
+
}, [accessToken, baseUrl]);
|
|
3056
|
+
const startPopupMonitoring = useCallback((popup) => {
|
|
3057
|
+
popupCheckIntervalRef.current = window.setInterval(() => {
|
|
3058
|
+
if (popup.closed) {
|
|
3059
|
+
handlePopupClosed();
|
|
3060
|
+
}
|
|
3061
|
+
}, 500);
|
|
3062
|
+
}, [handlePopupClosed]);
|
|
3063
|
+
const getVerificationErrorMessage = useCallback(
|
|
3064
|
+
(errorCode, fallbackError) => {
|
|
3065
|
+
switch (errorCode) {
|
|
3066
|
+
case "GUARDIAN_UNDER_18":
|
|
3067
|
+
return "The guardian must be 18 years or older. Please provide details of a different guardian.";
|
|
3068
|
+
case "TOKEN_FAILED":
|
|
3069
|
+
return "DigiLocker verification could not be completed. Please try again.";
|
|
3070
|
+
case "DIGILOCKER_AUTH_FAILED":
|
|
3071
|
+
return "DigiLocker authorization was cancelled or failed. Please try again.";
|
|
3072
|
+
case "NO_AUTH_CODE":
|
|
3073
|
+
return "DigiLocker did not return an authorization code. Please try again.";
|
|
3074
|
+
case "SESSION_EXPIRED":
|
|
3075
|
+
return "Verification session has expired. Please try again.";
|
|
3076
|
+
default:
|
|
3077
|
+
return fallbackError || "Verification failed. Please try again.";
|
|
3078
|
+
}
|
|
3079
|
+
},
|
|
3080
|
+
[]
|
|
3081
|
+
);
|
|
3082
|
+
const startStatusPolling = useCallback(
|
|
3083
|
+
(token) => {
|
|
3084
|
+
verificationSessionTokenRef.current = token;
|
|
3085
|
+
setIsPollingStatus(true);
|
|
3086
|
+
isPollingStatusRef.current = true;
|
|
3087
|
+
setVerificationError(null);
|
|
3088
|
+
setVerificationErrorCode(null);
|
|
3089
|
+
setCanRetryVerification(false);
|
|
3090
|
+
let attempts = 0;
|
|
3091
|
+
let consecutiveErrors = 0;
|
|
3092
|
+
let paused = false;
|
|
3093
|
+
const MAX_ATTEMPTS = 40;
|
|
3094
|
+
const MAX_CONSECUTIVE_ERRORS = 3;
|
|
3095
|
+
const POLL_INTERVAL = 3e3;
|
|
3096
|
+
const stopPolling = () => {
|
|
3097
|
+
var _a2;
|
|
3098
|
+
if (statusPollIntervalRef.current) {
|
|
3099
|
+
clearTimeout(statusPollIntervalRef.current);
|
|
3100
|
+
statusPollIntervalRef.current = null;
|
|
3101
|
+
}
|
|
3102
|
+
if (popupCheckIntervalRef.current) {
|
|
3103
|
+
clearInterval(popupCheckIntervalRef.current);
|
|
3104
|
+
popupCheckIntervalRef.current = null;
|
|
3105
|
+
}
|
|
3106
|
+
(_a2 = verificationPopupRef.current) == null ? void 0 : _a2.close();
|
|
3107
|
+
verificationPopupRef.current = null;
|
|
3108
|
+
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
3109
|
+
pollingCleanupRef.current = null;
|
|
3110
|
+
setIsPollingStatus(false);
|
|
3111
|
+
isPollingStatusRef.current = false;
|
|
3112
|
+
setIsInitiatingVerification(false);
|
|
3113
|
+
};
|
|
3114
|
+
const setError = (message, errorCode, canRetry) => {
|
|
3115
|
+
stopPolling();
|
|
3116
|
+
setVerificationError(message);
|
|
3117
|
+
setVerificationErrorCode(errorCode);
|
|
3118
|
+
setCanRetryVerification(canRetry);
|
|
3119
|
+
};
|
|
3120
|
+
const poll = async () => {
|
|
3121
|
+
var _a2;
|
|
3122
|
+
if (paused) return;
|
|
3123
|
+
attempts++;
|
|
3124
|
+
if (attempts > MAX_ATTEMPTS) {
|
|
3125
|
+
setError(
|
|
3126
|
+
"Verification is taking longer than expected. Please try again.",
|
|
3127
|
+
"SESSION_EXPIRED",
|
|
3128
|
+
true
|
|
3129
|
+
);
|
|
3130
|
+
return;
|
|
3131
|
+
}
|
|
3132
|
+
try {
|
|
3133
|
+
const response = await verifyGuardianStatus({
|
|
3134
|
+
accessToken,
|
|
3135
|
+
baseUrl,
|
|
3136
|
+
sessionToken: token
|
|
3137
|
+
});
|
|
3138
|
+
consecutiveErrors = 0;
|
|
3139
|
+
if (response.status === "verified") {
|
|
3140
|
+
stopPolling();
|
|
3141
|
+
const ref = response.verification_reference || ((_a2 = response.guardian_details) == null ? void 0 : _a2.verification_reference);
|
|
3142
|
+
if (!ref) {
|
|
3143
|
+
setError(
|
|
3144
|
+
"Verification completed but no reference received. Please try again.",
|
|
3145
|
+
null,
|
|
3146
|
+
true
|
|
3147
|
+
);
|
|
3148
|
+
return;
|
|
3149
|
+
}
|
|
3150
|
+
setVerificationReference(ref);
|
|
3151
|
+
setIsVerificationComplete(true);
|
|
3152
|
+
clearConsentState();
|
|
3153
|
+
return;
|
|
3154
|
+
}
|
|
3155
|
+
if (response.status === "failed" || response.status === "expired") {
|
|
3156
|
+
setError(
|
|
3157
|
+
getVerificationErrorMessage(response.error_code, response.error),
|
|
3158
|
+
response.error_code,
|
|
3159
|
+
response.can_retry
|
|
3160
|
+
);
|
|
3161
|
+
return;
|
|
3162
|
+
}
|
|
3163
|
+
if (!paused) {
|
|
3164
|
+
statusPollIntervalRef.current = window.setTimeout(poll, POLL_INTERVAL);
|
|
3165
|
+
}
|
|
3166
|
+
} catch (error) {
|
|
3167
|
+
const err = error;
|
|
3168
|
+
if (err.status === 404 || err.status === 410) {
|
|
3169
|
+
setError(
|
|
3170
|
+
"Verification session not found or expired. Please try again.",
|
|
3171
|
+
"SESSION_EXPIRED",
|
|
3172
|
+
true
|
|
3173
|
+
);
|
|
3174
|
+
return;
|
|
3175
|
+
}
|
|
3176
|
+
consecutiveErrors++;
|
|
3177
|
+
if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
|
|
3178
|
+
setError(
|
|
3179
|
+
err.message || "Unable to check verification status. Please try again.",
|
|
3180
|
+
null,
|
|
3181
|
+
true
|
|
3182
|
+
);
|
|
3183
|
+
return;
|
|
3184
|
+
}
|
|
3185
|
+
statusPollIntervalRef.current = window.setTimeout(poll, POLL_INTERVAL);
|
|
3186
|
+
}
|
|
3187
|
+
};
|
|
3188
|
+
const onVisibilityChange = () => {
|
|
3189
|
+
if (document.hidden) {
|
|
3190
|
+
paused = true;
|
|
3191
|
+
if (statusPollIntervalRef.current) {
|
|
3192
|
+
clearTimeout(statusPollIntervalRef.current);
|
|
3193
|
+
statusPollIntervalRef.current = null;
|
|
3194
|
+
}
|
|
3195
|
+
} else {
|
|
3196
|
+
paused = false;
|
|
3197
|
+
poll();
|
|
3198
|
+
}
|
|
3199
|
+
};
|
|
3200
|
+
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
3201
|
+
pollingCleanupRef.current = () => {
|
|
3202
|
+
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
3203
|
+
};
|
|
3204
|
+
statusPollIntervalRef.current = window.setTimeout(poll, POLL_INTERVAL);
|
|
3205
|
+
},
|
|
3206
|
+
[accessToken, baseUrl, getVerificationErrorMessage]
|
|
3207
|
+
);
|
|
3208
|
+
const handleBackToGuardianForm = useCallback((clearName = false) => {
|
|
3209
|
+
var _a2, _b2;
|
|
3210
|
+
(_a2 = verificationPopupRef.current) == null ? void 0 : _a2.close();
|
|
3211
|
+
verificationPopupRef.current = null;
|
|
3212
|
+
if (popupCheckIntervalRef.current) {
|
|
3213
|
+
clearInterval(popupCheckIntervalRef.current);
|
|
3214
|
+
popupCheckIntervalRef.current = null;
|
|
3215
|
+
}
|
|
3216
|
+
if (statusPollIntervalRef.current) {
|
|
3217
|
+
clearTimeout(statusPollIntervalRef.current);
|
|
3218
|
+
statusPollIntervalRef.current = null;
|
|
3219
|
+
}
|
|
3220
|
+
if (autoTransitionTimerRef.current) {
|
|
3221
|
+
clearTimeout(autoTransitionTimerRef.current);
|
|
3222
|
+
autoTransitionTimerRef.current = null;
|
|
3223
|
+
}
|
|
3224
|
+
if (digilockerRedirectTimeoutRef.current) {
|
|
3225
|
+
clearTimeout(digilockerRedirectTimeoutRef.current);
|
|
3226
|
+
digilockerRedirectTimeoutRef.current = null;
|
|
3227
|
+
}
|
|
3228
|
+
(_b2 = pollingCleanupRef.current) == null ? void 0 : _b2.call(pollingCleanupRef);
|
|
3229
|
+
pollingCleanupRef.current = null;
|
|
3230
|
+
setShowVerificationScreen(false);
|
|
3231
|
+
setShowGuardianForm(true);
|
|
3232
|
+
setVerificationError(null);
|
|
3233
|
+
setVerificationErrorCode(null);
|
|
3234
|
+
setCanRetryVerification(false);
|
|
3235
|
+
setIsInitiatingVerification(false);
|
|
3236
|
+
setIsPollingStatus(false);
|
|
3237
|
+
isPollingStatusRef.current = false;
|
|
3238
|
+
setIsVerificationComplete(false);
|
|
3239
|
+
if (clearName) {
|
|
3240
|
+
setGuardianFormData((prev) => ({ ...prev, guardianName: "" }));
|
|
3241
|
+
}
|
|
3242
|
+
clearConsentState();
|
|
3243
|
+
}, []);
|
|
2244
3244
|
const availableLanguages = useMemo(() => {
|
|
2245
3245
|
if (!content) return [language];
|
|
2246
3246
|
const languages = ["English"];
|
|
@@ -2650,12 +3650,67 @@ var RedactoNoticeConsent = ({
|
|
|
2650
3650
|
}, [content, stopAudio]);
|
|
2651
3651
|
useEffect2(() => {
|
|
2652
3652
|
return () => {
|
|
3653
|
+
var _a2, _b2;
|
|
2653
3654
|
if (abortControllerRef.current) {
|
|
2654
3655
|
abortControllerRef.current.abort();
|
|
2655
3656
|
}
|
|
2656
3657
|
stopAudio();
|
|
3658
|
+
if (popupCheckIntervalRef.current) {
|
|
3659
|
+
clearInterval(popupCheckIntervalRef.current);
|
|
3660
|
+
}
|
|
3661
|
+
if (statusPollIntervalRef.current) {
|
|
3662
|
+
clearTimeout(statusPollIntervalRef.current);
|
|
3663
|
+
}
|
|
3664
|
+
(_a2 = pollingCleanupRef.current) == null ? void 0 : _a2.call(pollingCleanupRef);
|
|
3665
|
+
pollingCleanupRef.current = null;
|
|
3666
|
+
(_b2 = verificationPopupRef.current) == null ? void 0 : _b2.close();
|
|
3667
|
+
if (autoTransitionTimerRef.current) {
|
|
3668
|
+
clearTimeout(autoTransitionTimerRef.current);
|
|
3669
|
+
autoTransitionTimerRef.current = null;
|
|
3670
|
+
}
|
|
3671
|
+
if (digilockerRedirectTimeoutRef.current) {
|
|
3672
|
+
clearTimeout(digilockerRedirectTimeoutRef.current);
|
|
3673
|
+
digilockerRedirectTimeoutRef.current = null;
|
|
3674
|
+
}
|
|
2657
3675
|
};
|
|
2658
3676
|
}, [stopAudio]);
|
|
3677
|
+
useEffect2(() => {
|
|
3678
|
+
const persistedState = getConsentState();
|
|
3679
|
+
if (!persistedState) return;
|
|
3680
|
+
if (persistedState.noticeId && persistedState.noticeId !== noticeId) {
|
|
3681
|
+
clearConsentState();
|
|
3682
|
+
return;
|
|
3683
|
+
}
|
|
3684
|
+
const REDIRECT_STATE_MAX_AGE_MS = 15 * 60 * 1e3;
|
|
3685
|
+
if (persistedState.timestamp) {
|
|
3686
|
+
const stateAge = Date.now() - new Date(persistedState.timestamp).getTime();
|
|
3687
|
+
if (stateAge > REDIRECT_STATE_MAX_AGE_MS) {
|
|
3688
|
+
clearConsentState();
|
|
3689
|
+
return;
|
|
3690
|
+
}
|
|
3691
|
+
}
|
|
3692
|
+
if (persistedState.flowState === "digilocker-pending" && persistedState.sessionToken) {
|
|
3693
|
+
setShowVerificationScreen(true);
|
|
3694
|
+
setShowGuardianForm(false);
|
|
3695
|
+
setShowAgeVerification(false);
|
|
3696
|
+
startStatusPolling(persistedState.sessionToken);
|
|
3697
|
+
} else if (persistedState.verificationResult === "verified" && persistedState.verificationReference) {
|
|
3698
|
+
setVerificationReference(persistedState.verificationReference);
|
|
3699
|
+
setShowVerificationScreen(true);
|
|
3700
|
+
setIsVerificationComplete(true);
|
|
3701
|
+
setShowGuardianForm(false);
|
|
3702
|
+
setShowAgeVerification(false);
|
|
3703
|
+
clearConsentState();
|
|
3704
|
+
} else if (persistedState.verificationResult === "failed" || persistedState.verificationResult === "expired") {
|
|
3705
|
+
setShowVerificationScreen(true);
|
|
3706
|
+
setShowGuardianForm(false);
|
|
3707
|
+
setShowAgeVerification(false);
|
|
3708
|
+
setVerificationError(
|
|
3709
|
+
persistedState.verificationResult === "expired" ? "Verification session has expired. Please try again." : "Verification failed. Please try again."
|
|
3710
|
+
);
|
|
3711
|
+
clearConsentState();
|
|
3712
|
+
}
|
|
3713
|
+
}, [startStatusPolling, noticeId]);
|
|
2659
3714
|
return /* @__PURE__ */ jsx(Fragment, { children: hasAlreadyConsented ? null : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2660
3715
|
blockUI && /* @__PURE__ */ jsx(
|
|
2661
3716
|
"div",
|
|
@@ -2841,6 +3896,27 @@ var RedactoNoticeConsent = ({
|
|
|
2841
3896
|
declineButtonStyle,
|
|
2842
3897
|
logoUrl: (content == null ? void 0 : content.logo_url) || redacto_logo_default
|
|
2843
3898
|
}
|
|
3899
|
+
) }) : showVerificationScreen ? /* @__PURE__ */ jsx("div", { style: { ...styles.content, ...responsiveStyles.content }, children: /* @__PURE__ */ jsx(
|
|
3900
|
+
VerificationScreen,
|
|
3901
|
+
{
|
|
3902
|
+
onBack: handleBackToGuardianForm,
|
|
3903
|
+
onContinue: handleVerificationContinue,
|
|
3904
|
+
isInitiating: isInitiatingVerification,
|
|
3905
|
+
isPolling: isPollingStatus,
|
|
3906
|
+
isVerificationComplete,
|
|
3907
|
+
isAutoTransitioning,
|
|
3908
|
+
error: verificationError,
|
|
3909
|
+
errorCode: verificationErrorCode,
|
|
3910
|
+
canRetry: canRetryVerification,
|
|
3911
|
+
styles,
|
|
3912
|
+
responsiveStyles,
|
|
3913
|
+
settings,
|
|
3914
|
+
componentHeadingStyle,
|
|
3915
|
+
componentTextStyle,
|
|
3916
|
+
acceptButtonStyle,
|
|
3917
|
+
declineButtonStyle,
|
|
3918
|
+
logoUrl: (content == null ? void 0 : content.logo_url) || redacto_logo_default
|
|
3919
|
+
}
|
|
2844
3920
|
) }) : /* @__PURE__ */ jsxs("div", { style: { ...styles.content, ...responsiveStyles.content }, children: [
|
|
2845
3921
|
errorMessage && /* @__PURE__ */ jsxs(
|
|
2846
3922
|
"div",
|
|
@@ -3474,60 +4550,27 @@ var submitConsentEvent2 = async ({
|
|
|
3474
4550
|
var _a, _b;
|
|
3475
4551
|
try {
|
|
3476
4552
|
const apiBaseUrl = baseUrl || BASE_URL2;
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
name: element.name,
|
|
3499
|
-
enabled: Boolean(element.enabled),
|
|
3500
|
-
required: Boolean(element.required),
|
|
3501
|
-
selected: element.required ? true : Boolean(element.selected)
|
|
3502
|
-
}))
|
|
3503
|
-
};
|
|
3504
|
-
})
|
|
3505
|
-
},
|
|
3506
|
-
meta_data: meta_data ? { specific_uuid: meta_data.specific_uuid } : void 0
|
|
3507
|
-
};
|
|
3508
|
-
} else {
|
|
3509
|
-
payload = {
|
|
3510
|
-
notice_uuid: noticeUuid,
|
|
3511
|
-
purposes: purposes.map((purpose) => {
|
|
3512
|
-
if (!purpose.uuid) {
|
|
3513
|
-
throw new Error(`Invalid purpose data: missing uuid`);
|
|
3514
|
-
}
|
|
3515
|
-
const dataElements = purpose.data_elements.filter((element) => element.enabled).map((element) => ({
|
|
3516
|
-
uuid: element.uuid,
|
|
3517
|
-
selected: element.required ? true : Boolean(element.selected)
|
|
3518
|
-
}));
|
|
3519
|
-
return {
|
|
3520
|
-
purpose_uuid: purpose.uuid,
|
|
3521
|
-
selected: Boolean(purpose.selected),
|
|
3522
|
-
data_elements: dataElements.length > 0 ? dataElements : void 0
|
|
3523
|
-
};
|
|
3524
|
-
}),
|
|
3525
|
-
select_all_mandatory: false,
|
|
3526
|
-
source: "WEB",
|
|
3527
|
-
declined,
|
|
3528
|
-
meta_data
|
|
3529
|
-
};
|
|
3530
|
-
}
|
|
4553
|
+
const payload = {
|
|
4554
|
+
notice_uuid: noticeUuid,
|
|
4555
|
+
purposes: purposes.map((purpose) => {
|
|
4556
|
+
if (!purpose.uuid) {
|
|
4557
|
+
throw new Error(`Invalid purpose data: missing uuid`);
|
|
4558
|
+
}
|
|
4559
|
+
const dataElements = purpose.data_elements.filter((element) => element.enabled).map((element) => ({
|
|
4560
|
+
uuid: element.uuid,
|
|
4561
|
+
selected: element.required ? true : Boolean(element.selected)
|
|
4562
|
+
}));
|
|
4563
|
+
return {
|
|
4564
|
+
purpose_uuid: purpose.uuid,
|
|
4565
|
+
selected: Boolean(purpose.selected),
|
|
4566
|
+
data_elements: dataElements.length > 0 ? dataElements : void 0
|
|
4567
|
+
};
|
|
4568
|
+
}),
|
|
4569
|
+
select_all_mandatory: false,
|
|
4570
|
+
source: "WEB",
|
|
4571
|
+
declined,
|
|
4572
|
+
meta_data
|
|
4573
|
+
};
|
|
3531
4574
|
const response = await fetch(
|
|
3532
4575
|
`${apiBaseUrl}/public/organisations/${org_uuid}/workspaces/${workspace_uuid}/submit-consent`,
|
|
3533
4576
|
{
|
|
@@ -4477,7 +5520,424 @@ var RedactoConsentInlineComponent = ({
|
|
|
4477
5520
|
};
|
|
4478
5521
|
RedactoConsentInlineComponent.displayName = "RedactoConsentInline";
|
|
4479
5522
|
var RedactoConsentInline = memo(RedactoConsentInlineComponent);
|
|
5523
|
+
|
|
5524
|
+
// src/RedactoNoticeConsent/components/DigiLockerCallback.tsx
|
|
5525
|
+
import { useCallback as useCallback3, useEffect as useEffect5, useRef as useRef3, useState as useState5 } from "react";
|
|
5526
|
+
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
5527
|
+
var DigiLockerCallback = ({
|
|
5528
|
+
accessToken: propAccessToken,
|
|
5529
|
+
baseUrl,
|
|
5530
|
+
onSuccess,
|
|
5531
|
+
onError
|
|
5532
|
+
}) => {
|
|
5533
|
+
const [status, setStatus] = useState5("processing");
|
|
5534
|
+
const [message, setMessage] = useState5("Verifying your guardian...");
|
|
5535
|
+
const [errorDetail, setErrorDetail] = useState5(null);
|
|
5536
|
+
const retryTimeoutRef = useRef3(null);
|
|
5537
|
+
const redirectTimeoutRef = useRef3(null);
|
|
5538
|
+
const isMountedRef = useRef3(true);
|
|
5539
|
+
const getErrorMessage = (errorCode) => {
|
|
5540
|
+
switch (errorCode) {
|
|
5541
|
+
case "GUARDIAN_UNDER_18":
|
|
5542
|
+
return "Guardian verification failed: The guardian must be 18 years or older.";
|
|
5543
|
+
case "SESSION_EXPIRED":
|
|
5544
|
+
return "Verification session has expired. Please restart the verification process.";
|
|
5545
|
+
case "TOKEN_FAILED":
|
|
5546
|
+
return "DigiLocker authentication failed. Please try again.";
|
|
5547
|
+
case "DIGILOCKER_AUTH_FAILED":
|
|
5548
|
+
return "DigiLocker authorization was cancelled or failed. Please try again.";
|
|
5549
|
+
case "NO_AUTH_CODE":
|
|
5550
|
+
return "Missing authorization code from DigiLocker. Please try again.";
|
|
5551
|
+
default:
|
|
5552
|
+
return "Verification failed. Please try again.";
|
|
5553
|
+
}
|
|
5554
|
+
};
|
|
5555
|
+
const redirectToOriginalPage = useCallback3(
|
|
5556
|
+
(originalUrl, verificationResult, verificationReference) => {
|
|
5557
|
+
updateConsentState({
|
|
5558
|
+
verificationResult,
|
|
5559
|
+
verificationReference,
|
|
5560
|
+
flowState: verificationResult === "verified" ? "consent-form" : "error"
|
|
5561
|
+
});
|
|
5562
|
+
redirectTimeoutRef.current = setTimeout(() => {
|
|
5563
|
+
window.location.href = originalUrl;
|
|
5564
|
+
}, 1500);
|
|
5565
|
+
},
|
|
5566
|
+
[]
|
|
5567
|
+
);
|
|
5568
|
+
const handleCallback = useCallback3(async () => {
|
|
5569
|
+
var _a, _b;
|
|
5570
|
+
try {
|
|
5571
|
+
const params = new URLSearchParams(window.location.search);
|
|
5572
|
+
const sessionToken = params.get("session_token");
|
|
5573
|
+
const urlStatus = params.get("status");
|
|
5574
|
+
const verificationReference = params.get("verification_reference");
|
|
5575
|
+
const errorCode = params.get("error_code");
|
|
5576
|
+
const persistedState = getConsentState();
|
|
5577
|
+
const originalUrl = (persistedState == null ? void 0 : persistedState.originalUrl) || "/";
|
|
5578
|
+
const storedBaseUrl = persistedState == null ? void 0 : persistedState.baseUrl;
|
|
5579
|
+
const storedSessionToken = persistedState == null ? void 0 : persistedState.sessionToken;
|
|
5580
|
+
const accessToken = propAccessToken;
|
|
5581
|
+
if (!accessToken) {
|
|
5582
|
+
throw new Error("Access token not provided. Please pass accessToken as a prop.");
|
|
5583
|
+
}
|
|
5584
|
+
const activeSessionToken = sessionToken || storedSessionToken;
|
|
5585
|
+
if (!activeSessionToken) {
|
|
5586
|
+
throw new Error("Session token not found. Please restart the verification process.");
|
|
5587
|
+
}
|
|
5588
|
+
let isInIframe = false;
|
|
5589
|
+
try {
|
|
5590
|
+
isInIframe = window.self !== window.top;
|
|
5591
|
+
} catch {
|
|
5592
|
+
isInIframe = true;
|
|
5593
|
+
}
|
|
5594
|
+
if (urlStatus === "verified" && verificationReference) {
|
|
5595
|
+
setStatus("success");
|
|
5596
|
+
setMessage("Guardian verified successfully! Redirecting...");
|
|
5597
|
+
onSuccess == null ? void 0 : onSuccess(verificationReference);
|
|
5598
|
+
if (isInIframe && window.parent) {
|
|
5599
|
+
window.parent.postMessage(
|
|
5600
|
+
{
|
|
5601
|
+
type: "DIGILOCKER_VERIFICATION_STATUS",
|
|
5602
|
+
status: "verified",
|
|
5603
|
+
verificationReference
|
|
5604
|
+
},
|
|
5605
|
+
window.location.origin
|
|
5606
|
+
);
|
|
5607
|
+
return;
|
|
5608
|
+
}
|
|
5609
|
+
redirectToOriginalPage(originalUrl, "verified", verificationReference);
|
|
5610
|
+
return;
|
|
5611
|
+
}
|
|
5612
|
+
if (urlStatus === "failed" || urlStatus === "expired") {
|
|
5613
|
+
const urlErrorCode = errorCode != null ? errorCode : void 0;
|
|
5614
|
+
const errorMessage = getErrorMessage(urlErrorCode);
|
|
5615
|
+
setStatus("error");
|
|
5616
|
+
setMessage("Verification failed");
|
|
5617
|
+
setErrorDetail(errorMessage);
|
|
5618
|
+
onError == null ? void 0 : onError(new Error(errorMessage), urlErrorCode);
|
|
5619
|
+
if (isInIframe && window.parent) {
|
|
5620
|
+
window.parent.postMessage(
|
|
5621
|
+
{
|
|
5622
|
+
type: "DIGILOCKER_VERIFICATION_STATUS",
|
|
5623
|
+
status: urlStatus,
|
|
5624
|
+
errorCode: urlErrorCode,
|
|
5625
|
+
error: errorMessage
|
|
5626
|
+
},
|
|
5627
|
+
window.location.origin
|
|
5628
|
+
);
|
|
5629
|
+
return;
|
|
5630
|
+
}
|
|
5631
|
+
redirectToOriginalPage(originalUrl, urlStatus);
|
|
5632
|
+
return;
|
|
5633
|
+
}
|
|
5634
|
+
setMessage("Processing verification...");
|
|
5635
|
+
const apiBaseUrl = baseUrl || storedBaseUrl;
|
|
5636
|
+
const response = await verifyGuardianStatus({
|
|
5637
|
+
accessToken,
|
|
5638
|
+
baseUrl: apiBaseUrl,
|
|
5639
|
+
sessionToken: activeSessionToken
|
|
5640
|
+
});
|
|
5641
|
+
if (!isMountedRef.current) return;
|
|
5642
|
+
if (response.status === "verified") {
|
|
5643
|
+
const verificationRef = response.verification_reference || ((_a = response.guardian_details) == null ? void 0 : _a.verification_reference) || void 0;
|
|
5644
|
+
if (!verificationRef) {
|
|
5645
|
+
setStatus("error");
|
|
5646
|
+
setMessage("Verification failed");
|
|
5647
|
+
setErrorDetail("Verification completed but no reference received. Please try again.");
|
|
5648
|
+
onError == null ? void 0 : onError(new Error("Verification completed but no reference received."));
|
|
5649
|
+
redirectToOriginalPage(originalUrl, "failed");
|
|
5650
|
+
return;
|
|
5651
|
+
}
|
|
5652
|
+
setStatus("success");
|
|
5653
|
+
setMessage("Guardian verified successfully! Redirecting...");
|
|
5654
|
+
onSuccess == null ? void 0 : onSuccess(verificationRef);
|
|
5655
|
+
if (isInIframe && window.parent) {
|
|
5656
|
+
window.parent.postMessage(
|
|
5657
|
+
{
|
|
5658
|
+
type: "DIGILOCKER_VERIFICATION_STATUS",
|
|
5659
|
+
status: "verified",
|
|
5660
|
+
verificationReference: verificationRef
|
|
5661
|
+
},
|
|
5662
|
+
window.location.origin
|
|
5663
|
+
);
|
|
5664
|
+
return;
|
|
5665
|
+
}
|
|
5666
|
+
redirectToOriginalPage(originalUrl, "verified", verificationRef);
|
|
5667
|
+
} else if (response.status === "failed" || response.status === "expired") {
|
|
5668
|
+
const responseErrorCode = (_b = response.error_code) != null ? _b : void 0;
|
|
5669
|
+
const errorMessage = response.error || getErrorMessage(responseErrorCode);
|
|
5670
|
+
setStatus("error");
|
|
5671
|
+
setMessage("Verification failed");
|
|
5672
|
+
setErrorDetail(errorMessage);
|
|
5673
|
+
onError == null ? void 0 : onError(new Error(errorMessage), responseErrorCode);
|
|
5674
|
+
if (isInIframe && window.parent) {
|
|
5675
|
+
window.parent.postMessage(
|
|
5676
|
+
{
|
|
5677
|
+
type: "DIGILOCKER_VERIFICATION_STATUS",
|
|
5678
|
+
status: response.status,
|
|
5679
|
+
errorCode: responseErrorCode,
|
|
5680
|
+
error: errorMessage
|
|
5681
|
+
},
|
|
5682
|
+
window.location.origin
|
|
5683
|
+
);
|
|
5684
|
+
return;
|
|
5685
|
+
}
|
|
5686
|
+
redirectToOriginalPage(originalUrl, response.status);
|
|
5687
|
+
} else {
|
|
5688
|
+
setMessage("Verification is still in progress. Please wait...");
|
|
5689
|
+
const MAX_RETRIES = 3;
|
|
5690
|
+
let retryCount = 0;
|
|
5691
|
+
const attemptRetry = () => {
|
|
5692
|
+
retryCount++;
|
|
5693
|
+
const delay = 3e3 * Math.pow(2, retryCount - 1);
|
|
5694
|
+
retryTimeoutRef.current = setTimeout(async () => {
|
|
5695
|
+
var _a2, _b2;
|
|
5696
|
+
if (!isMountedRef.current) return;
|
|
5697
|
+
try {
|
|
5698
|
+
const retryResponse = await verifyGuardianStatus({
|
|
5699
|
+
accessToken,
|
|
5700
|
+
baseUrl: apiBaseUrl,
|
|
5701
|
+
sessionToken: activeSessionToken
|
|
5702
|
+
});
|
|
5703
|
+
if (!isMountedRef.current) return;
|
|
5704
|
+
const retryRef = retryResponse.verification_reference || ((_a2 = retryResponse.guardian_details) == null ? void 0 : _a2.verification_reference) || void 0;
|
|
5705
|
+
if (retryResponse.status === "verified" && retryRef) {
|
|
5706
|
+
setStatus("success");
|
|
5707
|
+
setMessage("Guardian verified successfully! Redirecting...");
|
|
5708
|
+
onSuccess == null ? void 0 : onSuccess(retryRef);
|
|
5709
|
+
if (isInIframe && window.parent) {
|
|
5710
|
+
window.parent.postMessage(
|
|
5711
|
+
{
|
|
5712
|
+
type: "DIGILOCKER_VERIFICATION_STATUS",
|
|
5713
|
+
status: "verified",
|
|
5714
|
+
verificationReference: retryRef
|
|
5715
|
+
},
|
|
5716
|
+
window.location.origin
|
|
5717
|
+
);
|
|
5718
|
+
return;
|
|
5719
|
+
}
|
|
5720
|
+
redirectToOriginalPage(originalUrl, "verified", retryRef);
|
|
5721
|
+
} else if (retryResponse.status === "failed" || retryResponse.status === "expired") {
|
|
5722
|
+
const retryErrorCode = (_b2 = retryResponse.error_code) != null ? _b2 : void 0;
|
|
5723
|
+
const retryErrorMessage = retryResponse.error || getErrorMessage(retryErrorCode) || "Verification could not be completed. Please try again.";
|
|
5724
|
+
setStatus("error");
|
|
5725
|
+
setMessage("Verification failed");
|
|
5726
|
+
setErrorDetail(retryErrorMessage);
|
|
5727
|
+
onError == null ? void 0 : onError(new Error(retryErrorMessage), retryErrorCode);
|
|
5728
|
+
if (isInIframe && window.parent) {
|
|
5729
|
+
window.parent.postMessage(
|
|
5730
|
+
{
|
|
5731
|
+
type: "DIGILOCKER_VERIFICATION_STATUS",
|
|
5732
|
+
status: retryResponse.status,
|
|
5733
|
+
errorCode: retryErrorCode,
|
|
5734
|
+
error: retryErrorMessage
|
|
5735
|
+
},
|
|
5736
|
+
window.location.origin
|
|
5737
|
+
);
|
|
5738
|
+
return;
|
|
5739
|
+
}
|
|
5740
|
+
redirectToOriginalPage(originalUrl, retryResponse.status);
|
|
5741
|
+
} else if (retryCount < MAX_RETRIES) {
|
|
5742
|
+
setMessage("Verification taking longer than expected. Please wait...");
|
|
5743
|
+
attemptRetry();
|
|
5744
|
+
} else {
|
|
5745
|
+
const timeoutMessage = "Verification could not be completed in time. Please try again.";
|
|
5746
|
+
setStatus("error");
|
|
5747
|
+
setMessage("Verification failed");
|
|
5748
|
+
setErrorDetail(timeoutMessage);
|
|
5749
|
+
onError == null ? void 0 : onError(new Error(timeoutMessage));
|
|
5750
|
+
redirectToOriginalPage(originalUrl, "failed");
|
|
5751
|
+
}
|
|
5752
|
+
} catch (retryErr) {
|
|
5753
|
+
if (!isMountedRef.current) return;
|
|
5754
|
+
if (retryCount < MAX_RETRIES) {
|
|
5755
|
+
attemptRetry();
|
|
5756
|
+
} else {
|
|
5757
|
+
setStatus("error");
|
|
5758
|
+
setMessage("Verification failed");
|
|
5759
|
+
setErrorDetail(retryErr.message);
|
|
5760
|
+
onError == null ? void 0 : onError(retryErr);
|
|
5761
|
+
redirectToOriginalPage(originalUrl, "failed");
|
|
5762
|
+
}
|
|
5763
|
+
}
|
|
5764
|
+
}, delay);
|
|
5765
|
+
};
|
|
5766
|
+
attemptRetry();
|
|
5767
|
+
}
|
|
5768
|
+
} catch (error) {
|
|
5769
|
+
console.error("DigiLocker callback error:", error);
|
|
5770
|
+
setStatus("error");
|
|
5771
|
+
const err = error;
|
|
5772
|
+
setMessage("Verification failed");
|
|
5773
|
+
setErrorDetail(err.message || "An error occurred during verification");
|
|
5774
|
+
onError == null ? void 0 : onError(err);
|
|
5775
|
+
const persistedState = getConsentState();
|
|
5776
|
+
if (persistedState == null ? void 0 : persistedState.originalUrl) {
|
|
5777
|
+
redirectTimeoutRef.current = setTimeout(() => {
|
|
5778
|
+
redirectToOriginalPage(persistedState.originalUrl, "failed");
|
|
5779
|
+
}, 3e3);
|
|
5780
|
+
}
|
|
5781
|
+
}
|
|
5782
|
+
}, [propAccessToken, baseUrl, onSuccess, onError, redirectToOriginalPage]);
|
|
5783
|
+
useEffect5(() => {
|
|
5784
|
+
injectCheckboxStyles();
|
|
5785
|
+
handleCallback();
|
|
5786
|
+
return () => {
|
|
5787
|
+
isMountedRef.current = false;
|
|
5788
|
+
if (retryTimeoutRef.current) clearTimeout(retryTimeoutRef.current);
|
|
5789
|
+
if (redirectTimeoutRef.current) clearTimeout(redirectTimeoutRef.current);
|
|
5790
|
+
};
|
|
5791
|
+
}, [handleCallback]);
|
|
5792
|
+
const handleRetry = useCallback3(() => {
|
|
5793
|
+
const persistedState = getConsentState();
|
|
5794
|
+
if (persistedState == null ? void 0 : persistedState.originalUrl) {
|
|
5795
|
+
clearConsentState();
|
|
5796
|
+
window.location.href = persistedState.originalUrl;
|
|
5797
|
+
} else {
|
|
5798
|
+
window.location.href = "/";
|
|
5799
|
+
}
|
|
5800
|
+
}, []);
|
|
5801
|
+
const containerStyle = {
|
|
5802
|
+
display: "flex",
|
|
5803
|
+
alignItems: "center",
|
|
5804
|
+
justifyContent: "center",
|
|
5805
|
+
minHeight: "100vh",
|
|
5806
|
+
backgroundColor: "#f9fafb",
|
|
5807
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
|
5808
|
+
padding: "20px",
|
|
5809
|
+
boxSizing: "border-box"
|
|
5810
|
+
};
|
|
5811
|
+
const cardStyle = {
|
|
5812
|
+
backgroundColor: "#ffffff",
|
|
5813
|
+
borderRadius: "12px",
|
|
5814
|
+
boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
|
|
5815
|
+
padding: "40px",
|
|
5816
|
+
textAlign: "center",
|
|
5817
|
+
maxWidth: "400px",
|
|
5818
|
+
width: "100%"
|
|
5819
|
+
};
|
|
5820
|
+
const spinnerStyle = {
|
|
5821
|
+
width: "48px",
|
|
5822
|
+
height: "48px",
|
|
5823
|
+
border: "4px solid #e5e7eb",
|
|
5824
|
+
borderTopColor: "#3b82f6",
|
|
5825
|
+
borderRadius: "50%",
|
|
5826
|
+
animation: "spin 1s linear infinite",
|
|
5827
|
+
margin: "0 auto 24px"
|
|
5828
|
+
};
|
|
5829
|
+
const iconStyle = {
|
|
5830
|
+
width: "64px",
|
|
5831
|
+
height: "64px",
|
|
5832
|
+
borderRadius: "50%",
|
|
5833
|
+
display: "flex",
|
|
5834
|
+
alignItems: "center",
|
|
5835
|
+
justifyContent: "center",
|
|
5836
|
+
margin: "0 auto 24px"
|
|
5837
|
+
};
|
|
5838
|
+
const successIconStyle = {
|
|
5839
|
+
...iconStyle,
|
|
5840
|
+
backgroundColor: "#d1fae5",
|
|
5841
|
+
color: "#059669"
|
|
5842
|
+
};
|
|
5843
|
+
const errorIconStyle = {
|
|
5844
|
+
...iconStyle,
|
|
5845
|
+
backgroundColor: "#fee2e2",
|
|
5846
|
+
color: "#dc2626"
|
|
5847
|
+
};
|
|
5848
|
+
const titleStyle = {
|
|
5849
|
+
fontSize: "20px",
|
|
5850
|
+
fontWeight: 600,
|
|
5851
|
+
color: "#111827",
|
|
5852
|
+
margin: "0 0 12px 0"
|
|
5853
|
+
};
|
|
5854
|
+
const messageStyle = {
|
|
5855
|
+
fontSize: "14px",
|
|
5856
|
+
color: "#6b7280",
|
|
5857
|
+
marginBottom: "8px",
|
|
5858
|
+
lineHeight: 1.5
|
|
5859
|
+
};
|
|
5860
|
+
const errorDetailStyle = {
|
|
5861
|
+
fontSize: "13px",
|
|
5862
|
+
color: "#dc2626",
|
|
5863
|
+
marginTop: "12px",
|
|
5864
|
+
padding: "12px",
|
|
5865
|
+
backgroundColor: "#fef2f2",
|
|
5866
|
+
borderRadius: "6px",
|
|
5867
|
+
border: "1px solid #fecaca"
|
|
5868
|
+
};
|
|
5869
|
+
const buttonStyle = {
|
|
5870
|
+
marginTop: "20px",
|
|
5871
|
+
padding: "10px 24px",
|
|
5872
|
+
backgroundColor: "#3b82f6",
|
|
5873
|
+
color: "#ffffff",
|
|
5874
|
+
border: "none",
|
|
5875
|
+
borderRadius: "6px",
|
|
5876
|
+
fontSize: "14px",
|
|
5877
|
+
fontWeight: 500,
|
|
5878
|
+
cursor: "pointer",
|
|
5879
|
+
transition: "background-color 0.2s"
|
|
5880
|
+
};
|
|
5881
|
+
return /* @__PURE__ */ jsx3("div", { style: containerStyle, children: /* @__PURE__ */ jsxs3("div", { style: cardStyle, children: [
|
|
5882
|
+
status === "processing" && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
5883
|
+
/* @__PURE__ */ jsx3("div", { style: spinnerStyle }),
|
|
5884
|
+
/* @__PURE__ */ jsx3("h2", { style: titleStyle, children: "Processing Verification" }),
|
|
5885
|
+
/* @__PURE__ */ jsx3("p", { style: messageStyle, children: message }),
|
|
5886
|
+
/* @__PURE__ */ jsx3("p", { style: { ...messageStyle, fontSize: "12px", color: "#9ca3af" }, children: "Please wait while we verify your guardian's identity..." })
|
|
5887
|
+
] }),
|
|
5888
|
+
status === "success" && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
5889
|
+
/* @__PURE__ */ jsx3("div", { style: successIconStyle, children: /* @__PURE__ */ jsx3(
|
|
5890
|
+
"svg",
|
|
5891
|
+
{
|
|
5892
|
+
width: "32",
|
|
5893
|
+
height: "32",
|
|
5894
|
+
viewBox: "0 0 24 24",
|
|
5895
|
+
fill: "none",
|
|
5896
|
+
stroke: "currentColor",
|
|
5897
|
+
strokeWidth: "2",
|
|
5898
|
+
strokeLinecap: "round",
|
|
5899
|
+
strokeLinejoin: "round",
|
|
5900
|
+
children: /* @__PURE__ */ jsx3("polyline", { points: "20 6 9 17 4 12" })
|
|
5901
|
+
}
|
|
5902
|
+
) }),
|
|
5903
|
+
/* @__PURE__ */ jsx3("h2", { style: titleStyle, children: "Verification Successful" }),
|
|
5904
|
+
/* @__PURE__ */ jsx3("p", { style: messageStyle, children: message })
|
|
5905
|
+
] }),
|
|
5906
|
+
status === "error" && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
5907
|
+
/* @__PURE__ */ jsx3("div", { style: errorIconStyle, children: /* @__PURE__ */ jsxs3(
|
|
5908
|
+
"svg",
|
|
5909
|
+
{
|
|
5910
|
+
width: "32",
|
|
5911
|
+
height: "32",
|
|
5912
|
+
viewBox: "0 0 24 24",
|
|
5913
|
+
fill: "none",
|
|
5914
|
+
stroke: "currentColor",
|
|
5915
|
+
strokeWidth: "2",
|
|
5916
|
+
strokeLinecap: "round",
|
|
5917
|
+
strokeLinejoin: "round",
|
|
5918
|
+
children: [
|
|
5919
|
+
/* @__PURE__ */ jsx3("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
5920
|
+
/* @__PURE__ */ jsx3("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
5921
|
+
]
|
|
5922
|
+
}
|
|
5923
|
+
) }),
|
|
5924
|
+
/* @__PURE__ */ jsx3("h2", { style: titleStyle, children: "Verification Failed" }),
|
|
5925
|
+
/* @__PURE__ */ jsx3("p", { style: messageStyle, children: message }),
|
|
5926
|
+
errorDetail && /* @__PURE__ */ jsx3("p", { style: errorDetailStyle, children: errorDetail }),
|
|
5927
|
+
/* @__PURE__ */ jsx3(
|
|
5928
|
+
"button",
|
|
5929
|
+
{
|
|
5930
|
+
className: "redacto-dl-retry-btn",
|
|
5931
|
+
style: buttonStyle,
|
|
5932
|
+
onClick: handleRetry,
|
|
5933
|
+
children: "Try Again"
|
|
5934
|
+
}
|
|
5935
|
+
)
|
|
5936
|
+
] })
|
|
5937
|
+
] }) });
|
|
5938
|
+
};
|
|
4480
5939
|
export {
|
|
5940
|
+
DigiLockerCallback,
|
|
4481
5941
|
RedactoNoticeConsent,
|
|
4482
5942
|
RedactoConsentInline as RedactoNoticeConsentInline
|
|
4483
5943
|
};
|