@redacto.io/consent-sdk-react-native 4.0.1-beta.0 → 5.0.0-beta.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/dist/index.d.mts CHANGED
@@ -31,6 +31,8 @@ type Props$1 = Readonly<{
31
31
  accessToken: string;
32
32
  refreshToken: string;
33
33
  baseUrl?: string;
34
+ /** Go ledger base URL — serves check-consent and the consent write; omit to use the legacy consent server. */
35
+ ledgerBaseUrl?: string;
34
36
  settings?: Partial<Settings$1>;
35
37
  language?: string;
36
38
  blockUI?: boolean;
@@ -77,6 +79,7 @@ declare const RedactoConsentInline: React__default.NamedExoticComponent<Readonly
77
79
  accessToken?: string;
78
80
  refreshToken?: string;
79
81
  baseUrl?: string;
82
+ ledgerBaseUrl?: string;
80
83
  settings?: Partial<Settings>;
81
84
  language?: string;
82
85
  onAccept?: () => void;
@@ -93,6 +96,8 @@ type Props = Readonly<{
93
96
  accessToken?: string;
94
97
  refreshToken?: string;
95
98
  baseUrl?: string;
99
+ /** Go ledger base URL — serves check-consent and the consent write; omit to use the legacy consent server. */
100
+ ledgerBaseUrl?: string;
96
101
  settings?: Partial<Settings>;
97
102
  language?: string;
98
103
  onAccept?: () => void;
package/dist/index.d.ts CHANGED
@@ -31,6 +31,8 @@ type Props$1 = Readonly<{
31
31
  accessToken: string;
32
32
  refreshToken: string;
33
33
  baseUrl?: string;
34
+ /** Go ledger base URL — serves check-consent and the consent write; omit to use the legacy consent server. */
35
+ ledgerBaseUrl?: string;
34
36
  settings?: Partial<Settings$1>;
35
37
  language?: string;
36
38
  blockUI?: boolean;
@@ -77,6 +79,7 @@ declare const RedactoConsentInline: React__default.NamedExoticComponent<Readonly
77
79
  accessToken?: string;
78
80
  refreshToken?: string;
79
81
  baseUrl?: string;
82
+ ledgerBaseUrl?: string;
80
83
  settings?: Partial<Settings>;
81
84
  language?: string;
82
85
  onAccept?: () => void;
@@ -93,6 +96,8 @@ type Props = Readonly<{
93
96
  accessToken?: string;
94
97
  refreshToken?: string;
95
98
  baseUrl?: string;
99
+ /** Go ledger base URL — serves check-consent and the consent write; omit to use the legacy consent server. */
100
+ ledgerBaseUrl?: string;
96
101
  settings?: Partial<Settings>;
97
102
  language?: string;
98
103
  onAccept?: () => void;
package/dist/index.js CHANGED
@@ -147,6 +147,7 @@ var fetchConsentContent = async ({
147
147
  var submitConsentEvent = async ({
148
148
  accessToken,
149
149
  baseUrl,
150
+ ledgerBaseUrl,
150
151
  noticeUuid,
151
152
  purposes,
152
153
  declined,
@@ -166,7 +167,7 @@ var submitConsentEvent = async ({
166
167
  if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
167
168
  throw new Error("Invalid token: missing organization or workspace UUID");
168
169
  }
169
- const apiBaseUrl = baseUrl || DEFAULT_CONSENT_API_BASE_URL;
170
+ const apiBaseUrl = ledgerBaseUrl || baseUrl || DEFAULT_CONSENT_API_BASE_URL;
170
171
  const validatedPurposes = purposes.map((purpose) => {
171
172
  if (!purpose.uuid) {
172
173
  throw new Error("Invalid purpose data: missing uuid");
@@ -415,6 +416,122 @@ var verifyGuardianStatus = async ({
415
416
  };
416
417
  };
417
418
 
419
+ // src/shared/notice-consent-status.ts
420
+ var import_jwt_decode2 = require("jwt-decode");
421
+ var decodeNoticeConsentToken = (token) => {
422
+ try {
423
+ return (0, import_jwt_decode2.jwtDecode)(token);
424
+ } catch {
425
+ return null;
426
+ }
427
+ };
428
+ var fetchNoticeConsentStatusForScope = async ({
429
+ accessToken,
430
+ ledgerBaseUrl,
431
+ organisationUuid,
432
+ workspaceUuid,
433
+ noticeUuid,
434
+ signal
435
+ }) => {
436
+ if (!accessToken || !ledgerBaseUrl || !organisationUuid || !workspaceUuid || !noticeUuid) {
437
+ return null;
438
+ }
439
+ try {
440
+ const response = await fetch(
441
+ `${ledgerBaseUrl}/public/organisations/${organisationUuid}/workspaces/${workspaceUuid}/notices/${noticeUuid}/check-consent`,
442
+ {
443
+ method: "POST",
444
+ headers: {
445
+ Authorization: `Bearer ${accessToken}`,
446
+ "Content-Type": "application/json"
447
+ },
448
+ body: "{}",
449
+ signal
450
+ }
451
+ );
452
+ if (!response.ok) {
453
+ return null;
454
+ }
455
+ const data = await response.json();
456
+ const body = data && typeof data === "object" && "detail" in data && data.detail ? data.detail : data;
457
+ if (!body || !Array.isArray(body.purposes)) {
458
+ return null;
459
+ }
460
+ return body;
461
+ } catch {
462
+ return null;
463
+ }
464
+ };
465
+ var fetchNoticeConsentStatus = async ({
466
+ accessToken,
467
+ ledgerBaseUrl,
468
+ noticeUuid,
469
+ signal
470
+ }) => {
471
+ if (!accessToken || !ledgerBaseUrl || !noticeUuid) {
472
+ return null;
473
+ }
474
+ const decodedToken = decodeNoticeConsentToken(accessToken);
475
+ if (!decodedToken) {
476
+ return null;
477
+ }
478
+ const {
479
+ organisation_uuid: ORGANISATION_UUID,
480
+ workspace_uuid: WORKSPACE_UUID
481
+ } = decodedToken;
482
+ if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
483
+ return null;
484
+ }
485
+ return fetchNoticeConsentStatusForScope({
486
+ accessToken,
487
+ ledgerBaseUrl,
488
+ organisationUuid: ORGANISATION_UUID,
489
+ workspaceUuid: WORKSPACE_UUID,
490
+ noticeUuid,
491
+ signal
492
+ });
493
+ };
494
+ var isNoticeFullyConsented = (status) => status.consented && status.all_mandatory_active;
495
+ var buildLedgerConsentOverlay = (status, configPurposes) => {
496
+ var _a, _b;
497
+ const byUuid = new Map(status.purposes.map((p) => [p.uuid, p]));
498
+ const hasHistory = status.purposes.some(
499
+ (p) => (p.status || "INACTIVE") !== "INACTIVE"
500
+ );
501
+ if (!hasHistory) {
502
+ return null;
503
+ }
504
+ const purpose_selections = {};
505
+ for (const cp of configPurposes) {
506
+ const lp = byUuid.get(cp.uuid);
507
+ const purposeStatus = (lp == null ? void 0 : lp.status) || "INACTIVE";
508
+ const selectedByUuid = new Map(
509
+ ((lp == null ? void 0 : lp.data_elements) || []).map((de) => [de.uuid, de.selected])
510
+ );
511
+ const data_elements = {};
512
+ for (const de of cp.data_elements) {
513
+ data_elements[de.uuid] = {
514
+ selected: (_a = selectedByUuid.get(de.uuid)) != null ? _a : false,
515
+ enabled: de.enabled,
516
+ required: de.required
517
+ };
518
+ }
519
+ purpose_selections[cp.uuid] = {
520
+ selected: (_b = lp == null ? void 0 : lp.selected) != null ? _b : false,
521
+ status: purposeStatus,
522
+ needs_reconsent: purposeStatus !== "ACTIVE",
523
+ data_elements
524
+ };
525
+ }
526
+ const reconsent_required = configPurposes.some(
527
+ (cp) => {
528
+ var _a2;
529
+ return (((_a2 = purpose_selections[cp.uuid]) == null ? void 0 : _a2.status) || "INACTIVE") !== "ACTIVE";
530
+ }
531
+ );
532
+ return { reconsent_required, purpose_selections };
533
+ };
534
+
418
535
  // src/RedactoNoticeConsent/components/Checkbox.tsx
419
536
  var import_react_native = require("react-native");
420
537
  var import_react_native_svg = __toESM(require("react-native-svg"));
@@ -1638,6 +1755,7 @@ var RedactoNoticeConsent = ({
1638
1755
  accessToken,
1639
1756
  refreshToken: _refreshToken,
1640
1757
  baseUrl,
1758
+ ledgerBaseUrl,
1641
1759
  settings,
1642
1760
  language = "en",
1643
1761
  blockUI = false,
@@ -1697,6 +1815,7 @@ var RedactoNoticeConsent = ({
1697
1815
  const abortControllerRef = (0, import_react2.useRef)(null);
1698
1816
  const hasBootstrappedLanguageRef = (0, import_react2.useRef)(false);
1699
1817
  const fetchContent = (0, import_react2.useCallback)(async () => {
1818
+ var _a2, _b2;
1700
1819
  if (abortControllerRef.current) {
1701
1820
  abortControllerRef.current.abort();
1702
1821
  }
@@ -1715,8 +1834,23 @@ var RedactoNoticeConsent = ({
1715
1834
  signal: abortControllerRef.current.signal
1716
1835
  });
1717
1836
  const activeConfig2 = data.detail.active_config;
1718
- const purposeSelections = data.detail.purpose_selections;
1719
- const reconsentRequired = data.detail.reconsent_required || false;
1837
+ let purposeSelections = data.detail.purpose_selections;
1838
+ let reconsentRequired = data.detail.reconsent_required || false;
1839
+ if (ledgerBaseUrl && !applicationId) {
1840
+ const ledgerStatus = await fetchNoticeConsentStatus({
1841
+ accessToken,
1842
+ ledgerBaseUrl,
1843
+ noticeUuid: noticeId,
1844
+ signal: (_a2 = abortControllerRef.current) == null ? void 0 : _a2.signal
1845
+ });
1846
+ if (ledgerStatus) {
1847
+ const overlay = buildLedgerConsentOverlay(ledgerStatus, activeConfig2.purposes);
1848
+ reconsentRequired = (_b2 = overlay == null ? void 0 : overlay.reconsent_required) != null ? _b2 : false;
1849
+ purposeSelections = overlay == null ? void 0 : overlay.purpose_selections;
1850
+ data.detail.purpose_selections = purposeSelections;
1851
+ data.detail.reconsent_required = reconsentRequired;
1852
+ }
1853
+ }
1720
1854
  const noticeIsMinor = data.detail.is_minor || false;
1721
1855
  setIsMinor(noticeIsMinor);
1722
1856
  const initialCollapsed = {};
@@ -1729,9 +1863,9 @@ var RedactoNoticeConsent = ({
1729
1863
  const purposeSelected = sel ? sel.selected : false;
1730
1864
  initialPurposeState[purpose.uuid] = purposeSelected;
1731
1865
  purpose.data_elements.forEach((el) => {
1732
- var _a2, _b2, _c2;
1866
+ var _a3, _b3, _c2;
1733
1867
  const combinedId = `${purpose.uuid}-${el.uuid}`;
1734
- const elementSel = (_c2 = (_b2 = (_a2 = sel == null ? void 0 : sel.data_elements) == null ? void 0 : _a2[el.uuid]) == null ? void 0 : _b2.selected) != null ? _c2 : false;
1868
+ const elementSel = (_c2 = (_b3 = (_a3 = sel == null ? void 0 : sel.data_elements) == null ? void 0 : _a3[el.uuid]) == null ? void 0 : _b3.selected) != null ? _c2 : false;
1735
1869
  initialDataElementState[combinedId] = elementSel;
1736
1870
  initialDataElementSelectionsMap[combinedId] = elementSel;
1737
1871
  });
@@ -1779,7 +1913,7 @@ var RedactoNoticeConsent = ({
1779
1913
  } finally {
1780
1914
  setIsLoading(false);
1781
1915
  }
1782
- }, [noticeId, accessToken, baseUrl, validateAgainst, includeFullyConsentedData, applicationId, onAccept, onError]);
1916
+ }, [noticeId, accessToken, baseUrl, ledgerBaseUrl, validateAgainst, includeFullyConsentedData, applicationId, onAccept, onError]);
1783
1917
  (0, import_react2.useEffect)(() => {
1784
1918
  hasBootstrappedLanguageRef.current = false;
1785
1919
  }, [noticeId, accessToken]);
@@ -2182,6 +2316,7 @@ var RedactoNoticeConsent = ({
2182
2316
  await submitConsentEvent({
2183
2317
  accessToken,
2184
2318
  baseUrl,
2319
+ ledgerBaseUrl,
2185
2320
  noticeUuid: activeConfig2.notice_uuid,
2186
2321
  purposes: activeConfig2.purposes.map((purpose) => ({
2187
2322
  ...purpose,
@@ -2209,7 +2344,7 @@ var RedactoNoticeConsent = ({
2209
2344
  } finally {
2210
2345
  setIsSubmitting(false);
2211
2346
  }
2212
- }, [content, accessToken, baseUrl, applicationId, selectedPurposes, selectedDataElements, stopAudio, onAccept, onError]);
2347
+ }, [content, accessToken, baseUrl, ledgerBaseUrl, applicationId, selectedPurposes, selectedDataElements, stopAudio, onAccept, onError]);
2213
2348
  const handleDecline = (0, import_react2.useCallback)(() => {
2214
2349
  stopAudio();
2215
2350
  stopPolling();
@@ -2857,13 +2992,14 @@ var submitConsentEvent2 = async ({
2857
2992
  workspace_uuid,
2858
2993
  accessToken,
2859
2994
  baseUrl,
2995
+ ledgerBaseUrl,
2860
2996
  noticeUuid,
2861
2997
  purposes,
2862
2998
  declined,
2863
2999
  meta_data
2864
3000
  }) => {
2865
3001
  var _a, _b;
2866
- const apiBaseUrl = baseUrl || DEFAULT_CONSENT_API_BASE_URL;
3002
+ const apiBaseUrl = ledgerBaseUrl || baseUrl || DEFAULT_CONSENT_API_BASE_URL;
2867
3003
  const payload = {
2868
3004
  notice_uuid: noticeUuid,
2869
3005
  purposes: purposes.map((purpose) => {
@@ -3185,6 +3321,7 @@ var RedactoConsentInlineComponent = ({
3185
3321
  notice_uuid,
3186
3322
  accessToken,
3187
3323
  baseUrl,
3324
+ ledgerBaseUrl,
3188
3325
  language = "en",
3189
3326
  onAccept,
3190
3327
  onDecline: _onDecline,
@@ -3203,6 +3340,9 @@ var RedactoConsentInlineComponent = ({
3203
3340
  const [selectedPurposes, setSelectedPurposes] = (0, import_react3.useState)({});
3204
3341
  const [selectedDataElements, setSelectedDataElements] = (0, import_react3.useState)({});
3205
3342
  const [hasAlreadyConsented, setHasAlreadyConsented] = (0, import_react3.useState)(false);
3343
+ const [isCheckingConsent, setIsCheckingConsent] = (0, import_react3.useState)(
3344
+ Boolean(ledgerBaseUrl) && !applicationId
3345
+ );
3206
3346
  const [fetchError, setFetchError] = (0, import_react3.useState)(null);
3207
3347
  const [errorMessage, setErrorMessage] = (0, import_react3.useState)(null);
3208
3348
  const [isLanguageDropdownOpen, setIsLanguageDropdownOpen] = (0, import_react3.useState)(false);
@@ -3323,6 +3463,40 @@ var RedactoConsentInlineComponent = ({
3323
3463
  controller.abort();
3324
3464
  };
3325
3465
  }, [fetchNotice]);
3466
+ (0, import_react3.useEffect)(() => {
3467
+ if (!ledgerBaseUrl || applicationId) {
3468
+ return;
3469
+ }
3470
+ if (!accessToken || !content) {
3471
+ return;
3472
+ }
3473
+ let active = true;
3474
+ const controller = new AbortController();
3475
+ const checkLedgerConsent = async () => {
3476
+ try {
3477
+ const ledgerStatus = await fetchNoticeConsentStatusForScope({
3478
+ accessToken,
3479
+ ledgerBaseUrl,
3480
+ organisationUuid: org_uuid,
3481
+ workspaceUuid: workspace_uuid,
3482
+ noticeUuid: notice_uuid,
3483
+ signal: controller.signal
3484
+ });
3485
+ if (active && ledgerStatus && isNoticeFullyConsented(ledgerStatus)) {
3486
+ setHasAlreadyConsented(true);
3487
+ }
3488
+ } finally {
3489
+ if (active) {
3490
+ setIsCheckingConsent(false);
3491
+ }
3492
+ }
3493
+ };
3494
+ void checkLedgerConsent();
3495
+ return () => {
3496
+ active = false;
3497
+ controller.abort();
3498
+ };
3499
+ }, [ledgerBaseUrl, applicationId, accessToken, content, org_uuid, workspace_uuid, notice_uuid]);
3326
3500
  const togglePurposeCollapse = (0, import_react3.useCallback)((purposeUuid) => {
3327
3501
  setCollapsedPurposes((prev) => ({ ...prev, [purposeUuid]: !prev[purposeUuid] }));
3328
3502
  }, []);
@@ -3373,6 +3547,7 @@ var RedactoConsentInlineComponent = ({
3373
3547
  workspace_uuid,
3374
3548
  accessToken: tokenToUse,
3375
3549
  baseUrl,
3550
+ ledgerBaseUrl,
3376
3551
  noticeUuid: content.notice_uuid,
3377
3552
  purposes: content.purposes.map((purpose) => {
3378
3553
  const hasSelectedRequiredElement = purpose.data_elements.some(
@@ -3411,6 +3586,7 @@ var RedactoConsentInlineComponent = ({
3411
3586
  org_uuid,
3412
3587
  workspace_uuid,
3413
3588
  baseUrl,
3589
+ ledgerBaseUrl,
3414
3590
  selectedDataElements,
3415
3591
  selectedPurposes,
3416
3592
  applicationId,
@@ -3418,7 +3594,7 @@ var RedactoConsentInlineComponent = ({
3418
3594
  ]
3419
3595
  );
3420
3596
  (0, import_react3.useEffect)(() => {
3421
- if (accessToken && content && areAllRequiredElementsChecked && !isSubmitting && !hasSubmittedRef.current) {
3597
+ if (accessToken && content && areAllRequiredElementsChecked && !isSubmitting && !isCheckingConsent && !hasAlreadyConsented && !hasSubmittedRef.current) {
3422
3598
  hasSubmittedRef.current = true;
3423
3599
  const autoSubmit = async () => {
3424
3600
  try {
@@ -3430,7 +3606,7 @@ var RedactoConsentInlineComponent = ({
3430
3606
  };
3431
3607
  autoSubmit();
3432
3608
  }
3433
- }, [accessToken, content, areAllRequiredElementsChecked, isSubmitting, handleAcceptWithToken, onError]);
3609
+ }, [accessToken, content, areAllRequiredElementsChecked, isSubmitting, isCheckingConsent, hasAlreadyConsented, handleAcceptWithToken, onError]);
3434
3610
  (0, import_react3.useEffect)(() => {
3435
3611
  if (!accessToken) {
3436
3612
  hasSubmittedRef.current = false;
package/dist/index.mjs CHANGED
@@ -131,6 +131,7 @@ var fetchConsentContent = async ({
131
131
  var submitConsentEvent = async ({
132
132
  accessToken,
133
133
  baseUrl,
134
+ ledgerBaseUrl,
134
135
  noticeUuid,
135
136
  purposes,
136
137
  declined,
@@ -150,7 +151,7 @@ var submitConsentEvent = async ({
150
151
  if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
151
152
  throw new Error("Invalid token: missing organization or workspace UUID");
152
153
  }
153
- const apiBaseUrl = baseUrl || DEFAULT_CONSENT_API_BASE_URL;
154
+ const apiBaseUrl = ledgerBaseUrl || baseUrl || DEFAULT_CONSENT_API_BASE_URL;
154
155
  const validatedPurposes = purposes.map((purpose) => {
155
156
  if (!purpose.uuid) {
156
157
  throw new Error("Invalid purpose data: missing uuid");
@@ -399,6 +400,122 @@ var verifyGuardianStatus = async ({
399
400
  };
400
401
  };
401
402
 
403
+ // src/shared/notice-consent-status.ts
404
+ import { jwtDecode as jwtDecode2 } from "jwt-decode";
405
+ var decodeNoticeConsentToken = (token) => {
406
+ try {
407
+ return jwtDecode2(token);
408
+ } catch {
409
+ return null;
410
+ }
411
+ };
412
+ var fetchNoticeConsentStatusForScope = async ({
413
+ accessToken,
414
+ ledgerBaseUrl,
415
+ organisationUuid,
416
+ workspaceUuid,
417
+ noticeUuid,
418
+ signal
419
+ }) => {
420
+ if (!accessToken || !ledgerBaseUrl || !organisationUuid || !workspaceUuid || !noticeUuid) {
421
+ return null;
422
+ }
423
+ try {
424
+ const response = await fetch(
425
+ `${ledgerBaseUrl}/public/organisations/${organisationUuid}/workspaces/${workspaceUuid}/notices/${noticeUuid}/check-consent`,
426
+ {
427
+ method: "POST",
428
+ headers: {
429
+ Authorization: `Bearer ${accessToken}`,
430
+ "Content-Type": "application/json"
431
+ },
432
+ body: "{}",
433
+ signal
434
+ }
435
+ );
436
+ if (!response.ok) {
437
+ return null;
438
+ }
439
+ const data = await response.json();
440
+ const body = data && typeof data === "object" && "detail" in data && data.detail ? data.detail : data;
441
+ if (!body || !Array.isArray(body.purposes)) {
442
+ return null;
443
+ }
444
+ return body;
445
+ } catch {
446
+ return null;
447
+ }
448
+ };
449
+ var fetchNoticeConsentStatus = async ({
450
+ accessToken,
451
+ ledgerBaseUrl,
452
+ noticeUuid,
453
+ signal
454
+ }) => {
455
+ if (!accessToken || !ledgerBaseUrl || !noticeUuid) {
456
+ return null;
457
+ }
458
+ const decodedToken = decodeNoticeConsentToken(accessToken);
459
+ if (!decodedToken) {
460
+ return null;
461
+ }
462
+ const {
463
+ organisation_uuid: ORGANISATION_UUID,
464
+ workspace_uuid: WORKSPACE_UUID
465
+ } = decodedToken;
466
+ if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
467
+ return null;
468
+ }
469
+ return fetchNoticeConsentStatusForScope({
470
+ accessToken,
471
+ ledgerBaseUrl,
472
+ organisationUuid: ORGANISATION_UUID,
473
+ workspaceUuid: WORKSPACE_UUID,
474
+ noticeUuid,
475
+ signal
476
+ });
477
+ };
478
+ var isNoticeFullyConsented = (status) => status.consented && status.all_mandatory_active;
479
+ var buildLedgerConsentOverlay = (status, configPurposes) => {
480
+ var _a, _b;
481
+ const byUuid = new Map(status.purposes.map((p) => [p.uuid, p]));
482
+ const hasHistory = status.purposes.some(
483
+ (p) => (p.status || "INACTIVE") !== "INACTIVE"
484
+ );
485
+ if (!hasHistory) {
486
+ return null;
487
+ }
488
+ const purpose_selections = {};
489
+ for (const cp of configPurposes) {
490
+ const lp = byUuid.get(cp.uuid);
491
+ const purposeStatus = (lp == null ? void 0 : lp.status) || "INACTIVE";
492
+ const selectedByUuid = new Map(
493
+ ((lp == null ? void 0 : lp.data_elements) || []).map((de) => [de.uuid, de.selected])
494
+ );
495
+ const data_elements = {};
496
+ for (const de of cp.data_elements) {
497
+ data_elements[de.uuid] = {
498
+ selected: (_a = selectedByUuid.get(de.uuid)) != null ? _a : false,
499
+ enabled: de.enabled,
500
+ required: de.required
501
+ };
502
+ }
503
+ purpose_selections[cp.uuid] = {
504
+ selected: (_b = lp == null ? void 0 : lp.selected) != null ? _b : false,
505
+ status: purposeStatus,
506
+ needs_reconsent: purposeStatus !== "ACTIVE",
507
+ data_elements
508
+ };
509
+ }
510
+ const reconsent_required = configPurposes.some(
511
+ (cp) => {
512
+ var _a2;
513
+ return (((_a2 = purpose_selections[cp.uuid]) == null ? void 0 : _a2.status) || "INACTIVE") !== "ACTIVE";
514
+ }
515
+ );
516
+ return { reconsent_required, purpose_selections };
517
+ };
518
+
402
519
  // src/RedactoNoticeConsent/components/Checkbox.tsx
403
520
  import { TouchableOpacity, View, StyleSheet } from "react-native";
404
521
  import Svg, { Path } from "react-native-svg";
@@ -1629,6 +1746,7 @@ var RedactoNoticeConsent = ({
1629
1746
  accessToken,
1630
1747
  refreshToken: _refreshToken,
1631
1748
  baseUrl,
1749
+ ledgerBaseUrl,
1632
1750
  settings,
1633
1751
  language = "en",
1634
1752
  blockUI = false,
@@ -1688,6 +1806,7 @@ var RedactoNoticeConsent = ({
1688
1806
  const abortControllerRef = useRef2(null);
1689
1807
  const hasBootstrappedLanguageRef = useRef2(false);
1690
1808
  const fetchContent = useCallback(async () => {
1809
+ var _a2, _b2;
1691
1810
  if (abortControllerRef.current) {
1692
1811
  abortControllerRef.current.abort();
1693
1812
  }
@@ -1706,8 +1825,23 @@ var RedactoNoticeConsent = ({
1706
1825
  signal: abortControllerRef.current.signal
1707
1826
  });
1708
1827
  const activeConfig2 = data.detail.active_config;
1709
- const purposeSelections = data.detail.purpose_selections;
1710
- const reconsentRequired = data.detail.reconsent_required || false;
1828
+ let purposeSelections = data.detail.purpose_selections;
1829
+ let reconsentRequired = data.detail.reconsent_required || false;
1830
+ if (ledgerBaseUrl && !applicationId) {
1831
+ const ledgerStatus = await fetchNoticeConsentStatus({
1832
+ accessToken,
1833
+ ledgerBaseUrl,
1834
+ noticeUuid: noticeId,
1835
+ signal: (_a2 = abortControllerRef.current) == null ? void 0 : _a2.signal
1836
+ });
1837
+ if (ledgerStatus) {
1838
+ const overlay = buildLedgerConsentOverlay(ledgerStatus, activeConfig2.purposes);
1839
+ reconsentRequired = (_b2 = overlay == null ? void 0 : overlay.reconsent_required) != null ? _b2 : false;
1840
+ purposeSelections = overlay == null ? void 0 : overlay.purpose_selections;
1841
+ data.detail.purpose_selections = purposeSelections;
1842
+ data.detail.reconsent_required = reconsentRequired;
1843
+ }
1844
+ }
1711
1845
  const noticeIsMinor = data.detail.is_minor || false;
1712
1846
  setIsMinor(noticeIsMinor);
1713
1847
  const initialCollapsed = {};
@@ -1720,9 +1854,9 @@ var RedactoNoticeConsent = ({
1720
1854
  const purposeSelected = sel ? sel.selected : false;
1721
1855
  initialPurposeState[purpose.uuid] = purposeSelected;
1722
1856
  purpose.data_elements.forEach((el) => {
1723
- var _a2, _b2, _c2;
1857
+ var _a3, _b3, _c2;
1724
1858
  const combinedId = `${purpose.uuid}-${el.uuid}`;
1725
- const elementSel = (_c2 = (_b2 = (_a2 = sel == null ? void 0 : sel.data_elements) == null ? void 0 : _a2[el.uuid]) == null ? void 0 : _b2.selected) != null ? _c2 : false;
1859
+ const elementSel = (_c2 = (_b3 = (_a3 = sel == null ? void 0 : sel.data_elements) == null ? void 0 : _a3[el.uuid]) == null ? void 0 : _b3.selected) != null ? _c2 : false;
1726
1860
  initialDataElementState[combinedId] = elementSel;
1727
1861
  initialDataElementSelectionsMap[combinedId] = elementSel;
1728
1862
  });
@@ -1770,7 +1904,7 @@ var RedactoNoticeConsent = ({
1770
1904
  } finally {
1771
1905
  setIsLoading(false);
1772
1906
  }
1773
- }, [noticeId, accessToken, baseUrl, validateAgainst, includeFullyConsentedData, applicationId, onAccept, onError]);
1907
+ }, [noticeId, accessToken, baseUrl, ledgerBaseUrl, validateAgainst, includeFullyConsentedData, applicationId, onAccept, onError]);
1774
1908
  useEffect2(() => {
1775
1909
  hasBootstrappedLanguageRef.current = false;
1776
1910
  }, [noticeId, accessToken]);
@@ -2173,6 +2307,7 @@ var RedactoNoticeConsent = ({
2173
2307
  await submitConsentEvent({
2174
2308
  accessToken,
2175
2309
  baseUrl,
2310
+ ledgerBaseUrl,
2176
2311
  noticeUuid: activeConfig2.notice_uuid,
2177
2312
  purposes: activeConfig2.purposes.map((purpose) => ({
2178
2313
  ...purpose,
@@ -2200,7 +2335,7 @@ var RedactoNoticeConsent = ({
2200
2335
  } finally {
2201
2336
  setIsSubmitting(false);
2202
2337
  }
2203
- }, [content, accessToken, baseUrl, applicationId, selectedPurposes, selectedDataElements, stopAudio, onAccept, onError]);
2338
+ }, [content, accessToken, baseUrl, ledgerBaseUrl, applicationId, selectedPurposes, selectedDataElements, stopAudio, onAccept, onError]);
2204
2339
  const handleDecline = useCallback(() => {
2205
2340
  stopAudio();
2206
2341
  stopPolling();
@@ -2861,13 +2996,14 @@ var submitConsentEvent2 = async ({
2861
2996
  workspace_uuid,
2862
2997
  accessToken,
2863
2998
  baseUrl,
2999
+ ledgerBaseUrl,
2864
3000
  noticeUuid,
2865
3001
  purposes,
2866
3002
  declined,
2867
3003
  meta_data
2868
3004
  }) => {
2869
3005
  var _a, _b;
2870
- const apiBaseUrl = baseUrl || DEFAULT_CONSENT_API_BASE_URL;
3006
+ const apiBaseUrl = ledgerBaseUrl || baseUrl || DEFAULT_CONSENT_API_BASE_URL;
2871
3007
  const payload = {
2872
3008
  notice_uuid: noticeUuid,
2873
3009
  purposes: purposes.map((purpose) => {
@@ -3189,6 +3325,7 @@ var RedactoConsentInlineComponent = ({
3189
3325
  notice_uuid,
3190
3326
  accessToken,
3191
3327
  baseUrl,
3328
+ ledgerBaseUrl,
3192
3329
  language = "en",
3193
3330
  onAccept,
3194
3331
  onDecline: _onDecline,
@@ -3207,6 +3344,9 @@ var RedactoConsentInlineComponent = ({
3207
3344
  const [selectedPurposes, setSelectedPurposes] = useState2({});
3208
3345
  const [selectedDataElements, setSelectedDataElements] = useState2({});
3209
3346
  const [hasAlreadyConsented, setHasAlreadyConsented] = useState2(false);
3347
+ const [isCheckingConsent, setIsCheckingConsent] = useState2(
3348
+ Boolean(ledgerBaseUrl) && !applicationId
3349
+ );
3210
3350
  const [fetchError, setFetchError] = useState2(null);
3211
3351
  const [errorMessage, setErrorMessage] = useState2(null);
3212
3352
  const [isLanguageDropdownOpen, setIsLanguageDropdownOpen] = useState2(false);
@@ -3327,6 +3467,40 @@ var RedactoConsentInlineComponent = ({
3327
3467
  controller.abort();
3328
3468
  };
3329
3469
  }, [fetchNotice]);
3470
+ useEffect3(() => {
3471
+ if (!ledgerBaseUrl || applicationId) {
3472
+ return;
3473
+ }
3474
+ if (!accessToken || !content) {
3475
+ return;
3476
+ }
3477
+ let active = true;
3478
+ const controller = new AbortController();
3479
+ const checkLedgerConsent = async () => {
3480
+ try {
3481
+ const ledgerStatus = await fetchNoticeConsentStatusForScope({
3482
+ accessToken,
3483
+ ledgerBaseUrl,
3484
+ organisationUuid: org_uuid,
3485
+ workspaceUuid: workspace_uuid,
3486
+ noticeUuid: notice_uuid,
3487
+ signal: controller.signal
3488
+ });
3489
+ if (active && ledgerStatus && isNoticeFullyConsented(ledgerStatus)) {
3490
+ setHasAlreadyConsented(true);
3491
+ }
3492
+ } finally {
3493
+ if (active) {
3494
+ setIsCheckingConsent(false);
3495
+ }
3496
+ }
3497
+ };
3498
+ void checkLedgerConsent();
3499
+ return () => {
3500
+ active = false;
3501
+ controller.abort();
3502
+ };
3503
+ }, [ledgerBaseUrl, applicationId, accessToken, content, org_uuid, workspace_uuid, notice_uuid]);
3330
3504
  const togglePurposeCollapse = useCallback2((purposeUuid) => {
3331
3505
  setCollapsedPurposes((prev) => ({ ...prev, [purposeUuid]: !prev[purposeUuid] }));
3332
3506
  }, []);
@@ -3377,6 +3551,7 @@ var RedactoConsentInlineComponent = ({
3377
3551
  workspace_uuid,
3378
3552
  accessToken: tokenToUse,
3379
3553
  baseUrl,
3554
+ ledgerBaseUrl,
3380
3555
  noticeUuid: content.notice_uuid,
3381
3556
  purposes: content.purposes.map((purpose) => {
3382
3557
  const hasSelectedRequiredElement = purpose.data_elements.some(
@@ -3415,6 +3590,7 @@ var RedactoConsentInlineComponent = ({
3415
3590
  org_uuid,
3416
3591
  workspace_uuid,
3417
3592
  baseUrl,
3593
+ ledgerBaseUrl,
3418
3594
  selectedDataElements,
3419
3595
  selectedPurposes,
3420
3596
  applicationId,
@@ -3422,7 +3598,7 @@ var RedactoConsentInlineComponent = ({
3422
3598
  ]
3423
3599
  );
3424
3600
  useEffect3(() => {
3425
- if (accessToken && content && areAllRequiredElementsChecked && !isSubmitting && !hasSubmittedRef.current) {
3601
+ if (accessToken && content && areAllRequiredElementsChecked && !isSubmitting && !isCheckingConsent && !hasAlreadyConsented && !hasSubmittedRef.current) {
3426
3602
  hasSubmittedRef.current = true;
3427
3603
  const autoSubmit = async () => {
3428
3604
  try {
@@ -3434,7 +3610,7 @@ var RedactoConsentInlineComponent = ({
3434
3610
  };
3435
3611
  autoSubmit();
3436
3612
  }
3437
- }, [accessToken, content, areAllRequiredElementsChecked, isSubmitting, handleAcceptWithToken, onError]);
3613
+ }, [accessToken, content, areAllRequiredElementsChecked, isSubmitting, isCheckingConsent, hasAlreadyConsented, handleAcceptWithToken, onError]);
3438
3614
  useEffect3(() => {
3439
3615
  if (!accessToken) {
3440
3616
  hasSubmittedRef.current = false;