@tantainnovative/ndpr-toolkit 1.0.1 → 1.0.3

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 (212) hide show
  1. package/.claude/settings.local.json +20 -0
  2. package/.eslintrc.json +10 -0
  3. package/.github/workflows/ci.yml +36 -0
  4. package/.github/workflows/nextjs.yml +104 -0
  5. package/.husky/commit-msg +4 -0
  6. package/.husky/pre-commit +4 -0
  7. package/.lintstagedrc.js +4 -0
  8. package/.nvmrc +1 -0
  9. package/.versionrc +17 -0
  10. package/CHANGELOG.md +16 -0
  11. package/CLAUDE.md +90 -0
  12. package/CNAME +1 -0
  13. package/CONTRIBUTING.md +87 -0
  14. package/README.md +84 -431
  15. package/RELEASE-NOTES-v1.0.0.md +140 -0
  16. package/RELEASE-NOTES-v1.0.1.md +69 -0
  17. package/SECURITY.md +21 -0
  18. package/commitlint.config.js +36 -0
  19. package/components.json +21 -0
  20. package/eslint.config.mjs +16 -0
  21. package/jest.config.js +31 -0
  22. package/jest.setup.js +15 -0
  23. package/next.config.js +15 -0
  24. package/next.config.ts +62 -0
  25. package/package.json +70 -52
  26. package/packages/ndpr-toolkit/README.md +467 -0
  27. package/packages/ndpr-toolkit/jest.config.js +23 -0
  28. package/packages/ndpr-toolkit/package-lock.json +8197 -0
  29. package/packages/ndpr-toolkit/package.json +71 -0
  30. package/packages/ndpr-toolkit/rollup.config.js +34 -0
  31. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentBanner.test.tsx +119 -0
  32. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentManager.test.tsx +122 -0
  33. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentStorage.test.tsx +270 -0
  34. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRDashboard.test.tsx +199 -0
  35. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRRequestForm.test.tsx +224 -0
  36. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRTracker.test.tsx +104 -0
  37. package/packages/ndpr-toolkit/src/__tests__/hooks/useConsent.test.tsx +161 -0
  38. package/packages/ndpr-toolkit/src/__tests__/hooks/useDSR.test.tsx +330 -0
  39. package/packages/ndpr-toolkit/src/__tests__/utils/breach.test.ts +149 -0
  40. package/packages/ndpr-toolkit/src/__tests__/utils/consent.test.ts +88 -0
  41. package/packages/ndpr-toolkit/src/__tests__/utils/dpia.test.ts +160 -0
  42. package/packages/ndpr-toolkit/src/__tests__/utils/dsr.test.ts +110 -0
  43. package/packages/ndpr-toolkit/src/__tests__/utils/privacy.test.ts +97 -0
  44. package/packages/ndpr-toolkit/src/components/breach/BreachNotificationManager.tsx +701 -0
  45. package/packages/ndpr-toolkit/src/components/breach/BreachReportForm.tsx +631 -0
  46. package/packages/ndpr-toolkit/src/components/breach/BreachRiskAssessment.tsx +569 -0
  47. package/packages/ndpr-toolkit/src/components/breach/RegulatoryReportGenerator.tsx +496 -0
  48. package/packages/ndpr-toolkit/src/components/consent/ConsentBanner.tsx +270 -0
  49. package/packages/ndpr-toolkit/src/components/consent/ConsentManager.tsx +217 -0
  50. package/packages/ndpr-toolkit/src/components/consent/ConsentStorage.tsx +206 -0
  51. package/packages/ndpr-toolkit/src/components/dpia/DPIAQuestionnaire.tsx +342 -0
  52. package/packages/ndpr-toolkit/src/components/dpia/DPIAReport.tsx +373 -0
  53. package/packages/ndpr-toolkit/src/components/dpia/StepIndicator.tsx +174 -0
  54. package/packages/ndpr-toolkit/src/components/dsr/DSRDashboard.tsx +717 -0
  55. package/packages/ndpr-toolkit/src/components/dsr/DSRRequestForm.tsx +476 -0
  56. package/packages/ndpr-toolkit/src/components/dsr/DSRTracker.tsx +620 -0
  57. package/packages/ndpr-toolkit/src/components/policy/PolicyExporter.tsx +541 -0
  58. package/packages/ndpr-toolkit/src/components/policy/PolicyGenerator.tsx +454 -0
  59. package/packages/ndpr-toolkit/src/components/policy/PolicyPreview.tsx +333 -0
  60. package/packages/ndpr-toolkit/src/hooks/useBreach.ts +409 -0
  61. package/packages/ndpr-toolkit/src/hooks/useConsent.ts +263 -0
  62. package/packages/ndpr-toolkit/src/hooks/useDPIA.ts +457 -0
  63. package/packages/ndpr-toolkit/src/hooks/useDSR.ts +236 -0
  64. package/packages/ndpr-toolkit/src/hooks/usePrivacyPolicy.ts +428 -0
  65. package/{dist/index.d.ts → packages/ndpr-toolkit/src/index.ts} +14 -1
  66. package/packages/ndpr-toolkit/src/setupTests.ts +5 -0
  67. package/packages/ndpr-toolkit/src/types/breach.ts +283 -0
  68. package/packages/ndpr-toolkit/src/types/consent.ts +111 -0
  69. package/packages/ndpr-toolkit/src/types/dpia.ts +236 -0
  70. package/packages/ndpr-toolkit/src/types/dsr.ts +192 -0
  71. package/packages/ndpr-toolkit/src/types/index.ts +42 -0
  72. package/packages/ndpr-toolkit/src/types/privacy.ts +246 -0
  73. package/packages/ndpr-toolkit/src/utils/breach.ts +122 -0
  74. package/packages/ndpr-toolkit/src/utils/consent.ts +51 -0
  75. package/packages/ndpr-toolkit/src/utils/dpia.ts +104 -0
  76. package/packages/ndpr-toolkit/src/utils/dsr.ts +77 -0
  77. package/packages/ndpr-toolkit/src/utils/privacy.ts +100 -0
  78. package/packages/ndpr-toolkit/tsconfig.json +23 -0
  79. package/postcss.config.mjs +5 -0
  80. package/public/NDPR TOOLKIT.svg +1 -0
  81. package/public/favicon/android-chrome-192x192.png +0 -0
  82. package/public/favicon/android-chrome-512x512.png +0 -0
  83. package/public/favicon/apple-touch-icon.png +0 -0
  84. package/public/favicon/favicon-16x16.png +0 -0
  85. package/public/favicon/favicon-32x32.png +0 -0
  86. package/public/favicon/site.webmanifest +1 -0
  87. package/public/file.svg +1 -0
  88. package/public/globe.svg +1 -0
  89. package/public/ndpr-toolkit-logo.svg +108 -0
  90. package/public/next.svg +1 -0
  91. package/public/vercel.svg +1 -0
  92. package/public/window.svg +1 -0
  93. package/src/__tests__/example.test.ts +13 -0
  94. package/src/__tests__/requestService.test.ts +57 -0
  95. package/src/app/accessibility.css +70 -0
  96. package/src/app/docs/components/DocLayout.tsx +267 -0
  97. package/src/app/docs/components/breach-notification/page.tsx +797 -0
  98. package/src/app/docs/components/consent-management/page.tsx +576 -0
  99. package/src/app/docs/components/data-subject-rights/page.tsx +511 -0
  100. package/src/app/docs/components/dpia-questionnaire/layout.tsx +15 -0
  101. package/src/app/docs/components/dpia-questionnaire/metadata.ts +31 -0
  102. package/src/app/docs/components/dpia-questionnaire/page.tsx +666 -0
  103. package/src/app/docs/components/hooks/page.tsx +305 -0
  104. package/src/app/docs/components/page.tsx +84 -0
  105. package/src/app/docs/components/privacy-policy-generator/page.tsx +634 -0
  106. package/src/app/docs/guides/breach-notification-process/components/BestPractices.tsx +123 -0
  107. package/src/app/docs/guides/breach-notification-process/components/ImplementationSteps.tsx +328 -0
  108. package/src/app/docs/guides/breach-notification-process/components/Introduction.tsx +28 -0
  109. package/src/app/docs/guides/breach-notification-process/components/NotificationTimeline.tsx +91 -0
  110. package/src/app/docs/guides/breach-notification-process/components/Resources.tsx +118 -0
  111. package/src/app/docs/guides/breach-notification-process/page.tsx +39 -0
  112. package/src/app/docs/guides/conducting-dpia/page.tsx +593 -0
  113. package/src/app/docs/guides/data-subject-requests/page.tsx +666 -0
  114. package/src/app/docs/guides/managing-consent/page.tsx +738 -0
  115. package/src/app/docs/guides/ndpr-compliance-checklist/components/ComplianceChecklist.tsx +296 -0
  116. package/src/app/docs/guides/ndpr-compliance-checklist/components/ImplementationTools.tsx +145 -0
  117. package/src/app/docs/guides/ndpr-compliance-checklist/components/Introduction.tsx +33 -0
  118. package/src/app/docs/guides/ndpr-compliance-checklist/components/KeyRequirements.tsx +99 -0
  119. package/src/app/docs/guides/ndpr-compliance-checklist/components/Resources.tsx +159 -0
  120. package/src/app/docs/guides/ndpr-compliance-checklist/page.tsx +38 -0
  121. package/src/app/docs/guides/page.tsx +67 -0
  122. package/src/app/docs/layout.tsx +15 -0
  123. package/src/app/docs/metadata.ts +31 -0
  124. package/src/app/docs/page.tsx +572 -0
  125. package/src/app/favicon.ico +0 -0
  126. package/src/app/globals.css +123 -0
  127. package/src/app/layout.tsx +37 -0
  128. package/src/app/ndpr-demos/breach/page.tsx +354 -0
  129. package/src/app/ndpr-demos/consent/page.tsx +366 -0
  130. package/src/app/ndpr-demos/dpia/page.tsx +495 -0
  131. package/src/app/ndpr-demos/dsr/page.tsx +280 -0
  132. package/src/app/ndpr-demos/page.tsx +73 -0
  133. package/src/app/ndpr-demos/policy/page.tsx +771 -0
  134. package/src/app/page.tsx +452 -0
  135. package/src/components/ErrorBoundary.tsx +90 -0
  136. package/src/components/breach-notification/BreachNotificationForm.tsx +479 -0
  137. package/src/components/consent/ConsentBanner.tsx +159 -0
  138. package/src/components/data-subject-rights/DataSubjectRequestForm.tsx +419 -0
  139. package/src/components/docs/DocLayout.tsx +289 -0
  140. package/src/components/docs/index.ts +2 -0
  141. package/src/components/dpia/DPIAQuestionnaire.tsx +483 -0
  142. package/src/components/privacy-policy/PolicyGenerator.tsx +1062 -0
  143. package/src/components/privacy-policy/data.ts +98 -0
  144. package/src/components/privacy-policy/shared/CheckboxField.tsx +38 -0
  145. package/src/components/privacy-policy/shared/CheckboxGroup.tsx +85 -0
  146. package/src/components/privacy-policy/shared/FormField.tsx +79 -0
  147. package/src/components/privacy-policy/shared/StepIndicator.tsx +86 -0
  148. package/src/components/privacy-policy/steps/CustomSectionsStep.tsx +335 -0
  149. package/src/components/privacy-policy/steps/DataCollectionStep.tsx +231 -0
  150. package/src/components/privacy-policy/steps/DataSharingStep.tsx +418 -0
  151. package/src/components/privacy-policy/steps/OrganizationInfoStep.tsx +202 -0
  152. package/src/components/privacy-policy/steps/PolicyPreviewStep.tsx +172 -0
  153. package/src/components/ui/Badge.tsx +46 -0
  154. package/src/components/ui/Button.tsx +59 -0
  155. package/src/components/ui/Card.tsx +92 -0
  156. package/src/components/ui/Checkbox.tsx +57 -0
  157. package/src/components/ui/FormField.tsx +50 -0
  158. package/src/components/ui/Input.tsx +38 -0
  159. package/src/components/ui/Loading.tsx +201 -0
  160. package/src/components/ui/Select.tsx +42 -0
  161. package/src/components/ui/TextArea.tsx +38 -0
  162. package/src/components/ui/label.tsx +24 -0
  163. package/src/components/ui/switch.tsx +31 -0
  164. package/src/components/ui/tabs.tsx +66 -0
  165. package/src/hooks/useConsent.ts +64 -0
  166. package/src/hooks/useLoadingState.ts +85 -0
  167. package/src/lib/consentService.ts +137 -0
  168. package/src/lib/dpiaQuestions.ts +148 -0
  169. package/src/lib/requestService.ts +75 -0
  170. package/src/lib/sanitize.ts +108 -0
  171. package/src/lib/storage.ts +222 -0
  172. package/src/lib/utils.ts +6 -0
  173. package/src/types/html-to-docx.d.ts +30 -0
  174. package/src/types/index.ts +72 -0
  175. package/tailwind.config.ts +65 -0
  176. package/tsconfig.json +41 -0
  177. package/dist/components/breach/BreachNotificationManager.d.ts +0 -62
  178. package/dist/components/breach/BreachReportForm.d.ts +0 -66
  179. package/dist/components/breach/BreachRiskAssessment.d.ts +0 -50
  180. package/dist/components/breach/RegulatoryReportGenerator.d.ts +0 -94
  181. package/dist/components/consent/ConsentBanner.d.ts +0 -79
  182. package/dist/components/consent/ConsentManager.d.ts +0 -73
  183. package/dist/components/consent/ConsentStorage.d.ts +0 -41
  184. package/dist/components/dpia/DPIAQuestionnaire.d.ts +0 -70
  185. package/dist/components/dpia/DPIAReport.d.ts +0 -40
  186. package/dist/components/dpia/StepIndicator.d.ts +0 -64
  187. package/dist/components/dsr/DSRDashboard.d.ts +0 -58
  188. package/dist/components/dsr/DSRRequestForm.d.ts +0 -74
  189. package/dist/components/dsr/DSRTracker.d.ts +0 -56
  190. package/dist/components/policy/PolicyExporter.d.ts +0 -65
  191. package/dist/components/policy/PolicyGenerator.d.ts +0 -54
  192. package/dist/components/policy/PolicyPreview.d.ts +0 -71
  193. package/dist/hooks/useBreach.d.ts +0 -97
  194. package/dist/hooks/useConsent.d.ts +0 -63
  195. package/dist/hooks/useDPIA.d.ts +0 -92
  196. package/dist/hooks/useDSR.d.ts +0 -72
  197. package/dist/hooks/usePrivacyPolicy.d.ts +0 -87
  198. package/dist/index.esm.js +0 -2
  199. package/dist/index.esm.js.map +0 -1
  200. package/dist/index.js +0 -2
  201. package/dist/index.js.map +0 -1
  202. package/dist/setupTests.d.ts +0 -2
  203. package/dist/types/breach.d.ts +0 -239
  204. package/dist/types/consent.d.ts +0 -95
  205. package/dist/types/dpia.d.ts +0 -196
  206. package/dist/types/dsr.d.ts +0 -162
  207. package/dist/types/privacy.d.ts +0 -204
  208. package/dist/utils/breach.d.ts +0 -14
  209. package/dist/utils/consent.d.ts +0 -10
  210. package/dist/utils/dpia.d.ts +0 -12
  211. package/dist/utils/dsr.d.ts +0 -11
  212. package/dist/utils/privacy.d.ts +0 -12
@@ -0,0 +1,495 @@
1
+ 'use client';
2
+
3
+ import React, { useState, useEffect } from 'react';
4
+ import Link from 'next/link';
5
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
6
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/Card';
7
+ import { DPIAQuestionnaire } from '@tantainnovative/ndpr-toolkit';
8
+ import type { DPIAQuestion, DPIAResult } from '@tantainnovative/ndpr-toolkit';
9
+
10
+ export default function DPIADemoPage() {
11
+ const [activeTab, setActiveTab] = useState('form');
12
+ const [isClient, setIsClient] = useState(false);
13
+ // Removed unused state variables
14
+ const [assessmentData, setAssessmentData] = useState<Record<string, unknown>>({});
15
+ const [assessmentResult, setAssessmentResult] = useState<DPIAResult | null>(null);
16
+
17
+ // Define DPIA questions
18
+ const dpiaQuestions: DPIAQuestion[] = [
19
+ {
20
+ id: 'purpose',
21
+ text: 'What is the purpose of the data processing?',
22
+ guidance: 'Describe why you are collecting and processing personal data',
23
+ type: 'text',
24
+ required: true
25
+ },
26
+ {
27
+ id: 'dataTypes',
28
+ text: 'What types of personal data will be processed?',
29
+ guidance: 'Select all types of personal data that will be processed',
30
+ type: 'checkbox',
31
+ options: [
32
+ { value: 'basic', label: 'Basic personal information (name, contact details)' },
33
+ { value: 'identification', label: 'Identification numbers (ID, passport)' },
34
+ { value: 'financial', label: 'Financial information (bank details, payment info)' },
35
+ { value: 'location', label: 'Location data' },
36
+ { value: 'health', label: 'Health data' },
37
+ { value: 'biometric', label: 'Biometric data' },
38
+ { value: 'children', label: 'Data relating to children' }
39
+ ],
40
+ required: true
41
+ },
42
+ {
43
+ id: 'dataVolume',
44
+ text: 'What is the volume of data being processed?',
45
+ guidance: 'Estimate the number of data subjects affected',
46
+ type: 'radio',
47
+ options: [
48
+ { value: 'small', label: 'Small (less than 1,000 individuals)' },
49
+ { value: 'medium', label: 'Medium (1,000 to 10,000 individuals)' },
50
+ { value: 'large', label: 'Large (10,000 to 100,000 individuals)' },
51
+ { value: 'veryLarge', label: 'Very large (more than 100,000 individuals)' }
52
+ ],
53
+ required: true
54
+ },
55
+ {
56
+ id: 'legalBasis',
57
+ text: 'What is the legal basis for processing?',
58
+ guidance: 'Select the legal basis under which you are processing data',
59
+ type: 'select',
60
+ options: [
61
+ { value: 'consent', label: 'Consent of the data subject' },
62
+ { value: 'contract', label: 'Performance of a contract' },
63
+ { value: 'legalObligation', label: 'Compliance with a legal obligation' },
64
+ { value: 'vitalInterests', label: 'Protection of vital interests' },
65
+ { value: 'publicInterest', label: 'Performance of a task in the public interest' },
66
+ { value: 'legitimateInterests', label: 'Legitimate interests' }
67
+ ],
68
+ required: true
69
+ },
70
+ {
71
+ id: 'dataRetention',
72
+ text: 'How long will the data be retained?',
73
+ guidance: 'Specify the retention period for the personal data',
74
+ type: 'text',
75
+ required: true
76
+ },
77
+ {
78
+ id: 'securityMeasures',
79
+ text: 'What security measures are in place to protect the data?',
80
+ guidance: 'Describe the technical and organizational measures to ensure data security',
81
+ type: 'textarea',
82
+ required: true
83
+ },
84
+ {
85
+ id: 'dataTransfers',
86
+ text: 'Will data be transferred outside Nigeria?',
87
+ guidance: 'Indicate if data will be transferred to countries outside Nigeria',
88
+ type: 'radio',
89
+ options: [
90
+ { value: 'yes', label: 'Yes' },
91
+ { value: 'no', label: 'No' }
92
+ ],
93
+ required: true
94
+ },
95
+ {
96
+ id: 'riskAssessment',
97
+ text: 'Have you conducted a risk assessment?',
98
+ guidance: 'Indicate if you have assessed the risks to data subjects',
99
+ type: 'radio',
100
+ options: [
101
+ { value: 'yes', label: 'Yes' },
102
+ { value: 'no', label: 'No' },
103
+ { value: 'inProgress', label: 'In progress' }
104
+ ],
105
+ required: true
106
+ }
107
+ ];
108
+
109
+ // This effect runs only on the client side after hydration
110
+ useEffect(() => {
111
+ setIsClient(true);
112
+
113
+ // Sample data for demonstration
114
+ const sampleData = {
115
+ purpose: 'Customer data processing for service delivery',
116
+ dataTypes: ['basic', 'financial'],
117
+ dataVolume: 'medium',
118
+ legalBasis: 'contract',
119
+ dataRetention: '3 years after service termination',
120
+ securityMeasures: 'Encryption, access controls, regular security audits',
121
+ dataTransfers: 'no',
122
+ riskAssessment: 'yes'
123
+ };
124
+
125
+ setAssessmentData(sampleData);
126
+
127
+ // Generate a mock assessment result
128
+ const mockResult: DPIAResult = {
129
+ id: 'dpia-' + Date.now(),
130
+ title: 'DPIA for Demo Project',
131
+ processingDescription: sampleData.purpose || 'Data processing activity',
132
+ startedAt: Date.now() - 86400000, // 1 day ago
133
+ completedAt: Date.now(),
134
+ assessor: {
135
+ name: 'Demo User',
136
+ role: 'Data Protection Officer',
137
+ email: 'dpo@example.com'
138
+ },
139
+ answers: sampleData,
140
+ risks: [
141
+ {
142
+ id: 'risk-1',
143
+ description: 'Unauthorized access to personal data',
144
+ likelihood: 3,
145
+ impact: 4,
146
+ score: 12,
147
+ level: 'high',
148
+ mitigationMeasures: [
149
+ 'Implement strong access controls',
150
+ 'Regular security audits',
151
+ 'Encryption of sensitive data'
152
+ ],
153
+ mitigated: true,
154
+ residualScore: 6,
155
+ relatedQuestionIds: ['securityMeasures']
156
+ },
157
+ {
158
+ id: 'risk-2',
159
+ description: 'Data retention beyond necessary period',
160
+ likelihood: 2,
161
+ impact: 3,
162
+ score: 6,
163
+ level: 'medium',
164
+ mitigationMeasures: [
165
+ 'Implement automated data deletion',
166
+ 'Regular data retention audits'
167
+ ],
168
+ mitigated: false,
169
+ relatedQuestionIds: ['dataRetention']
170
+ }
171
+ ],
172
+ overallRiskLevel: 'medium',
173
+ canProceed: true,
174
+ conclusion: 'The processing can proceed with the implementation of the recommended mitigation measures.',
175
+ recommendations: [
176
+ 'Document all security measures implemented',
177
+ 'Conduct regular reviews of the DPIA',
178
+ 'Ensure all staff are trained on data protection'
179
+ ],
180
+ reviewDate: Date.now() + 31536000000, // 1 year from now
181
+ version: '1.0'
182
+ };
183
+
184
+ setAssessmentResult(mockResult);
185
+ }, [isClient]);
186
+
187
+ const handleAssessmentComplete = (assessment: Record<string, unknown>) => {
188
+ setAssessmentData(assessment);
189
+ setActiveTab('assessment');
190
+
191
+ // In a real application, you would analyze the data and generate a real assessment result
192
+ console.log('Assessment data submitted:', assessment);
193
+ };
194
+
195
+ if (!isClient) {
196
+ return <div>Loading...</div>;
197
+ }
198
+
199
+ return (
200
+ <div className="container mx-auto py-10">
201
+ <div className="mb-6">
202
+ <Link href="/ndpr-demos" className="text-blue-600 hover:underline">
203
+ ← Back to NDPR Demos
204
+ </Link>
205
+ </div>
206
+
207
+ <h1 className="text-3xl font-bold mb-8">Data Protection Impact Assessment Demo</h1>
208
+
209
+ <Tabs value={activeTab} onValueChange={setActiveTab}>
210
+ <TabsList className="mb-6">
211
+ <TabsTrigger value="form">DPIA Form</TabsTrigger>
212
+ <TabsTrigger value="assessment">DPIA Assessment</TabsTrigger>
213
+ <TabsTrigger value="report">DPIA Report</TabsTrigger>
214
+ </TabsList>
215
+
216
+ <TabsContent value="form" className="mt-6">
217
+ <Card>
218
+ <CardHeader>
219
+ <CardTitle>DPIA Form</CardTitle>
220
+ <CardDescription>
221
+ This form helps you conduct a Data Protection Impact Assessment for high-risk processing activities.
222
+ </CardDescription>
223
+ </CardHeader>
224
+ <CardContent>
225
+ <DPIAQuestionnaire
226
+ sections={[{
227
+ id: 'main',
228
+ title: 'Data Protection Impact Assessment',
229
+ description: 'Complete this form to assess the impact of your data processing activities on data subjects\'s privacy.',
230
+ questions: dpiaQuestions,
231
+ order: 1
232
+ }]}
233
+ answers={assessmentData || {}}
234
+ onAnswerChange={(questionId, value) => {
235
+ setAssessmentData((prev: Record<string, unknown>) => ({
236
+ ...prev,
237
+ [questionId]: value
238
+ }));
239
+ }}
240
+ currentSectionIndex={0}
241
+ onNextSection={() => handleAssessmentComplete(assessmentData)}
242
+ submitButtonText="Submit Assessment"
243
+ />
244
+ </CardContent>
245
+ </Card>
246
+ </TabsContent>
247
+
248
+ <TabsContent value="assessment" className="mt-6">
249
+ <Card>
250
+ <CardHeader>
251
+ <CardTitle>DPIA Assessment</CardTitle>
252
+ <CardDescription>
253
+ This component displays the assessment results and risk analysis.
254
+ </CardDescription>
255
+ </CardHeader>
256
+ <CardContent>
257
+ {assessmentResult ? (
258
+ <div className="space-y-6">
259
+ <div className="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6">
260
+ <h2 className="text-xl font-bold mb-4">DPIA Assessment Results</h2>
261
+ <p className="mb-6">Review the risk assessment and recommended actions for your data processing activity.</p>
262
+
263
+ <div className="mb-6">
264
+ <h3 className="text-lg font-semibold mb-2">Risk Assessment</h3>
265
+ <div className="border rounded-md p-4">
266
+ <div className="flex justify-between items-center mb-4">
267
+ <span className="font-medium">Overall Risk Level:</span>
268
+ <span className={`px-3 py-1 rounded-full text-sm font-medium ${
269
+ assessmentResult.overallRiskLevel === 'low' ? 'bg-green-100 text-green-800' :
270
+ assessmentResult.overallRiskLevel === 'medium' ? 'bg-yellow-100 text-yellow-800' :
271
+ assessmentResult.overallRiskLevel === 'high' ? 'bg-orange-100 text-orange-800' :
272
+ 'bg-red-100 text-red-800'
273
+ }`}>
274
+ {assessmentResult.overallRiskLevel.charAt(0).toUpperCase() + assessmentResult.overallRiskLevel.slice(1)}
275
+ </span>
276
+ </div>
277
+
278
+ <h4 className="font-medium mb-2">Identified Risks:</h4>
279
+ <ul className="space-y-4">
280
+ {assessmentResult.risks.map(risk => (
281
+ <li key={risk.id} className="border-b pb-3">
282
+ <div className="flex justify-between items-start">
283
+ <div>
284
+ <p className="font-medium">{risk.description}</p>
285
+ <p className="text-sm text-gray-500 mt-1">
286
+ Risk Level: <span className={`font-medium ${
287
+ risk.level === 'low' ? 'text-green-600' :
288
+ risk.level === 'medium' ? 'text-yellow-600' :
289
+ risk.level === 'high' ? 'text-orange-600' :
290
+ 'text-red-600'
291
+ }`}>
292
+ {risk.level.charAt(0).toUpperCase() + risk.level.slice(1)}
293
+ </span>
294
+ </p>
295
+ </div>
296
+ <div className="text-center px-3 py-1 bg-gray-100 rounded-md">
297
+ <div className="text-lg font-bold">{risk.score}</div>
298
+ <div className="text-xs">Score</div>
299
+ </div>
300
+ </div>
301
+ {risk.mitigationMeasures && risk.mitigationMeasures.length > 0 && (
302
+ <div className="mt-2">
303
+ <p className="text-sm font-medium">Mitigation Measures:</p>
304
+ <ul className="list-disc pl-5 text-sm">
305
+ {risk.mitigationMeasures.map((measure, idx) => (
306
+ <li key={idx}>{measure}</li>
307
+ ))}
308
+ </ul>
309
+ </div>
310
+ )}
311
+ </li>
312
+ ))}
313
+ </ul>
314
+ </div>
315
+ </div>
316
+
317
+ <div>
318
+ <h3 className="text-lg font-semibold mb-2">Recommendations</h3>
319
+ <ul className="list-disc pl-5 space-y-1">
320
+ {assessmentResult.recommendations?.map((rec, idx) => (
321
+ <li key={idx}>{rec}</li>
322
+ ))}
323
+ </ul>
324
+ </div>
325
+ </div>
326
+ </div>
327
+ ) : (
328
+ <div className="p-4 text-center">
329
+ <p>No assessment data available. Please complete the DPIA form first.</p>
330
+ </div>
331
+ )}
332
+ </CardContent>
333
+ </Card>
334
+ </TabsContent>
335
+
336
+ <TabsContent value="report" className="mt-6">
337
+ <Card>
338
+ <CardHeader>
339
+ <CardTitle>DPIA Report</CardTitle>
340
+ <CardDescription>
341
+ This component generates a comprehensive DPIA report for documentation and compliance.
342
+ </CardDescription>
343
+ </CardHeader>
344
+ <CardContent>
345
+ {assessmentResult && assessmentData ? (
346
+ <div className="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6">
347
+ <h2 className="text-2xl font-bold mb-6">Data Protection Impact Assessment Report</h2>
348
+
349
+ <div className="mb-6">
350
+ <h3 className="text-lg font-semibold mb-2">Organization Information</h3>
351
+ <div className="border rounded-md p-4">
352
+ <p><strong>Organization:</strong> Demo Company Ltd.</p>
353
+ <p><strong>Address:</strong> 123 Business Street, Lagos, Nigeria</p>
354
+ <p><strong>Contact Email:</strong> privacy@democompany.com</p>
355
+ <p><strong>Contact Phone:</strong> +234 123 456 7890</p>
356
+ </div>
357
+ </div>
358
+
359
+ <div className="mb-6">
360
+ <h3 className="text-lg font-semibold mb-2">DPIA Information</h3>
361
+ <div className="border rounded-md p-4">
362
+ <p><strong>Title:</strong> {assessmentResult.title}</p>
363
+ <p><strong>Processing Description:</strong> {assessmentResult.processingDescription}</p>
364
+ <p><strong>Started:</strong> {new Date(assessmentResult.startedAt).toLocaleDateString()}</p>
365
+ <p><strong>Completed:</strong> {assessmentResult.completedAt ? new Date(assessmentResult.completedAt).toLocaleDateString() : 'Not completed'}</p>
366
+ <p><strong>Assessor:</strong> {assessmentResult.assessor.name} ({assessmentResult.assessor.role})</p>
367
+ </div>
368
+ </div>
369
+
370
+ <div className="mb-6">
371
+ <h3 className="text-lg font-semibold mb-2">Risk Assessment</h3>
372
+ <div className="border rounded-md p-4">
373
+ <p className="mb-2">
374
+ <strong>Overall Risk Level: </strong>
375
+ <span className={`px-3 py-1 rounded-full text-sm font-medium ${
376
+ assessmentResult.overallRiskLevel === 'low' ? 'bg-green-100 text-green-800' :
377
+ assessmentResult.overallRiskLevel === 'medium' ? 'bg-yellow-100 text-yellow-800' :
378
+ assessmentResult.overallRiskLevel === 'high' ? 'bg-orange-100 text-orange-800' :
379
+ 'bg-red-100 text-red-800'
380
+ }`}>
381
+ {assessmentResult.overallRiskLevel.charAt(0).toUpperCase() + assessmentResult.overallRiskLevel.slice(1)}
382
+ </span>
383
+ </p>
384
+
385
+ <p className="mb-2"><strong>Can Processing Proceed:</strong> {assessmentResult.canProceed ? 'Yes' : 'No'}</p>
386
+
387
+ <p className="mb-2"><strong>Conclusion:</strong></p>
388
+ <p className="mb-4 pl-4 border-l-4 border-gray-300">{assessmentResult.conclusion}</p>
389
+
390
+ <p className="font-medium mb-2">Identified Risks:</p>
391
+ <ul className="space-y-4">
392
+ {assessmentResult.risks.map(risk => (
393
+ <li key={risk.id} className="border-b pb-3">
394
+ <div className="flex justify-between items-start">
395
+ <div>
396
+ <p className="font-medium">{risk.description}</p>
397
+ <p className="text-sm text-gray-500 mt-1">
398
+ Risk Level: <span className={`font-medium ${
399
+ risk.level === 'low' ? 'text-green-600' :
400
+ risk.level === 'medium' ? 'text-yellow-600' :
401
+ risk.level === 'high' ? 'text-orange-600' :
402
+ 'text-red-600'
403
+ }`}>
404
+ {risk.level.charAt(0).toUpperCase() + risk.level.slice(1)}
405
+ </span>
406
+ </p>
407
+ </div>
408
+ <div className="text-center px-3 py-1 bg-gray-100 rounded-md">
409
+ <div className="text-lg font-bold">{risk.score}</div>
410
+ <div className="text-xs">Score</div>
411
+ </div>
412
+ </div>
413
+ {risk.mitigationMeasures && risk.mitigationMeasures.length > 0 && (
414
+ <div className="mt-2">
415
+ <p className="text-sm font-medium">Mitigation Measures:</p>
416
+ <ul className="list-disc pl-5 text-sm">
417
+ {risk.mitigationMeasures.map((measure, idx) => (
418
+ <li key={idx}>{measure}</li>
419
+ ))}
420
+ </ul>
421
+ </div>
422
+ )}
423
+ </li>
424
+ ))}
425
+ </ul>
426
+ </div>
427
+ </div>
428
+
429
+ <div className="mb-6">
430
+ <h3 className="text-lg font-semibold mb-2">Recommendations</h3>
431
+ <div className="border rounded-md p-4">
432
+ <ul className="list-disc pl-5 space-y-1">
433
+ {assessmentResult.recommendations?.map((rec, idx) => (
434
+ <li key={idx}>{rec}</li>
435
+ ))}
436
+ </ul>
437
+ </div>
438
+ </div>
439
+
440
+ <div className="flex justify-end space-x-4">
441
+ <button
442
+ className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
443
+ onClick={() => window.print()}
444
+ >
445
+ Print Report
446
+ </button>
447
+ <button
448
+ className="px-4 py-2 bg-green-600 text-white rounded hover:bg-green-700"
449
+ onClick={() => {
450
+ const blob = new Blob([JSON.stringify(assessmentResult, null, 2)], { type: 'application/json' });
451
+ const url = URL.createObjectURL(blob);
452
+ const a = document.createElement('a');
453
+ a.href = url;
454
+ a.download = `dpia-report-${new Date().toISOString().split('T')[0]}.json`;
455
+ document.body.appendChild(a);
456
+ a.click();
457
+ document.body.removeChild(a);
458
+ URL.revokeObjectURL(url);
459
+ }}
460
+ >
461
+ Download Report
462
+ </button>
463
+ </div>
464
+ </div>
465
+ ) : (
466
+ <div className="p-4 text-center">
467
+ <p>No assessment data available. Please complete the DPIA form and assessment first.</p>
468
+ </div>
469
+ )}
470
+ </CardContent>
471
+ </Card>
472
+ </TabsContent>
473
+ </Tabs>
474
+
475
+ <div className="mt-10 p-4 bg-gray-100 rounded-lg">
476
+ <h2 className="text-xl font-semibold mb-2">Implementation Notes</h2>
477
+ <p className="mb-4">
478
+ This demo showcases the DPIA components from the NDPR Toolkit:
479
+ </p>
480
+ <ul className="list-disc pl-5 space-y-2">
481
+ <li><code>DPIAForm</code>: For collecting information about data processing activities</li>
482
+ <li><code>DPIAAssessment</code>: For analyzing risks and providing recommendations</li>
483
+ <li><code>DPIAReport</code>: For generating comprehensive DPIA reports</li>
484
+ </ul>
485
+ <p className="mt-4">
486
+ For detailed documentation, see the{' '}
487
+ <Link href="/docs/components/dpia" className="text-blue-600 hover:underline">
488
+ DPIA documentation
489
+ </Link>
490
+ .
491
+ </p>
492
+ </div>
493
+ </div>
494
+ );
495
+ }