@redacto.io/consent-sdk-react 3.1.0 → 3.3.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.mjs CHANGED
@@ -3,6 +3,21 @@ 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
6
21
  var BASE_URL = "https://api.redacto.io/consent";
7
22
  var apiCache = /* @__PURE__ */ new Map();
8
23
  var CACHE_TTL = 5 * 60 * 1e3;
@@ -27,14 +42,6 @@ function decodeTokenSafely(token) {
27
42
  return null;
28
43
  }
29
44
  }
30
- var storage = {
31
- getItem: (key) => {
32
- if (typeof window !== "undefined") {
33
- return localStorage.getItem(key);
34
- }
35
- return null;
36
- }
37
- };
38
45
  var clearApiCache = () => {
39
46
  apiCache.clear();
40
47
  };
@@ -108,7 +115,6 @@ var fetchConsentContent = async ({
108
115
  }
109
116
  return data;
110
117
  } catch (error) {
111
- console.error("Error fetching consent content:", error instanceof Error ? error.message : error);
112
118
  throw error;
113
119
  }
114
120
  };
@@ -134,42 +140,62 @@ var submitConsentEvent = async ({
134
140
  if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
135
141
  throw new Error("Invalid token: missing organization or workspace UUID");
136
142
  }
137
- const primaryEmail = storage.getItem("userEmail");
138
- const validatedPurposes = purposes.map((purpose) => {
139
- if (!purpose.uuid || !purpose.name) {
140
- throw new Error(`Invalid purpose data: missing uuid or name`);
141
- }
142
- return {
143
- uuid: purpose.uuid,
144
- name: purpose.name,
145
- description: purpose.description || "",
146
- industries: purpose.industries || "",
147
- selected: Boolean(purpose.selected),
148
- data_elements: (purpose.data_elements || []).map((element) => {
149
- if (!element.uuid || !element.name) {
150
- throw new Error(`Invalid data element: missing uuid or name`);
151
- }
152
- return {
153
- uuid: element.uuid,
154
- name: element.name,
155
- enabled: Boolean(element.enabled),
156
- required: Boolean(element.required),
157
- selected: element.required ? true : Boolean(element.selected)
158
- };
159
- })
160
- };
161
- });
162
- const payload = {
163
- primary_email: primaryEmail || void 0,
164
- notice_uuid: noticeUuid,
165
- source: "WEB",
166
- declined: Boolean(declined),
167
- consents: {
168
- purposes: validatedPurposes
169
- },
170
- meta_data: meta_data ? { specific_uuid: meta_data.specific_uuid } : void 0
171
- };
172
143
  const apiBaseUrl = baseUrl || BASE_URL;
144
+ let payload;
145
+ if (isLegacyApi(apiBaseUrl)) {
146
+ const primaryEmail = typeof window !== "undefined" ? localStorage.getItem("userEmail") : null;
147
+ payload = {
148
+ primary_email: primaryEmail || void 0,
149
+ notice_uuid: noticeUuid,
150
+ source: "WEB",
151
+ declined: Boolean(declined),
152
+ consents: {
153
+ purposes: purposes.map((purpose) => {
154
+ if (!purpose.uuid) {
155
+ throw new Error(`Invalid purpose data: missing uuid`);
156
+ }
157
+ return {
158
+ uuid: purpose.uuid,
159
+ name: purpose.name,
160
+ description: purpose.description || "",
161
+ industries: purpose.industries || "",
162
+ selected: Boolean(purpose.selected),
163
+ data_elements: (purpose.data_elements || []).map((element) => ({
164
+ uuid: element.uuid,
165
+ name: element.name,
166
+ enabled: Boolean(element.enabled),
167
+ required: Boolean(element.required),
168
+ selected: element.required ? true : Boolean(element.selected)
169
+ }))
170
+ };
171
+ })
172
+ },
173
+ meta_data: meta_data ? { specific_uuid: meta_data.specific_uuid } : void 0
174
+ };
175
+ } else {
176
+ const validatedPurposes = purposes.map((purpose) => {
177
+ if (!purpose.uuid) {
178
+ throw new Error(`Invalid purpose data: missing uuid`);
179
+ }
180
+ const dataElements = (purpose.data_elements || []).filter((element) => element.enabled).map((element) => ({
181
+ uuid: element.uuid,
182
+ selected: element.required ? true : Boolean(element.selected)
183
+ }));
184
+ return {
185
+ purpose_uuid: purpose.uuid,
186
+ selected: Boolean(purpose.selected),
187
+ data_elements: dataElements.length > 0 ? dataElements : void 0
188
+ };
189
+ });
190
+ payload = {
191
+ notice_uuid: noticeUuid,
192
+ purposes: validatedPurposes,
193
+ select_all_mandatory: false,
194
+ source: "WEB",
195
+ declined: Boolean(declined),
196
+ meta_data: meta_data ? { specific_uuid: meta_data.specific_uuid } : void 0
197
+ };
198
+ }
173
199
  const response = await fetch(
174
200
  `${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/submit-consent`,
175
201
  {
@@ -202,7 +228,6 @@ var submitConsentEvent = async ({
202
228
  }
203
229
  apiCache.clear();
204
230
  } catch (error) {
205
- console.error("Error submitting consent event:", error instanceof Error ? error.message : error);
206
231
  throw error;
207
232
  }
208
233
  };
@@ -334,7 +359,6 @@ var fetchTTSAudioUrls = async ({
334
359
  const data = await response.json();
335
360
  return data;
336
361
  } catch (error) {
337
- console.error("Error fetching TTS audio URLs:", error instanceof Error ? error.message : error);
338
362
  throw error;
339
363
  }
340
364
  };
@@ -872,7 +896,8 @@ var PurposeItem = ({
872
896
  onDataElementToggle,
873
897
  getTranslatedText,
874
898
  isAlreadyConsented,
875
- selectedLanguage
899
+ selectedLanguage,
900
+ initialDataElementSelections = {}
876
901
  }) => {
877
902
  const headingStyle = useMemo(
878
903
  () => ({
@@ -1087,46 +1112,68 @@ var PurposeItem = ({
1087
1112
  )}${dataElement.required ? " (required)" : ""}`
1088
1113
  }
1089
1114
  ),
1090
- isAlreadyConsented && /* @__PURE__ */ jsx(
1091
- "div",
1092
- {
1093
- style: {
1094
- display: "flex",
1095
- alignItems: "center",
1096
- justifyContent: "center",
1097
- width: "16px",
1098
- height: "16px",
1099
- borderRadius: "50%",
1100
- backgroundColor: "#10B981"
1101
- },
1102
- "aria-label": `Already consented to ${getTranslatedText(
1103
- `data_elements.name`,
1104
- dataElement.name,
1105
- dataElement.uuid
1106
- )}`,
1107
- children: /* @__PURE__ */ jsx(
1108
- "svg",
1115
+ isAlreadyConsented && /* @__PURE__ */ jsx(Fragment, { children: (() => {
1116
+ const combinedId = `${purpose.uuid}-${dataElement.uuid}`;
1117
+ const isCurrentlySelected = selectedDataElements[combinedId] || false;
1118
+ const wasOriginallySelected = initialDataElementSelections[combinedId] || false;
1119
+ if (isCurrentlySelected && wasOriginallySelected) {
1120
+ return /* @__PURE__ */ jsx(
1121
+ "div",
1109
1122
  {
1110
- width: "10",
1111
- height: "10",
1112
- viewBox: "0 0 10 10",
1113
- fill: "none",
1114
- xmlns: "http://www.w3.org/2000/svg",
1115
- "aria-hidden": "true",
1123
+ style: {
1124
+ display: "flex",
1125
+ alignItems: "center",
1126
+ justifyContent: "center",
1127
+ width: "16px",
1128
+ height: "16px",
1129
+ borderRadius: "50%",
1130
+ backgroundColor: "#10B981"
1131
+ },
1132
+ "aria-label": `Already consented to ${getTranslatedText(
1133
+ `data_elements.name`,
1134
+ dataElement.name,
1135
+ dataElement.uuid
1136
+ )}`,
1116
1137
  children: /* @__PURE__ */ jsx(
1117
- "path",
1138
+ "svg",
1118
1139
  {
1119
- d: "M3 5L4.5 6.5L7.5 3.5",
1120
- stroke: "white",
1121
- strokeWidth: "1.5",
1122
- strokeLinecap: "round",
1123
- strokeLinejoin: "round"
1140
+ width: "10",
1141
+ height: "10",
1142
+ viewBox: "0 0 10 10",
1143
+ fill: "none",
1144
+ xmlns: "http://www.w3.org/2000/svg",
1145
+ "aria-hidden": "true",
1146
+ children: /* @__PURE__ */ jsx(
1147
+ "path",
1148
+ {
1149
+ d: "M3 5L4.5 6.5L7.5 3.5",
1150
+ stroke: "white",
1151
+ strokeWidth: "1.5",
1152
+ strokeLinecap: "round",
1153
+ strokeLinejoin: "round"
1154
+ }
1155
+ )
1124
1156
  }
1125
1157
  )
1126
1158
  }
1127
- )
1159
+ );
1160
+ } else {
1161
+ return /* @__PURE__ */ jsx(
1162
+ "input",
1163
+ {
1164
+ className: "redacto-checkbox-small",
1165
+ type: "checkbox",
1166
+ checked: isCurrentlySelected,
1167
+ onChange: () => onDataElementToggle(dataElement.uuid, purpose.uuid),
1168
+ "aria-label": `Select ${getTranslatedText(
1169
+ `data_elements.name`,
1170
+ dataElement.name,
1171
+ dataElement.uuid
1172
+ )}${dataElement.required ? " (required)" : ""}`
1173
+ }
1174
+ );
1128
1175
  }
1129
- )
1176
+ })() })
1130
1177
  ]
1131
1178
  },
1132
1179
  `${dataElement.uuid}-${selectedLanguage}`
@@ -1565,10 +1612,13 @@ var RedactoNoticeConsent = ({
1565
1612
  }
1566
1613
  const [isLoading, setIsLoading] = useState2(true);
1567
1614
  const [isSubmitting, setIsSubmitting] = useState2(false);
1615
+ const [isSubmittingAccept, setIsSubmittingAccept] = useState2(false);
1616
+ const [isSubmittingDecline, setIsSubmittingDecline] = useState2(false);
1568
1617
  const [content, setContent] = useState2(null);
1569
1618
  const [categorizedPurposes, setCategorizedPurposes] = useState2(null);
1570
1619
  const [selectedPurposes, setSelectedPurposes] = useState2({});
1571
1620
  const [selectedDataElements, setSelectedDataElements] = useState2({});
1621
+ const [initialDataElementSelections, setInitialDataElementSelections] = useState2({});
1572
1622
  const [collapsedPurposes, setCollapsedPurposes] = useState2({});
1573
1623
  const [hasAlreadyConsented, setHasAlreadyConsented] = useState2(false);
1574
1624
  const [isLanguageDropdownOpen, setIsLanguageDropdownOpen] = useState2(false);
@@ -1709,11 +1759,14 @@ var RedactoNoticeConsent = ({
1709
1759
  setCategorizedPurposes(null);
1710
1760
  setSelectedPurposes({});
1711
1761
  setSelectedDataElements({});
1762
+ setInitialDataElementSelections({});
1712
1763
  setCollapsedPurposes({});
1713
1764
  setHasAlreadyConsented(false);
1714
1765
  setErrorMessage(null);
1715
1766
  setFetchError(null);
1716
1767
  setIsLoading(true);
1768
+ setIsSubmittingAccept(false);
1769
+ setIsSubmittingDecline(false);
1717
1770
  setShowAgeVerification(false);
1718
1771
  setShowGuardianForm(false);
1719
1772
  setIsSubmittingGuardian(false);
@@ -1796,14 +1849,15 @@ var RedactoNoticeConsent = ({
1796
1849
  validate_against: validateAgainst,
1797
1850
  signal: (_a2 = abortControllerRef.current) == null ? void 0 : _a2.signal
1798
1851
  });
1799
- setContent(consentContentData.detail.active_config);
1800
- if (consentContentData.detail.active_config.default_language) {
1801
- const defaultLang = consentContentData.detail.active_config.default_language;
1852
+ const activeConfig = consentContentData.detail.active_config;
1853
+ setContent(activeConfig);
1854
+ if (activeConfig.default_language) {
1855
+ const defaultLang = activeConfig.default_language;
1802
1856
  setSelectedLanguage(
1803
1857
  defaultLang === "en" || defaultLang === "EN" ? "English" : defaultLang
1804
1858
  );
1805
1859
  }
1806
- const initialCollapsedState = consentContentData.detail.active_config.purposes.reduce(
1860
+ const initialCollapsedState = activeConfig.purposes.reduce(
1807
1861
  (acc, purpose) => ({
1808
1862
  ...acc,
1809
1863
  [purpose.uuid]: true
@@ -1814,13 +1868,13 @@ var RedactoNoticeConsent = ({
1814
1868
  const isReconsentRequired = consentContentData.detail.reconsent_required;
1815
1869
  const purposeSelections = consentContentData.detail.purpose_selections;
1816
1870
  const newCategorizedPurposes = isReconsentRequired ? {
1817
- alreadyConsented: consentContentData.detail.active_config.purposes.filter(
1871
+ alreadyConsented: activeConfig.purposes.filter(
1818
1872
  (purpose) => {
1819
1873
  const selection = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid];
1820
1874
  return selection && (selection.status === "ACTIVE" || selection.status === "EXPIRED") && !selection.needs_reconsent;
1821
1875
  }
1822
1876
  ),
1823
- needsConsent: consentContentData.detail.active_config.purposes.filter(
1877
+ needsConsent: activeConfig.purposes.filter(
1824
1878
  (purpose) => {
1825
1879
  const selection = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid];
1826
1880
  return !selection || selection.status !== "ACTIVE" || selection.needs_reconsent;
@@ -1828,7 +1882,7 @@ var RedactoNoticeConsent = ({
1828
1882
  )
1829
1883
  } : null;
1830
1884
  setCategorizedPurposes(newCategorizedPurposes);
1831
- const initialPurposeState = consentContentData.detail.active_config.purposes.reduce(
1885
+ const initialPurposeState = activeConfig.purposes.reduce(
1832
1886
  (acc, purpose) => {
1833
1887
  if (isReconsentRequired && (purposeSelections == null ? void 0 : purposeSelections[purpose.uuid])) {
1834
1888
  acc[purpose.uuid] = purposeSelections[purpose.uuid].selected;
@@ -1840,7 +1894,7 @@ var RedactoNoticeConsent = ({
1840
1894
  {}
1841
1895
  );
1842
1896
  setSelectedPurposes(initialPurposeState);
1843
- const initialDataElementState = consentContentData.detail.active_config.purposes.reduce(
1897
+ const initialDataElementState = activeConfig.purposes.reduce(
1844
1898
  (acc, purpose) => {
1845
1899
  purpose.data_elements.forEach((element) => {
1846
1900
  var _a3, _b2;
@@ -1856,6 +1910,23 @@ var RedactoNoticeConsent = ({
1856
1910
  {}
1857
1911
  );
1858
1912
  setSelectedDataElements(initialDataElementState);
1913
+ if (isReconsentRequired && newCategorizedPurposes) {
1914
+ const initialSelections = {};
1915
+ newCategorizedPurposes.alreadyConsented.forEach((purpose) => {
1916
+ purpose.data_elements.forEach((element) => {
1917
+ var _a3, _b2;
1918
+ const combinedId = `${purpose.uuid}-${element.uuid}`;
1919
+ if ((_b2 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) {
1920
+ initialSelections[combinedId] = purposeSelections[purpose.uuid].data_elements[element.uuid].selected;
1921
+ } else {
1922
+ initialSelections[combinedId] = false;
1923
+ }
1924
+ });
1925
+ });
1926
+ setInitialDataElementSelections(initialSelections);
1927
+ } else {
1928
+ setInitialDataElementSelections({});
1929
+ }
1859
1930
  if (consentContentData.detail.is_minor) {
1860
1931
  setShowAgeVerification(true);
1861
1932
  }
@@ -1864,7 +1935,6 @@ var RedactoNoticeConsent = ({
1864
1935
  if (err instanceof Error && err.name === "AbortError") {
1865
1936
  return;
1866
1937
  }
1867
- console.error(err);
1868
1938
  const error = err;
1869
1939
  setFetchError(error);
1870
1940
  if (error.status === 409) {
@@ -1956,6 +2026,7 @@ var RedactoNoticeConsent = ({
1956
2026
  const handleAccept = async () => {
1957
2027
  const submitController = new AbortController();
1958
2028
  try {
2029
+ setIsSubmittingAccept(true);
1959
2030
  setIsSubmitting(true);
1960
2031
  setErrorMessage(null);
1961
2032
  if (content) {
@@ -1963,14 +2034,31 @@ var RedactoNoticeConsent = ({
1963
2034
  accessToken,
1964
2035
  baseUrl,
1965
2036
  noticeUuid: content.notice_uuid,
1966
- purposes: content.purposes.map((purpose) => ({
1967
- ...purpose,
1968
- selected: selectedPurposes[purpose.uuid] || false,
1969
- data_elements: purpose.data_elements.map((element) => ({
1970
- ...element,
1971
- selected: element.required ? true : selectedDataElements[`${purpose.uuid}-${element.uuid}`] || false
1972
- }))
1973
- })),
2037
+ purposes: content.purposes.map((purpose) => {
2038
+ const isAlreadyConsented = (categorizedPurposes == null ? void 0 : categorizedPurposes.alreadyConsented.some(
2039
+ (p) => p.uuid === purpose.uuid
2040
+ )) || false;
2041
+ let purposeSelected = selectedPurposes[purpose.uuid] || false;
2042
+ if (isAlreadyConsented) {
2043
+ const wasModified = purpose.data_elements.some((element) => {
2044
+ const combinedId = `${purpose.uuid}-${element.uuid}`;
2045
+ const currentSelection = selectedDataElements[combinedId] || false;
2046
+ const initialSelection = initialDataElementSelections[combinedId] || false;
2047
+ return currentSelection !== initialSelection;
2048
+ });
2049
+ if (wasModified) {
2050
+ purposeSelected = true;
2051
+ }
2052
+ }
2053
+ return {
2054
+ ...purpose,
2055
+ selected: purposeSelected,
2056
+ data_elements: purpose.data_elements.map((element) => ({
2057
+ ...element,
2058
+ selected: element.required ? true : selectedDataElements[`${purpose.uuid}-${element.uuid}`] || false
2059
+ }))
2060
+ };
2061
+ }),
1974
2062
  declined: false,
1975
2063
  meta_data: applicationId ? { specific_uuid: applicationId } : void 0,
1976
2064
  signal: submitController.signal
@@ -1981,20 +2069,24 @@ var RedactoNoticeConsent = ({
1981
2069
  if (error instanceof Error && error.name === "AbortError") {
1982
2070
  return;
1983
2071
  }
1984
- console.error("Error submitting consent:", error);
1985
2072
  const err = error;
1986
- if (err.status === 500) {
1987
- setErrorMessage(
1988
- "An error occurred while submitting your consent. Please try again later."
1989
- );
1990
- }
2073
+ const message = err.status === 500 ? "An error occurred while submitting your consent. Please try again later." : err.message || "Failed to submit consent. Please try again.";
2074
+ setErrorMessage(message);
1991
2075
  onError == null ? void 0 : onError(error);
1992
2076
  } finally {
2077
+ setIsSubmittingAccept(false);
1993
2078
  setIsSubmitting(false);
1994
2079
  }
1995
2080
  };
1996
2081
  const handleDecline = useCallback(async () => {
1997
- onDecline == null ? void 0 : onDecline();
2082
+ try {
2083
+ setIsSubmittingDecline(true);
2084
+ setIsSubmitting(true);
2085
+ onDecline == null ? void 0 : onDecline();
2086
+ } finally {
2087
+ setIsSubmittingDecline(false);
2088
+ setIsSubmitting(false);
2089
+ }
1998
2090
  }, [onDecline]);
1999
2091
  const handleGuardianFormChange = useCallback(
2000
2092
  (field, value) => {
@@ -2361,7 +2453,6 @@ var RedactoNoticeConsent = ({
2361
2453
  setIsTTSAvailable(true);
2362
2454
  }).catch((error) => {
2363
2455
  if (error instanceof Error && error.name !== "AbortError") {
2364
- console.warn("Failed to fetch TTS audio URLs:", error.message);
2365
2456
  setIsTTSAvailable(false);
2366
2457
  setTtsAudioUrls(null);
2367
2458
  }
@@ -2968,7 +3059,8 @@ var RedactoNoticeConsent = ({
2968
3059
  onDataElementToggle: handleDataElementCheckboxChange,
2969
3060
  getTranslatedText,
2970
3061
  isAlreadyConsented: true,
2971
- selectedLanguage
3062
+ selectedLanguage,
3063
+ initialDataElementSelections
2972
3064
  },
2973
3065
  `${purpose.uuid}-${selectedLanguage}`
2974
3066
  )),
@@ -3038,12 +3130,12 @@ var RedactoNoticeConsent = ({
3038
3130
  opacity: acceptDisabled ? 0.5 : 1
3039
3131
  },
3040
3132
  onClick: handleAccept,
3041
- disabled: acceptDisabled,
3133
+ disabled: acceptDisabled || isSubmittingDecline,
3042
3134
  "aria-label": getTranslatedText(
3043
3135
  "confirm_button_text",
3044
3136
  (content == null ? void 0 : content.confirm_button_text) || "Accept"
3045
3137
  ),
3046
- children: isSubmitting ? "Processing..." : getTranslatedText(
3138
+ children: isSubmittingAccept ? "Processing..." : getTranslatedText(
3047
3139
  "confirm_button_text",
3048
3140
  (content == null ? void 0 : content.confirm_button_text) || "Accept"
3049
3141
  )
@@ -3057,15 +3149,16 @@ var RedactoNoticeConsent = ({
3057
3149
  ...styles.button,
3058
3150
  ...responsiveStyles.button,
3059
3151
  ...styles.cancelButton,
3060
- ...declineButtonStyle
3152
+ ...declineButtonStyle,
3153
+ opacity: isSubmittingAccept ? 0.5 : 1
3061
3154
  },
3062
3155
  onClick: handleDecline,
3063
- disabled: isSubmitting,
3156
+ disabled: isSubmittingDecline || isSubmittingAccept,
3064
3157
  "aria-label": getTranslatedText(
3065
3158
  "decline_button_text",
3066
3159
  (content == null ? void 0 : content.decline_button_text) || "Decline"
3067
3160
  ),
3068
- children: isSubmitting ? "Processing..." : getTranslatedText(
3161
+ children: isSubmittingDecline ? "Processing..." : getTranslatedText(
3069
3162
  "decline_button_text",
3070
3163
  (content == null ? void 0 : content.decline_button_text) || "Decline"
3071
3164
  )
@@ -3125,7 +3218,6 @@ var fetchConsentContent2 = async ({
3125
3218
  const data = await response.json();
3126
3219
  return data;
3127
3220
  } catch (error) {
3128
- console.error("Error fetching consent content:", error);
3129
3221
  throw error;
3130
3222
  }
3131
3223
  };
@@ -3141,31 +3233,61 @@ var submitConsentEvent2 = async ({
3141
3233
  }) => {
3142
3234
  var _a, _b;
3143
3235
  try {
3144
- const primaryEmail = localStorage.getItem("userEmail");
3145
- const payload = {
3146
- primary_email: primaryEmail || void 0,
3147
- notice_uuid: noticeUuid,
3148
- source: "WEB",
3149
- declined,
3150
- consents: {
3151
- purposes: purposes.map((purpose) => ({
3152
- uuid: purpose.uuid,
3153
- name: purpose.name,
3154
- description: purpose.description,
3155
- industries: purpose.industries || "",
3156
- selected: purpose.selected,
3157
- data_elements: purpose.data_elements.map((element) => ({
3158
- uuid: element.uuid,
3159
- name: element.name,
3160
- enabled: element.enabled,
3161
- required: element.required,
3162
- selected: element.required ? true : element.selected
3163
- }))
3164
- }))
3165
- },
3166
- meta_data
3167
- };
3168
3236
  const apiBaseUrl = baseUrl || BASE_URL2;
3237
+ let payload;
3238
+ if (isLegacyApi(apiBaseUrl)) {
3239
+ const primaryEmail = typeof window !== "undefined" ? localStorage.getItem("userEmail") : null;
3240
+ payload = {
3241
+ primary_email: primaryEmail || void 0,
3242
+ notice_uuid: noticeUuid,
3243
+ source: "WEB",
3244
+ declined: Boolean(declined),
3245
+ consents: {
3246
+ purposes: purposes.map((purpose) => {
3247
+ if (!purpose.uuid) {
3248
+ throw new Error(`Invalid purpose data: missing uuid`);
3249
+ }
3250
+ return {
3251
+ uuid: purpose.uuid,
3252
+ name: purpose.name,
3253
+ description: purpose.description || "",
3254
+ industries: purpose.industries || "",
3255
+ selected: Boolean(purpose.selected),
3256
+ data_elements: (purpose.data_elements || []).map((element) => ({
3257
+ uuid: element.uuid,
3258
+ name: element.name,
3259
+ enabled: Boolean(element.enabled),
3260
+ required: Boolean(element.required),
3261
+ selected: element.required ? true : Boolean(element.selected)
3262
+ }))
3263
+ };
3264
+ })
3265
+ },
3266
+ meta_data: meta_data ? { specific_uuid: meta_data.specific_uuid } : void 0
3267
+ };
3268
+ } else {
3269
+ payload = {
3270
+ notice_uuid: noticeUuid,
3271
+ purposes: purposes.map((purpose) => {
3272
+ if (!purpose.uuid) {
3273
+ throw new Error(`Invalid purpose data: missing uuid`);
3274
+ }
3275
+ const dataElements = purpose.data_elements.filter((element) => element.enabled).map((element) => ({
3276
+ uuid: element.uuid,
3277
+ selected: element.required ? true : Boolean(element.selected)
3278
+ }));
3279
+ return {
3280
+ purpose_uuid: purpose.uuid,
3281
+ selected: Boolean(purpose.selected),
3282
+ data_elements: dataElements.length > 0 ? dataElements : void 0
3283
+ };
3284
+ }),
3285
+ select_all_mandatory: false,
3286
+ source: "WEB",
3287
+ declined,
3288
+ meta_data
3289
+ };
3290
+ }
3169
3291
  const response = await fetch(
3170
3292
  `${apiBaseUrl}/public/organisations/${org_uuid}/workspaces/${workspace_uuid}/submit-consent`,
3171
3293
  {
@@ -3202,7 +3324,6 @@ var submitConsentEvent2 = async ({
3202
3324
  throw error;
3203
3325
  }
3204
3326
  } catch (error) {
3205
- console.error("Error submitting consent event:", error);
3206
3327
  throw error;
3207
3328
  }
3208
3329
  };
@@ -3720,13 +3841,12 @@ var RedactoConsentInlineComponent = ({
3720
3841
  language,
3721
3842
  specific_uuid: applicationId
3722
3843
  });
3723
- setContent(consentContentData.detail.active_config);
3724
- if (consentContentData.detail.active_config.default_language) {
3725
- setSelectedLanguage(
3726
- consentContentData.detail.active_config.default_language
3727
- );
3844
+ const activeConfig = consentContentData.detail.active_config;
3845
+ setContent(activeConfig);
3846
+ if (activeConfig.default_language) {
3847
+ setSelectedLanguage(activeConfig.default_language);
3728
3848
  }
3729
- const initialCollapsedState = consentContentData.detail.active_config.purposes.reduce(
3849
+ const initialCollapsedState = activeConfig.purposes.reduce(
3730
3850
  (acc, purpose) => ({
3731
3851
  ...acc,
3732
3852
  [purpose.uuid]: true
@@ -3734,7 +3854,7 @@ var RedactoConsentInlineComponent = ({
3734
3854
  {}
3735
3855
  );
3736
3856
  setCollapsedPurposes(initialCollapsedState);
3737
- const initialDataElementState = consentContentData.detail.active_config.purposes.reduce(
3857
+ const initialDataElementState = activeConfig.purposes.reduce(
3738
3858
  (acc, purpose) => {
3739
3859
  purpose.data_elements.forEach((element) => {
3740
3860
  const combinedId = `${purpose.uuid}-${element.uuid}`;
@@ -3745,7 +3865,7 @@ var RedactoConsentInlineComponent = ({
3745
3865
  {}
3746
3866
  );
3747
3867
  setSelectedDataElements(initialDataElementState);
3748
- const initialPurposeState = consentContentData.detail.active_config.purposes.reduce(
3868
+ const initialPurposeState = activeConfig.purposes.reduce(
3749
3869
  (acc, purpose) => {
3750
3870
  return {
3751
3871
  ...acc,
@@ -3756,7 +3876,6 @@ var RedactoConsentInlineComponent = ({
3756
3876
  );
3757
3877
  setSelectedPurposes(initialPurposeState);
3758
3878
  } catch (err) {
3759
- console.error(err);
3760
3879
  const error = err;
3761
3880
  setFetchError(error);
3762
3881
  if (error.status === 409) {
@@ -3871,13 +3990,9 @@ var RedactoConsentInlineComponent = ({
3871
3990
  onAccept == null ? void 0 : onAccept();
3872
3991
  hasSubmittedRef.current = false;
3873
3992
  } catch (error) {
3874
- console.error("Error submitting consent:", error);
3875
3993
  const err = error;
3876
- if (err.status === 500) {
3877
- setErrorMessage(
3878
- "An error occurred while submitting your consent. Please try again later."
3879
- );
3880
- }
3994
+ const message = err.status === 500 ? "An error occurred while submitting your consent. Please try again later." : err.message || "Failed to submit consent. Please try again.";
3995
+ setErrorMessage(message);
3881
3996
  hasSubmittedRef.current = false;
3882
3997
  throw error;
3883
3998
  } finally {
@@ -3902,7 +4017,6 @@ var RedactoConsentInlineComponent = ({
3902
4017
  try {
3903
4018
  await handleAcceptWithToken(accessToken);
3904
4019
  } catch (err) {
3905
- console.error("Failed to auto-submit consent:", err);
3906
4020
  hasSubmittedRef.current = false;
3907
4021
  onError == null ? void 0 : onError(err);
3908
4022
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redacto.io/consent-sdk-react",
3
- "version": "3.1.0",
3
+ "version": "3.3.0",
4
4
  "main": "dist/index.cjs",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",