@tantainnovative/ndpr-toolkit 1.0.5 → 1.0.7

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.
Files changed (263) hide show
  1. package/README.md +88 -14
  2. package/dist/components/breach-notification/BreachNotificationForm.d.ts +18 -0
  3. package/dist/components/breach-notification/BreachNotificationForm.d.ts.map +1 -0
  4. package/dist/components/consent/ConsentBanner.d.ts +30 -0
  5. package/dist/components/consent/ConsentBanner.d.ts.map +1 -0
  6. package/dist/components/consent/ConsentManager.d.ts +51 -0
  7. package/dist/components/consent/ConsentManager.d.ts.map +1 -0
  8. package/dist/components/consent/ConsentSettings.d.ts +15 -0
  9. package/dist/components/consent/ConsentSettings.d.ts.map +1 -0
  10. package/dist/components/consent/unstyled/UnstyledConsentBanner.d.ts +7 -0
  11. package/dist/components/consent/unstyled/UnstyledConsentBanner.d.ts.map +1 -0
  12. package/dist/components/consent/unstyled/UnstyledConsentSettings.d.ts +7 -0
  13. package/dist/components/consent/unstyled/UnstyledConsentSettings.d.ts.map +1 -0
  14. package/dist/components/consent/unstyled/UnstyledConsentToggle.d.ts +8 -0
  15. package/dist/components/consent/unstyled/UnstyledConsentToggle.d.ts.map +1 -0
  16. package/dist/components/consent/unstyled/index.d.ts +4 -0
  17. package/dist/components/consent/unstyled/index.d.ts.map +1 -0
  18. package/dist/components/data-subject-rights/DataSubjectRequestForm.d.ts +14 -0
  19. package/dist/components/data-subject-rights/DataSubjectRequestForm.d.ts.map +1 -0
  20. package/dist/components/docs/DocLayout.d.ts +9 -0
  21. package/dist/components/docs/DocLayout.d.ts.map +1 -0
  22. package/dist/components/docs/index.d.ts +2 -0
  23. package/dist/components/docs/index.d.ts.map +1 -0
  24. package/dist/components/dpia/DPIAQuestionnaire.d.ts +9 -0
  25. package/dist/components/dpia/DPIAQuestionnaire.d.ts.map +1 -0
  26. package/dist/components/privacy-policy/PolicyGenerator.d.ts +12 -0
  27. package/dist/components/privacy-policy/PolicyGenerator.d.ts.map +1 -0
  28. package/dist/components/privacy-policy/data.d.ts +8 -0
  29. package/dist/components/privacy-policy/data.d.ts.map +1 -0
  30. package/dist/components/privacy-policy/shared/CheckboxField.d.ts +13 -0
  31. package/dist/components/privacy-policy/shared/CheckboxField.d.ts.map +1 -0
  32. package/dist/components/privacy-policy/shared/CheckboxGroup.d.ts +13 -0
  33. package/dist/components/privacy-policy/shared/CheckboxGroup.d.ts.map +1 -0
  34. package/dist/components/privacy-policy/shared/FormField.d.ts +13 -0
  35. package/dist/components/privacy-policy/shared/FormField.d.ts.map +1 -0
  36. package/dist/components/privacy-policy/shared/StepIndicator.d.ts +8 -0
  37. package/dist/components/privacy-policy/shared/StepIndicator.d.ts.map +1 -0
  38. package/dist/components/privacy-policy/steps/CustomSectionsStep.d.ts +15 -0
  39. package/dist/components/privacy-policy/steps/CustomSectionsStep.d.ts.map +1 -0
  40. package/dist/components/privacy-policy/steps/DataCollectionStep.d.ts +20 -0
  41. package/dist/components/privacy-policy/steps/DataCollectionStep.d.ts.map +1 -0
  42. package/dist/components/privacy-policy/steps/DataSharingStep.d.ts +34 -0
  43. package/dist/components/privacy-policy/steps/DataSharingStep.d.ts.map +1 -0
  44. package/dist/components/privacy-policy/steps/OrganizationInfoStep.d.ts +17 -0
  45. package/dist/components/privacy-policy/steps/OrganizationInfoStep.d.ts.map +1 -0
  46. package/dist/components/privacy-policy/steps/PolicyPreviewStep.d.ts +30 -0
  47. package/dist/components/privacy-policy/steps/PolicyPreviewStep.d.ts.map +1 -0
  48. package/dist/components/ui/Badge.d.ts +10 -0
  49. package/dist/components/ui/Badge.d.ts.map +1 -0
  50. package/dist/components/ui/Button.d.ts +11 -0
  51. package/dist/components/ui/Button.d.ts.map +1 -0
  52. package/dist/components/ui/Card.d.ts +10 -0
  53. package/dist/components/ui/Card.d.ts.map +1 -0
  54. package/dist/components/ui/Checkbox.d.ts +8 -0
  55. package/dist/components/ui/Checkbox.d.ts.map +1 -0
  56. package/dist/components/ui/FormField.d.ts +11 -0
  57. package/dist/components/ui/FormField.d.ts.map +1 -0
  58. package/dist/components/ui/Input.d.ts +6 -0
  59. package/dist/components/ui/Input.d.ts.map +1 -0
  60. package/dist/components/ui/Select.d.ts +6 -0
  61. package/dist/components/ui/Select.d.ts.map +1 -0
  62. package/dist/components/ui/TextArea.d.ts +6 -0
  63. package/dist/components/ui/TextArea.d.ts.map +1 -0
  64. package/dist/components/ui/dialog.d.ts +18 -0
  65. package/dist/components/ui/dialog.d.ts.map +1 -0
  66. package/dist/components/ui/label.d.ts +5 -0
  67. package/dist/components/ui/label.d.ts.map +1 -0
  68. package/dist/components/ui/switch.d.ts +5 -0
  69. package/dist/components/ui/switch.d.ts.map +1 -0
  70. package/dist/components/ui/tabs.d.ts +8 -0
  71. package/dist/components/ui/tabs.d.ts.map +1 -0
  72. package/dist/contexts/ConsentContext.d.ts +35 -0
  73. package/dist/contexts/ConsentContext.d.ts.map +1 -0
  74. package/dist/contexts/GenericConsentContext.d.ts +11 -0
  75. package/dist/contexts/GenericConsentContext.d.ts.map +1 -0
  76. package/dist/hooks/useConsent.d.ts +12 -0
  77. package/dist/hooks/useConsent.d.ts.map +1 -0
  78. package/dist/hooks/useConsentActions.d.ts +12 -0
  79. package/dist/hooks/useConsentActions.d.ts.map +1 -0
  80. package/dist/hooks/useConsentManager.d.ts +14 -0
  81. package/dist/hooks/useConsentManager.d.ts.map +1 -0
  82. package/dist/hooks/useConsentState.d.ts +10 -0
  83. package/dist/hooks/useConsentState.d.ts.map +1 -0
  84. package/dist/index.d.mts +256 -0
  85. package/dist/index.d.ts +24 -0
  86. package/dist/index.d.ts.map +1 -0
  87. package/dist/index.js +2 -0
  88. package/dist/index.js.map +1 -0
  89. package/dist/index.mjs +2 -0
  90. package/dist/index.mjs.map +1 -0
  91. package/dist/lib/consentService.d.ts +11 -0
  92. package/dist/lib/consentService.d.ts.map +1 -0
  93. package/dist/lib/dpiaQuestions.d.ts +3 -0
  94. package/dist/lib/dpiaQuestions.d.ts.map +1 -0
  95. package/dist/lib/requestService.d.ts +10 -0
  96. package/dist/lib/requestService.d.ts.map +1 -0
  97. package/dist/lib/utils.d.ts +3 -0
  98. package/dist/lib/utils.d.ts.map +1 -0
  99. package/dist/styles.css +38 -0
  100. package/dist/types/consent.d.ts +57 -0
  101. package/dist/types/consent.d.ts.map +1 -0
  102. package/dist/types/index.d.ts +91 -0
  103. package/dist/types/index.d.ts.map +1 -0
  104. package/dist/unstyled.d.mts +22 -0
  105. package/dist/unstyled.d.ts +2 -0
  106. package/dist/unstyled.d.ts.map +1 -0
  107. package/dist/unstyled.js +2 -0
  108. package/dist/unstyled.js.map +1 -0
  109. package/dist/unstyled.mjs +2 -0
  110. package/dist/unstyled.mjs.map +1 -0
  111. package/package.json +33 -5
  112. package/CHANGELOG.md +0 -16
  113. package/CNAME +0 -1
  114. package/CONTRIBUTING.md +0 -87
  115. package/RELEASE-NOTES-v1.0.0.md +0 -140
  116. package/RELEASE-NOTES-v1.0.1.md +0 -69
  117. package/SECURITY.md +0 -21
  118. package/components.json +0 -21
  119. package/eslint.config.mjs +0 -16
  120. package/next-env.d.ts +0 -5
  121. package/next.config.js +0 -15
  122. package/next.config.ts +0 -62
  123. package/packages/ndpr-toolkit/README.md +0 -467
  124. package/packages/ndpr-toolkit/dist/components/breach/BreachNotificationManager.d.ts +0 -62
  125. package/packages/ndpr-toolkit/dist/components/breach/BreachReportForm.d.ts +0 -66
  126. package/packages/ndpr-toolkit/dist/components/breach/BreachRiskAssessment.d.ts +0 -50
  127. package/packages/ndpr-toolkit/dist/components/breach/RegulatoryReportGenerator.d.ts +0 -94
  128. package/packages/ndpr-toolkit/dist/components/consent/ConsentBanner.d.ts +0 -79
  129. package/packages/ndpr-toolkit/dist/components/consent/ConsentManager.d.ts +0 -73
  130. package/packages/ndpr-toolkit/dist/components/consent/ConsentStorage.d.ts +0 -41
  131. package/packages/ndpr-toolkit/dist/components/dpia/DPIAQuestionnaire.d.ts +0 -70
  132. package/packages/ndpr-toolkit/dist/components/dpia/DPIAReport.d.ts +0 -40
  133. package/packages/ndpr-toolkit/dist/components/dpia/StepIndicator.d.ts +0 -64
  134. package/packages/ndpr-toolkit/dist/components/dsr/DSRDashboard.d.ts +0 -58
  135. package/packages/ndpr-toolkit/dist/components/dsr/DSRRequestForm.d.ts +0 -74
  136. package/packages/ndpr-toolkit/dist/components/dsr/DSRTracker.d.ts +0 -56
  137. package/packages/ndpr-toolkit/dist/components/policy/PolicyExporter.d.ts +0 -65
  138. package/packages/ndpr-toolkit/dist/components/policy/PolicyGenerator.d.ts +0 -54
  139. package/packages/ndpr-toolkit/dist/components/policy/PolicyPreview.d.ts +0 -71
  140. package/packages/ndpr-toolkit/dist/hooks/useBreach.d.ts +0 -97
  141. package/packages/ndpr-toolkit/dist/hooks/useConsent.d.ts +0 -63
  142. package/packages/ndpr-toolkit/dist/hooks/useDPIA.d.ts +0 -92
  143. package/packages/ndpr-toolkit/dist/hooks/useDSR.d.ts +0 -72
  144. package/packages/ndpr-toolkit/dist/hooks/usePrivacyPolicy.d.ts +0 -87
  145. package/packages/ndpr-toolkit/dist/index.d.ts +0 -31
  146. package/packages/ndpr-toolkit/dist/index.esm.js +0 -2
  147. package/packages/ndpr-toolkit/dist/index.esm.js.map +0 -1
  148. package/packages/ndpr-toolkit/dist/index.js +0 -2
  149. package/packages/ndpr-toolkit/dist/index.js.map +0 -1
  150. package/packages/ndpr-toolkit/dist/setupTests.d.ts +0 -2
  151. package/packages/ndpr-toolkit/dist/types/breach.d.ts +0 -239
  152. package/packages/ndpr-toolkit/dist/types/consent.d.ts +0 -95
  153. package/packages/ndpr-toolkit/dist/types/dpia.d.ts +0 -196
  154. package/packages/ndpr-toolkit/dist/types/dsr.d.ts +0 -162
  155. package/packages/ndpr-toolkit/dist/types/privacy.d.ts +0 -204
  156. package/packages/ndpr-toolkit/dist/utils/breach.d.ts +0 -14
  157. package/packages/ndpr-toolkit/dist/utils/consent.d.ts +0 -10
  158. package/packages/ndpr-toolkit/dist/utils/dpia.d.ts +0 -12
  159. package/packages/ndpr-toolkit/dist/utils/dsr.d.ts +0 -11
  160. package/packages/ndpr-toolkit/dist/utils/privacy.d.ts +0 -12
  161. package/packages/ndpr-toolkit/package-lock.json +0 -8197
  162. package/packages/ndpr-toolkit/package.json +0 -71
  163. package/packages/ndpr-toolkit/rollup.config.js +0 -34
  164. package/packages/ndpr-toolkit/src/components/breach/BreachNotificationManager.tsx +0 -701
  165. package/packages/ndpr-toolkit/src/components/breach/BreachReportForm.tsx +0 -631
  166. package/packages/ndpr-toolkit/src/components/breach/BreachRiskAssessment.tsx +0 -569
  167. package/packages/ndpr-toolkit/src/components/breach/RegulatoryReportGenerator.tsx +0 -496
  168. package/packages/ndpr-toolkit/src/components/consent/ConsentBanner.tsx +0 -270
  169. package/packages/ndpr-toolkit/src/components/consent/ConsentManager.tsx +0 -217
  170. package/packages/ndpr-toolkit/src/components/consent/ConsentStorage.tsx +0 -206
  171. package/packages/ndpr-toolkit/src/components/dpia/DPIAQuestionnaire.tsx +0 -342
  172. package/packages/ndpr-toolkit/src/components/dpia/DPIAReport.tsx +0 -373
  173. package/packages/ndpr-toolkit/src/components/dpia/StepIndicator.tsx +0 -174
  174. package/packages/ndpr-toolkit/src/components/dsr/DSRDashboard.tsx +0 -717
  175. package/packages/ndpr-toolkit/src/components/dsr/DSRRequestForm.tsx +0 -476
  176. package/packages/ndpr-toolkit/src/components/dsr/DSRTracker.tsx +0 -620
  177. package/packages/ndpr-toolkit/src/components/policy/PolicyExporter.tsx +0 -541
  178. package/packages/ndpr-toolkit/src/components/policy/PolicyGenerator.tsx +0 -454
  179. package/packages/ndpr-toolkit/src/components/policy/PolicyPreview.tsx +0 -333
  180. package/packages/ndpr-toolkit/src/hooks/useBreach.ts +0 -409
  181. package/packages/ndpr-toolkit/src/hooks/useConsent.ts +0 -263
  182. package/packages/ndpr-toolkit/src/hooks/useDPIA.ts +0 -457
  183. package/packages/ndpr-toolkit/src/hooks/useDSR.ts +0 -236
  184. package/packages/ndpr-toolkit/src/hooks/usePrivacyPolicy.ts +0 -428
  185. package/packages/ndpr-toolkit/src/index.ts +0 -44
  186. package/packages/ndpr-toolkit/src/setupTests.ts +0 -5
  187. package/packages/ndpr-toolkit/src/types/breach.ts +0 -283
  188. package/packages/ndpr-toolkit/src/types/consent.ts +0 -111
  189. package/packages/ndpr-toolkit/src/types/dpia.ts +0 -236
  190. package/packages/ndpr-toolkit/src/types/dsr.ts +0 -192
  191. package/packages/ndpr-toolkit/src/types/index.ts +0 -42
  192. package/packages/ndpr-toolkit/src/types/privacy.ts +0 -246
  193. package/packages/ndpr-toolkit/src/utils/breach.ts +0 -122
  194. package/packages/ndpr-toolkit/src/utils/consent.ts +0 -51
  195. package/packages/ndpr-toolkit/src/utils/dpia.ts +0 -104
  196. package/packages/ndpr-toolkit/src/utils/dsr.ts +0 -77
  197. package/packages/ndpr-toolkit/src/utils/privacy.ts +0 -100
  198. package/packages/ndpr-toolkit/tsconfig.json +0 -23
  199. package/postcss.config.mjs +0 -5
  200. package/public/NDPR TOOLKIT.svg +0 -1
  201. package/public/favicon/android-chrome-192x192.png +0 -0
  202. package/public/favicon/android-chrome-512x512.png +0 -0
  203. package/public/favicon/apple-touch-icon.png +0 -0
  204. package/public/favicon/favicon-16x16.png +0 -0
  205. package/public/favicon/favicon-32x32.png +0 -0
  206. package/public/favicon/site.webmanifest +0 -1
  207. package/public/file.svg +0 -1
  208. package/public/globe.svg +0 -1
  209. package/public/ndpr-toolkit-logo.svg +0 -108
  210. package/public/next.svg +0 -1
  211. package/public/vercel.svg +0 -1
  212. package/public/window.svg +0 -1
  213. package/src/app/accessibility.css +0 -70
  214. package/src/app/favicon.ico +0 -0
  215. package/src/app/globals.css +0 -123
  216. package/src/app/layout.tsx +0 -37
  217. package/src/app/ndpr-demos/breach/page.tsx +0 -354
  218. package/src/app/ndpr-demos/consent/page.tsx +0 -366
  219. package/src/app/ndpr-demos/dpia/page.tsx +0 -495
  220. package/src/app/ndpr-demos/dsr/page.tsx +0 -280
  221. package/src/app/ndpr-demos/page.tsx +0 -73
  222. package/src/app/ndpr-demos/policy/page.tsx +0 -771
  223. package/src/app/page.tsx +0 -452
  224. package/src/components/ErrorBoundary.tsx +0 -90
  225. package/src/components/breach-notification/BreachNotificationForm.tsx +0 -479
  226. package/src/components/consent/ConsentBanner.tsx +0 -193
  227. package/src/components/data-subject-rights/DataSubjectRequestForm.tsx +0 -530
  228. package/src/components/dpia/DPIAQuestionnaire.tsx +0 -523
  229. package/src/components/privacy-policy/PolicyGenerator.tsx +0 -1062
  230. package/src/components/privacy-policy/data.ts +0 -98
  231. package/src/components/privacy-policy/shared/CheckboxField.tsx +0 -38
  232. package/src/components/privacy-policy/shared/CheckboxGroup.tsx +0 -85
  233. package/src/components/privacy-policy/shared/FormField.tsx +0 -79
  234. package/src/components/privacy-policy/shared/StepIndicator.tsx +0 -86
  235. package/src/components/privacy-policy/steps/CustomSectionsStep.tsx +0 -361
  236. package/src/components/privacy-policy/steps/DataCollectionStep.tsx +0 -231
  237. package/src/components/privacy-policy/steps/DataSharingStep.tsx +0 -418
  238. package/src/components/privacy-policy/steps/OrganizationInfoStep.tsx +0 -202
  239. package/src/components/privacy-policy/steps/PolicyPreviewStep.tsx +0 -226
  240. package/src/components/ui/Badge.tsx +0 -46
  241. package/src/components/ui/Button.tsx +0 -59
  242. package/src/components/ui/Card.tsx +0 -92
  243. package/src/components/ui/Checkbox.tsx +0 -57
  244. package/src/components/ui/FormField.tsx +0 -50
  245. package/src/components/ui/Input.tsx +0 -38
  246. package/src/components/ui/Loading.tsx +0 -201
  247. package/src/components/ui/Select.tsx +0 -42
  248. package/src/components/ui/TextArea.tsx +0 -38
  249. package/src/components/ui/label.tsx +0 -24
  250. package/src/components/ui/switch.tsx +0 -31
  251. package/src/components/ui/tabs.tsx +0 -66
  252. package/src/hooks/useConsent.ts +0 -70
  253. package/src/hooks/useLoadingState.ts +0 -85
  254. package/src/lib/consentService.ts +0 -144
  255. package/src/lib/dpiaQuestions.ts +0 -188
  256. package/src/lib/requestService.ts +0 -79
  257. package/src/lib/sanitize.ts +0 -108
  258. package/src/lib/storage.ts +0 -222
  259. package/src/lib/utils.ts +0 -6
  260. package/src/types/html-to-docx.d.ts +0 -30
  261. package/src/types/index.ts +0 -77
  262. package/tailwind.config.ts +0 -65
  263. package/tsconfig.json +0 -41
@@ -1,457 +0,0 @@
1
- import { useState, useEffect } from 'react';
2
- import { DPIAQuestion, DPIASection, DPIAResult, DPIARisk } from '../types/dpia';
3
- import { assessDPIARisk } from '../utils/dpia';
4
-
5
- interface UseDPIAOptions {
6
- /**
7
- * Sections of the DPIA questionnaire
8
- */
9
- sections: DPIASection[];
10
-
11
- /**
12
- * Initial answers (if resuming a DPIA)
13
- */
14
- initialAnswers?: Record<string, any>;
15
-
16
- /**
17
- * Storage key for DPIA data
18
- * @default "ndpr_dpia_data"
19
- */
20
- storageKey?: string;
21
-
22
- /**
23
- * Whether to use local storage to persist DPIA data
24
- * @default true
25
- */
26
- useLocalStorage?: boolean;
27
-
28
- /**
29
- * Callback function called when the DPIA is completed
30
- */
31
- onComplete?: (result: DPIAResult) => void;
32
- }
33
-
34
- interface UseDPIAReturn {
35
- /**
36
- * Current section index
37
- */
38
- currentSectionIndex: number;
39
-
40
- /**
41
- * Current section
42
- */
43
- currentSection: DPIASection | null;
44
-
45
- /**
46
- * All answers
47
- */
48
- answers: Record<string, any>;
49
-
50
- /**
51
- * Update an answer
52
- */
53
- updateAnswer: (questionId: string, value: any) => void;
54
-
55
- /**
56
- * Go to the next section
57
- */
58
- nextSection: () => boolean;
59
-
60
- /**
61
- * Go to the previous section
62
- */
63
- prevSection: () => boolean;
64
-
65
- /**
66
- * Go to a specific section
67
- */
68
- goToSection: (index: number) => boolean;
69
-
70
- /**
71
- * Check if the current section is valid
72
- */
73
- isCurrentSectionValid: () => boolean;
74
-
75
- /**
76
- * Get validation errors for the current section
77
- */
78
- getCurrentSectionErrors: () => Record<string, string>;
79
-
80
- /**
81
- * Check if the DPIA is complete
82
- */
83
- isComplete: () => boolean;
84
-
85
- /**
86
- * Complete the DPIA and generate a result
87
- */
88
- completeDPIA: (assessorInfo: { name: string; role: string; email: string; }, title: string, processingDescription: string) => DPIAResult;
89
-
90
- /**
91
- * Get the visible questions for the current section
92
- */
93
- getVisibleQuestions: () => DPIAQuestion[];
94
-
95
- /**
96
- * Reset the DPIA
97
- */
98
- resetDPIA: () => void;
99
-
100
- /**
101
- * Progress percentage
102
- */
103
- progress: number;
104
- }
105
-
106
- /**
107
- * Hook for conducting Data Protection Impact Assessments in compliance with NDPR
108
- */
109
- export function useDPIA({
110
- sections,
111
- initialAnswers = {},
112
- storageKey = "ndpr_dpia_data",
113
- useLocalStorage = true,
114
- onComplete
115
- }: UseDPIAOptions): UseDPIAReturn {
116
- const [currentSectionIndex, setCurrentSectionIndex] = useState<number>(0);
117
- const [answers, setAnswers] = useState<Record<string, any>>(initialAnswers);
118
-
119
- // Load DPIA data from storage on mount
120
- useEffect(() => {
121
- if (useLocalStorage && typeof window !== 'undefined') {
122
- try {
123
- const savedData = localStorage.getItem(storageKey);
124
- if (savedData) {
125
- const { answers: savedAnswers, sectionIndex } = JSON.parse(savedData);
126
- setAnswers(savedAnswers || {});
127
- setCurrentSectionIndex(sectionIndex || 0);
128
- }
129
- } catch (error) {
130
- console.error('Error loading DPIA data:', error);
131
- }
132
- }
133
- }, [storageKey, useLocalStorage]);
134
-
135
- // Save DPIA data to storage when it changes
136
- useEffect(() => {
137
- if (useLocalStorage && typeof window !== 'undefined') {
138
- try {
139
- localStorage.setItem(storageKey, JSON.stringify({
140
- answers,
141
- sectionIndex: currentSectionIndex
142
- }));
143
- } catch (error) {
144
- console.error('Error saving DPIA data:', error);
145
- }
146
- }
147
- }, [answers, currentSectionIndex, storageKey, useLocalStorage]);
148
-
149
- // Get the current section
150
- const currentSection = sections[currentSectionIndex] || null;
151
-
152
- // Update an answer
153
- const updateAnswer = (questionId: string, value: any) => {
154
- setAnswers(prevAnswers => ({
155
- ...prevAnswers,
156
- [questionId]: value
157
- }));
158
- };
159
-
160
- // Check if a question should be shown based on its conditions
161
- const shouldShowQuestion = (question: DPIAQuestion): boolean => {
162
- if (!question.showWhen) {
163
- return true;
164
- }
165
-
166
- return question.showWhen.every(condition => {
167
- const answer = answers[condition.questionId];
168
-
169
- switch (condition.operator) {
170
- case 'equals':
171
- return answer === condition.value;
172
- case 'contains':
173
- return Array.isArray(answer) ? answer.includes(condition.value) : false;
174
- case 'greaterThan':
175
- return typeof answer === 'number' ? answer > condition.value : false;
176
- case 'lessThan':
177
- return typeof answer === 'number' ? answer < condition.value : false;
178
- default:
179
- return true;
180
- }
181
- });
182
- };
183
-
184
- // Get the visible questions for the current section
185
- const getVisibleQuestions = (): DPIAQuestion[] => {
186
- if (!currentSection) {
187
- return [];
188
- }
189
-
190
- return currentSection.questions.filter(shouldShowQuestion);
191
- };
192
-
193
- // Check if the current section is valid
194
- const isCurrentSectionValid = (): boolean => {
195
- if (!currentSection) {
196
- return false;
197
- }
198
-
199
- const visibleQuestions = getVisibleQuestions();
200
-
201
- return visibleQuestions.every(question => {
202
- if (!question.required) {
203
- return true;
204
- }
205
-
206
- const answer = answers[question.id];
207
-
208
- if (answer === undefined || answer === null) {
209
- return false;
210
- }
211
-
212
- if (typeof answer === 'string' && answer.trim() === '') {
213
- return false;
214
- }
215
-
216
- if (Array.isArray(answer) && answer.length === 0) {
217
- return false;
218
- }
219
-
220
- return true;
221
- });
222
- };
223
-
224
- // Get validation errors for the current section
225
- const getCurrentSectionErrors = (): Record<string, string> => {
226
- const errors: Record<string, string> = {};
227
-
228
- if (!currentSection) {
229
- return errors;
230
- }
231
-
232
- const visibleQuestions = getVisibleQuestions();
233
-
234
- visibleQuestions.forEach(question => {
235
- if (!question.required) {
236
- return;
237
- }
238
-
239
- const answer = answers[question.id];
240
-
241
- if (answer === undefined || answer === null) {
242
- errors[question.id] = 'This question is required';
243
- } else if (typeof answer === 'string' && answer.trim() === '') {
244
- errors[question.id] = 'This question is required';
245
- } else if (Array.isArray(answer) && answer.length === 0) {
246
- errors[question.id] = 'At least one option must be selected';
247
- }
248
- });
249
-
250
- return errors;
251
- };
252
-
253
- // Go to the next section
254
- const nextSection = (): boolean => {
255
- if (!isCurrentSectionValid()) {
256
- return false;
257
- }
258
-
259
- if (currentSectionIndex < sections.length - 1) {
260
- setCurrentSectionIndex(prevIndex => prevIndex + 1);
261
- return true;
262
- }
263
-
264
- return false;
265
- };
266
-
267
- // Go to the previous section
268
- const prevSection = (): boolean => {
269
- if (currentSectionIndex > 0) {
270
- setCurrentSectionIndex(prevIndex => prevIndex - 1);
271
- return true;
272
- }
273
-
274
- return false;
275
- };
276
-
277
- // Go to a specific section
278
- const goToSection = (index: number): boolean => {
279
- if (index >= 0 && index < sections.length) {
280
- setCurrentSectionIndex(index);
281
- return true;
282
- }
283
-
284
- return false;
285
- };
286
-
287
- // Check if the DPIA is complete
288
- const isComplete = (): boolean => {
289
- return sections.every((section, index) => {
290
- // Temporarily set the current section to check ifit&apos;s valid
291
- setCurrentSectionIndex(index);
292
- const valid = isCurrentSectionValid();
293
- // Restore the current section
294
- setCurrentSectionIndex(currentSectionIndex);
295
- return valid;
296
- });
297
- };
298
-
299
- // Identify risks based on answers
300
- const identifyRisks = (): DPIARisk[] => {
301
- const risks: DPIARisk[] = [];
302
-
303
- // Check each question for risk indicators
304
- sections.forEach(section => {
305
- section.questions.forEach(question => {
306
- const answer = answers[question.id];
307
-
308
- // Skip if no answer
309
- if (answer === undefined || answer === null) {
310
- return;
311
- }
312
-
313
- // Check if the question has a risk level
314
- if (question.riskLevel) {
315
- // For select/radio/checkbox questions, check if the selected option has a risk level
316
- if (['select', 'radio', 'checkbox'].includes(question.type) && question.options) {
317
- const selectedOptions = Array.isArray(answer) ? answer : [answer];
318
-
319
- selectedOptions.forEach(selectedOption => {
320
- const option = question.options?.find(opt => opt.value === selectedOption);
321
-
322
- if (option?.riskLevel) {
323
- const riskLevel = option.riskLevel;
324
- const likelihood = riskLevel === 'low' ? 1 : riskLevel === 'medium' ? 3 : 5;
325
- const impact = riskLevel === 'low' ? 1 : riskLevel === 'medium' ? 3 : 5;
326
-
327
- risks.push({
328
- id: `risk_${risks.length + 1}`,
329
- description: `${question.text} - ${option.label}`,
330
- likelihood,
331
- impact,
332
- score: likelihood * impact,
333
- level: riskLevel,
334
- mitigated: false,
335
- relatedQuestionIds: [question.id]
336
- });
337
- }
338
- });
339
- } else {
340
- // For other question types, use the question's risk level
341
- const riskLevel = question.riskLevel;
342
- const likelihood = riskLevel === 'low' ? 1 : riskLevel === 'medium' ? 3 : 5;
343
- const impact = riskLevel === 'low' ? 1 : riskLevel === 'medium' ? 3 : 5;
344
-
345
- risks.push({
346
- id: `risk_${risks.length + 1}`,
347
- description: question.text,
348
- likelihood,
349
- impact,
350
- score: likelihood * impact,
351
- level: riskLevel,
352
- mitigated: false,
353
- relatedQuestionIds: [question.id]
354
- });
355
- }
356
- }
357
- });
358
- });
359
-
360
- return risks;
361
- };
362
-
363
- // Complete the DPIA and generate a result
364
- const completeDPIA = (
365
- assessorInfo: { name: string; role: string; email: string; },
366
- title: string,
367
- processingDescription: string
368
- ): DPIAResult => {
369
- const risks = identifyRisks();
370
-
371
- const result: DPIAResult = {
372
- id: `dpia_${Date.now()}`,
373
- title,
374
- processingDescription,
375
- startedAt: Date.now(),
376
- completedAt: Date.now(),
377
- assessor: assessorInfo,
378
- answers,
379
- risks,
380
- overallRiskLevel: 'low',
381
- canProceed: true,
382
- conclusion: '',
383
- version: '1.0'
384
- };
385
-
386
- // Assess the risks
387
- const assessment = assessDPIARisk(result);
388
-
389
- result.overallRiskLevel = assessment.overallRiskLevel;
390
- result.canProceed = assessment.canProceed;
391
- result.conclusion = assessment.canProceed
392
- ? 'Based on the assessment, the processing can proceed with appropriate safeguards.'
393
- : 'Based on the assessment, the processing should not proceed without further mitigation measures.';
394
- result.recommendations = assessment.recommendations;
395
-
396
- if (onComplete) {
397
- onComplete(result);
398
- }
399
-
400
- return result;
401
- };
402
-
403
- // Reset the DPIA
404
- const resetDPIA = () => {
405
- setAnswers({});
406
- setCurrentSectionIndex(0);
407
-
408
- if (useLocalStorage && typeof window !== 'undefined') {
409
- localStorage.removeItem(storageKey);
410
- }
411
- };
412
-
413
- // Calculate progress percentage
414
- const progress = (() => {
415
- let answeredQuestions = 0;
416
- let totalRequiredQuestions = 0;
417
-
418
- sections.forEach(section => {
419
- section.questions.forEach(question => {
420
- if (question.required && shouldShowQuestion(question)) {
421
- totalRequiredQuestions++;
422
-
423
- const answer = answers[question.id];
424
- if (
425
- answer !== undefined &&
426
- answer !== null &&
427
- !(typeof answer === 'string' && answer.trim() === '') &&
428
- !(Array.isArray(answer) && answer.length === 0)
429
- ) {
430
- answeredQuestions++;
431
- }
432
- }
433
- });
434
- });
435
-
436
- return totalRequiredQuestions > 0
437
- ? Math.round((answeredQuestions / totalRequiredQuestions) * 100)
438
- : 0;
439
- })();
440
-
441
- return {
442
- currentSectionIndex,
443
- currentSection,
444
- answers,
445
- updateAnswer,
446
- nextSection,
447
- prevSection,
448
- goToSection,
449
- isCurrentSectionValid,
450
- getCurrentSectionErrors,
451
- isComplete,
452
- completeDPIA,
453
- getVisibleQuestions,
454
- resetDPIA,
455
- progress
456
- };
457
- }
@@ -1,236 +0,0 @@
1
- import { useState, useEffect } from 'react';
2
- import { DSRRequest, RequestStatus, RequestType } from '../types/dsr';
3
- import { formatDSRRequest } from '../utils/dsr';
4
-
5
- interface UseDSROptions {
6
- /**
7
- * Initial requests to load
8
- */
9
- initialRequests?: DSRRequest[];
10
-
11
- /**
12
- * Available request types
13
- */
14
- requestTypes: RequestType[];
15
-
16
- /**
17
- * Storage key for requests
18
- * @default "ndpr_dsr_requests"
19
- */
20
- storageKey?: string;
21
-
22
- /**
23
- * Whether to use local storage to persist requests
24
- * @default true
25
- */
26
- useLocalStorage?: boolean;
27
-
28
- /**
29
- * Callback function called when a request is submitted
30
- */
31
- onSubmit?: (request: DSRRequest) => void;
32
-
33
- /**
34
- * Callback function called when a request is updated
35
- */
36
- onUpdate?: (request: DSRRequest) => void;
37
- }
38
-
39
- interface UseDSRReturn {
40
- /**
41
- * All requests
42
- */
43
- requests: DSRRequest[];
44
-
45
- /**
46
- * Submit a new request
47
- */
48
- submitRequest: (requestData: Omit<DSRRequest, 'id' | 'status' | 'submittedAt' | 'updatedAt' | 'estimatedCompletionDate'>) => DSRRequest;
49
-
50
- /**
51
- * Update an existing request
52
- */
53
- updateRequest: (id: string, updates: Partial<DSRRequest>) => DSRRequest | null;
54
-
55
- /**
56
- * Get a request by ID
57
- */
58
- getRequest: (id: string) => DSRRequest | null;
59
-
60
- /**
61
- * Get requests by status
62
- */
63
- getRequestsByStatus: (status: RequestStatus) => DSRRequest[];
64
-
65
- /**
66
- * Get requests by type
67
- */
68
- getRequestsByType: (type: string) => DSRRequest[];
69
-
70
- /**
71
- * Get the request type definition by ID
72
- */
73
- getRequestType: (typeId: string) => RequestType | undefined;
74
-
75
- /**
76
- * Format a request for display or submission
77
- */
78
- formatRequest: (request: DSRRequest) => Record<string, any>;
79
-
80
- /**
81
- * Clear all requests
82
- */
83
- clearRequests: () => void;
84
- }
85
-
86
- /**
87
- * Hook for managing Data Subject Requests in compliance with NDPR
88
- */
89
- export function useDSR({
90
- initialRequests = [],
91
- requestTypes,
92
- storageKey = "ndpr_dsr_requests",
93
- useLocalStorage = true,
94
- onSubmit,
95
- onUpdate
96
- }: UseDSROptions): UseDSRReturn {
97
- const [requests, setRequests] = useState<DSRRequest[]>(initialRequests);
98
-
99
- // Load requests from storage on mount
100
- useEffect(() => {
101
- if (useLocalStorage && typeof window !== 'undefined') {
102
- try {
103
- const savedRequests = localStorage.getItem(storageKey);
104
- if (savedRequests) {
105
- setRequests(JSON.parse(savedRequests));
106
- }
107
- } catch (error) {
108
- console.error('Error loading DSR requests:', error);
109
- }
110
- }
111
- }, [storageKey, useLocalStorage]);
112
-
113
- // Save requests to storage when they change
114
- useEffect(() => {
115
- if (useLocalStorage && typeof window !== 'undefined' && requests.length > 0) {
116
- try {
117
- localStorage.setItem(storageKey, JSON.stringify(requests));
118
- } catch (error) {
119
- console.error('Error saving DSR requests:', error);
120
- }
121
- }
122
- }, [requests, storageKey, useLocalStorage]);
123
-
124
- // Generate a unique ID
125
- const generateId = (): string => {
126
- return 'dsr_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
127
- };
128
-
129
- // Submit a new request
130
- const submitRequest = (requestData: Omit<DSRRequest, 'id' | 'status' | 'submittedAt' | 'updatedAt' | 'estimatedCompletionDate'>): DSRRequest => {
131
- // Find the request type to get the estimated completion time
132
- const requestType = requestTypes.find(type => type.id === requestData.type);
133
- const estimatedCompletionDays = requestType?.estimatedCompletionTime || 30; // Default to 30 days
134
-
135
- const now = Date.now();
136
- const estimatedCompletionDate = now + (estimatedCompletionDays * 24 * 60 * 60 * 1000);
137
-
138
- // Extract any properties we want to override from requestData
139
- const { createdAt, ...restRequestData } = requestData as any;
140
-
141
- const newRequest: DSRRequest = {
142
- id: generateId(),
143
- status: 'pending',
144
- createdAt: now,
145
- updatedAt: now,
146
- dueDate: estimatedCompletionDate,
147
- ...restRequestData
148
- };
149
-
150
- setRequests(prevRequests => [...prevRequests, newRequest]);
151
-
152
- if (onSubmit) {
153
- onSubmit(newRequest);
154
- }
155
-
156
- return newRequest;
157
- };
158
-
159
- // Update an existing request
160
- const updateRequest = (id: string, updates: Partial<DSRRequest>): DSRRequest | null => {
161
- let updatedRequest: DSRRequest | null = null;
162
-
163
- setRequests(prevRequests => {
164
- const index = prevRequests.findIndex(request => request.id === id);
165
-
166
- if (index === -1) {
167
- return prevRequests;
168
- }
169
-
170
- const request = prevRequests[index];
171
- updatedRequest = {
172
- ...request,
173
- ...updates,
174
- updatedAt: Date.now()
175
- };
176
-
177
- const newRequests = [...prevRequests];
178
- newRequests[index] = updatedRequest as DSRRequest;
179
-
180
- return newRequests;
181
- });
182
-
183
- if (updatedRequest && onUpdate) {
184
- onUpdate(updatedRequest);
185
- }
186
-
187
- return updatedRequest;
188
- };
189
-
190
- // Get a request by ID
191
- const getRequest = (id: string): DSRRequest | null => {
192
- return requests.find(request => request.id === id) || null;
193
- };
194
-
195
- // Get requests by status
196
- const getRequestsByStatus = (status: RequestStatus): DSRRequest[] => {
197
- return requests.filter(request => request.status === status);
198
- };
199
-
200
- // Get requests by type
201
- const getRequestsByType = (type: string): DSRRequest[] => {
202
- return requests.filter(request => request.type === type);
203
- };
204
-
205
- // Get the request type definition by ID
206
- const getRequestType = (typeId: string): RequestType | undefined => {
207
- return requestTypes.find(type => type.id === typeId);
208
- };
209
-
210
- // Format a request for display or submission
211
- const formatRequest = (request: DSRRequest): Record<string, any> => {
212
- const { formattedRequest } = formatDSRRequest(request);
213
- return formattedRequest;
214
- };
215
-
216
- // Clear all requests
217
- const clearRequests = () => {
218
- setRequests([]);
219
-
220
- if (useLocalStorage && typeof window !== 'undefined') {
221
- localStorage.removeItem(storageKey);
222
- }
223
- };
224
-
225
- return {
226
- requests,
227
- submitRequest,
228
- updateRequest,
229
- getRequest,
230
- getRequestsByStatus,
231
- getRequestsByType,
232
- getRequestType,
233
- formatRequest,
234
- clearRequests
235
- };
236
- }