@tantainnovative/ndpr-toolkit 1.0.3 → 1.0.4
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/next-env.d.ts +5 -0
- package/package.json +1 -1
- package/.claude/settings.local.json +0 -20
- package/.eslintrc.json +0 -10
- package/.github/workflows/ci.yml +0 -36
- package/.github/workflows/nextjs.yml +0 -104
- package/.husky/commit-msg +0 -4
- package/.husky/pre-commit +0 -4
- package/.lintstagedrc.js +0 -4
- package/.nvmrc +0 -1
- package/.versionrc +0 -17
- package/CLAUDE.md +0 -90
- package/commitlint.config.js +0 -36
- package/eslint.config.mjs +0 -16
- package/jest.config.js +0 -31
- package/jest.setup.js +0 -15
- package/next.config.js +0 -15
- package/next.config.ts +0 -62
- package/packages/ndpr-toolkit/README.md +0 -467
- package/packages/ndpr-toolkit/jest.config.js +0 -23
- package/packages/ndpr-toolkit/package-lock.json +0 -8197
- package/packages/ndpr-toolkit/package.json +0 -71
- package/packages/ndpr-toolkit/rollup.config.js +0 -34
- package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentBanner.test.tsx +0 -119
- package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentManager.test.tsx +0 -122
- package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentStorage.test.tsx +0 -270
- package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRDashboard.test.tsx +0 -199
- package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRRequestForm.test.tsx +0 -224
- package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRTracker.test.tsx +0 -104
- package/packages/ndpr-toolkit/src/__tests__/hooks/useConsent.test.tsx +0 -161
- package/packages/ndpr-toolkit/src/__tests__/hooks/useDSR.test.tsx +0 -330
- package/packages/ndpr-toolkit/src/__tests__/utils/breach.test.ts +0 -149
- package/packages/ndpr-toolkit/src/__tests__/utils/consent.test.ts +0 -88
- package/packages/ndpr-toolkit/src/__tests__/utils/dpia.test.ts +0 -160
- package/packages/ndpr-toolkit/src/__tests__/utils/dsr.test.ts +0 -110
- package/packages/ndpr-toolkit/src/__tests__/utils/privacy.test.ts +0 -97
- package/packages/ndpr-toolkit/src/components/breach/BreachNotificationManager.tsx +0 -701
- package/packages/ndpr-toolkit/src/components/breach/BreachReportForm.tsx +0 -631
- package/packages/ndpr-toolkit/src/components/breach/BreachRiskAssessment.tsx +0 -569
- package/packages/ndpr-toolkit/src/components/breach/RegulatoryReportGenerator.tsx +0 -496
- package/packages/ndpr-toolkit/src/components/consent/ConsentBanner.tsx +0 -270
- package/packages/ndpr-toolkit/src/components/consent/ConsentManager.tsx +0 -217
- package/packages/ndpr-toolkit/src/components/consent/ConsentStorage.tsx +0 -206
- package/packages/ndpr-toolkit/src/components/dpia/DPIAQuestionnaire.tsx +0 -342
- package/packages/ndpr-toolkit/src/components/dpia/DPIAReport.tsx +0 -373
- package/packages/ndpr-toolkit/src/components/dpia/StepIndicator.tsx +0 -174
- package/packages/ndpr-toolkit/src/components/dsr/DSRDashboard.tsx +0 -717
- package/packages/ndpr-toolkit/src/components/dsr/DSRRequestForm.tsx +0 -476
- package/packages/ndpr-toolkit/src/components/dsr/DSRTracker.tsx +0 -620
- package/packages/ndpr-toolkit/src/components/policy/PolicyExporter.tsx +0 -541
- package/packages/ndpr-toolkit/src/components/policy/PolicyGenerator.tsx +0 -454
- package/packages/ndpr-toolkit/src/components/policy/PolicyPreview.tsx +0 -333
- package/packages/ndpr-toolkit/src/hooks/useBreach.ts +0 -409
- package/packages/ndpr-toolkit/src/hooks/useConsent.ts +0 -263
- package/packages/ndpr-toolkit/src/hooks/useDPIA.ts +0 -457
- package/packages/ndpr-toolkit/src/hooks/useDSR.ts +0 -236
- package/packages/ndpr-toolkit/src/hooks/usePrivacyPolicy.ts +0 -428
- package/packages/ndpr-toolkit/src/index.ts +0 -44
- package/packages/ndpr-toolkit/src/setupTests.ts +0 -5
- package/packages/ndpr-toolkit/src/types/breach.ts +0 -283
- package/packages/ndpr-toolkit/src/types/consent.ts +0 -111
- package/packages/ndpr-toolkit/src/types/dpia.ts +0 -236
- package/packages/ndpr-toolkit/src/types/dsr.ts +0 -192
- package/packages/ndpr-toolkit/src/types/index.ts +0 -42
- package/packages/ndpr-toolkit/src/types/privacy.ts +0 -246
- package/packages/ndpr-toolkit/src/utils/breach.ts +0 -122
- package/packages/ndpr-toolkit/src/utils/consent.ts +0 -51
- package/packages/ndpr-toolkit/src/utils/dpia.ts +0 -104
- package/packages/ndpr-toolkit/src/utils/dsr.ts +0 -77
- package/packages/ndpr-toolkit/src/utils/privacy.ts +0 -100
- package/packages/ndpr-toolkit/tsconfig.json +0 -23
- package/postcss.config.mjs +0 -5
- package/src/__tests__/example.test.ts +0 -13
- package/src/__tests__/requestService.test.ts +0 -57
- package/src/app/accessibility.css +0 -70
- package/src/app/docs/components/DocLayout.tsx +0 -267
- package/src/app/docs/components/breach-notification/page.tsx +0 -797
- package/src/app/docs/components/consent-management/page.tsx +0 -576
- package/src/app/docs/components/data-subject-rights/page.tsx +0 -511
- package/src/app/docs/components/dpia-questionnaire/layout.tsx +0 -15
- package/src/app/docs/components/dpia-questionnaire/metadata.ts +0 -31
- package/src/app/docs/components/dpia-questionnaire/page.tsx +0 -666
- package/src/app/docs/components/hooks/page.tsx +0 -305
- package/src/app/docs/components/page.tsx +0 -84
- package/src/app/docs/components/privacy-policy-generator/page.tsx +0 -634
- package/src/app/docs/guides/breach-notification-process/components/BestPractices.tsx +0 -123
- package/src/app/docs/guides/breach-notification-process/components/ImplementationSteps.tsx +0 -328
- package/src/app/docs/guides/breach-notification-process/components/Introduction.tsx +0 -28
- package/src/app/docs/guides/breach-notification-process/components/NotificationTimeline.tsx +0 -91
- package/src/app/docs/guides/breach-notification-process/components/Resources.tsx +0 -118
- package/src/app/docs/guides/breach-notification-process/page.tsx +0 -39
- package/src/app/docs/guides/conducting-dpia/page.tsx +0 -593
- package/src/app/docs/guides/data-subject-requests/page.tsx +0 -666
- package/src/app/docs/guides/managing-consent/page.tsx +0 -738
- package/src/app/docs/guides/ndpr-compliance-checklist/components/ComplianceChecklist.tsx +0 -296
- package/src/app/docs/guides/ndpr-compliance-checklist/components/ImplementationTools.tsx +0 -145
- package/src/app/docs/guides/ndpr-compliance-checklist/components/Introduction.tsx +0 -33
- package/src/app/docs/guides/ndpr-compliance-checklist/components/KeyRequirements.tsx +0 -99
- package/src/app/docs/guides/ndpr-compliance-checklist/components/Resources.tsx +0 -159
- package/src/app/docs/guides/ndpr-compliance-checklist/page.tsx +0 -38
- package/src/app/docs/guides/page.tsx +0 -67
- package/src/app/docs/layout.tsx +0 -15
- package/src/app/docs/metadata.ts +0 -31
- package/src/app/docs/page.tsx +0 -572
- package/src/app/favicon.ico +0 -0
- package/src/app/globals.css +0 -123
- package/src/app/layout.tsx +0 -37
- package/src/app/ndpr-demos/breach/page.tsx +0 -354
- package/src/app/ndpr-demos/consent/page.tsx +0 -366
- package/src/app/ndpr-demos/dpia/page.tsx +0 -495
- package/src/app/ndpr-demos/dsr/page.tsx +0 -280
- package/src/app/ndpr-demos/page.tsx +0 -73
- package/src/app/ndpr-demos/policy/page.tsx +0 -771
- package/src/app/page.tsx +0 -452
- package/src/components/ErrorBoundary.tsx +0 -90
- package/src/components/breach-notification/BreachNotificationForm.tsx +0 -479
- package/src/components/consent/ConsentBanner.tsx +0 -159
- package/src/components/data-subject-rights/DataSubjectRequestForm.tsx +0 -419
- package/src/components/docs/DocLayout.tsx +0 -289
- package/src/components/docs/index.ts +0 -2
- package/src/components/dpia/DPIAQuestionnaire.tsx +0 -483
- package/src/components/privacy-policy/PolicyGenerator.tsx +0 -1062
- package/src/components/privacy-policy/data.ts +0 -98
- package/src/components/privacy-policy/shared/CheckboxField.tsx +0 -38
- package/src/components/privacy-policy/shared/CheckboxGroup.tsx +0 -85
- package/src/components/privacy-policy/shared/FormField.tsx +0 -79
- package/src/components/privacy-policy/shared/StepIndicator.tsx +0 -86
- package/src/components/privacy-policy/steps/CustomSectionsStep.tsx +0 -335
- package/src/components/privacy-policy/steps/DataCollectionStep.tsx +0 -231
- package/src/components/privacy-policy/steps/DataSharingStep.tsx +0 -418
- package/src/components/privacy-policy/steps/OrganizationInfoStep.tsx +0 -202
- package/src/components/privacy-policy/steps/PolicyPreviewStep.tsx +0 -172
- package/src/components/ui/Badge.tsx +0 -46
- package/src/components/ui/Button.tsx +0 -59
- package/src/components/ui/Card.tsx +0 -92
- package/src/components/ui/Checkbox.tsx +0 -57
- package/src/components/ui/FormField.tsx +0 -50
- package/src/components/ui/Input.tsx +0 -38
- package/src/components/ui/Loading.tsx +0 -201
- package/src/components/ui/Select.tsx +0 -42
- package/src/components/ui/TextArea.tsx +0 -38
- package/src/components/ui/label.tsx +0 -24
- package/src/components/ui/switch.tsx +0 -31
- package/src/components/ui/tabs.tsx +0 -66
- package/src/hooks/useConsent.ts +0 -64
- package/src/hooks/useLoadingState.ts +0 -85
- package/src/lib/consentService.ts +0 -137
- package/src/lib/dpiaQuestions.ts +0 -148
- package/src/lib/requestService.ts +0 -75
- package/src/lib/sanitize.ts +0 -108
- package/src/lib/storage.ts +0 -222
- package/src/lib/utils.ts +0 -6
- package/src/types/html-to-docx.d.ts +0 -30
- package/src/types/index.ts +0 -72
- package/tailwind.config.ts +0 -65
- package/tsconfig.json +0 -41
|
@@ -1,335 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React, { useRef, useState } from 'react';
|
|
4
|
-
import { FormField } from '@/components/ui/FormField';
|
|
5
|
-
import { Button } from '@/components/ui/Button';
|
|
6
|
-
import { Input } from '@/components/ui/Input';
|
|
7
|
-
import { TextArea } from '@/components/ui/TextArea';
|
|
8
|
-
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/Card';
|
|
9
|
-
import { Select } from '@/components/ui/Select';
|
|
10
|
-
|
|
11
|
-
interface CustomSectionsStepProps {
|
|
12
|
-
formData: {
|
|
13
|
-
customSections: { title: string; template: string }[];
|
|
14
|
-
industryCategory: string;
|
|
15
|
-
includeNDPRCompliance: boolean;
|
|
16
|
-
};
|
|
17
|
-
onAddCustomSection: (title: string, template: string) => void;
|
|
18
|
-
onRemoveCustomSection: (index: number) => void;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
interface TemplateSectionType {
|
|
22
|
-
id: string;
|
|
23
|
-
title: string;
|
|
24
|
-
description: string;
|
|
25
|
-
content: string;
|
|
26
|
-
categories: string[];
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export default function CustomSectionsStep({
|
|
30
|
-
formData,
|
|
31
|
-
onAddCustomSection,
|
|
32
|
-
onRemoveCustomSection,
|
|
33
|
-
}: CustomSectionsStepProps) {
|
|
34
|
-
const titleInputRef = useRef<HTMLInputElement>(null);
|
|
35
|
-
const contentInputRef = useRef<HTMLTextAreaElement>(null);
|
|
36
|
-
const [selectedTemplate, setSelectedTemplate] = useState<string>('');
|
|
37
|
-
const [showTemplateContent, setShowTemplateContent] = useState<boolean>(false);
|
|
38
|
-
|
|
39
|
-
// Template sections that can be added to the policy
|
|
40
|
-
const templateSections: TemplateSectionType[] = [
|
|
41
|
-
{
|
|
42
|
-
id: 'gdpr-compliance',
|
|
43
|
-
title: 'GDPR Compliance',
|
|
44
|
-
description: 'Information about compliance with the EU General Data Protection Regulation',
|
|
45
|
-
content: `In addition to complying with the Nigeria Data Protection Regulation (NDPR) and Data Protection Act (DPA), we also adhere to the European Union's General Data Protection Regulation (GDPR) for users from the European Economic Area (EEA).
|
|
46
|
-
|
|
47
|
-
When processing personal data of individuals in the EEA, we ensure that:
|
|
48
|
-
- We have a lawful basis for processing
|
|
49
|
-
- We implement appropriate technical and organizational measures
|
|
50
|
-
- We facilitate the exercise of data subject rights
|
|
51
|
-
- We have appropriate data transfer mechanisms in place
|
|
52
|
-
- We maintain records of processing activities
|
|
53
|
-
|
|
54
|
-
For more information about our GDPR compliance measures, please contact us at the details provided in the 'Contact Us' section.`,
|
|
55
|
-
categories: ['All'],
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
id: 'california-privacy-rights',
|
|
59
|
-
title: 'California Privacy Rights',
|
|
60
|
-
description: 'Information about compliance with California privacy laws (CCPA/CPRA)',
|
|
61
|
-
content: `If you are a California resident, you have specific rights under California privacy laws, including the California Consumer Privacy Act (CCPA) and the California Privacy Rights Act (CPRA).
|
|
62
|
-
|
|
63
|
-
As a California resident, you have the right to:
|
|
64
|
-
- Know what personal information we collect about you
|
|
65
|
-
- Request deletion of your personal information
|
|
66
|
-
- Opt-out of the sale or sharing of your personal information
|
|
67
|
-
- Limit the use of your sensitive personal information
|
|
68
|
-
- Non-discrimination for exercising your rights
|
|
69
|
-
|
|
70
|
-
To exercise your California privacy rights, please contact us using the information in the 'Contact Us' section. We will respond to verifiable consumer requests within 45 days.`,
|
|
71
|
-
categories: ['All'],
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
id: 'mobile-app-privacy',
|
|
75
|
-
title: 'Mobile Application Privacy',
|
|
76
|
-
description: 'Privacy information specific to mobile applications',
|
|
77
|
-
content: `Our mobile application collects and processes personal data as described in this Privacy Policy. In addition to the information outlined elsewhere in this policy, our mobile application may:
|
|
78
|
-
|
|
79
|
-
- Access your device's camera, microphone, or other sensors with your permission
|
|
80
|
-
- Collect device identifiers such as device ID, advertising ID, or similar identifiers
|
|
81
|
-
- Access your location data (precise or approximate) with your permission
|
|
82
|
-
- Collect information about your mobile network and internet connection
|
|
83
|
-
|
|
84
|
-
You can control these permissions through your device settings. If you choose to deny certain permissions, some features of the application may not be available or may have limited functionality.`,
|
|
85
|
-
categories: ['All'],
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
id: 'social-media-integration',
|
|
89
|
-
title: 'Social Media Integration',
|
|
90
|
-
description: 'Information about social media features and widgets',
|
|
91
|
-
content: `Our services may include social media features, such as the Facebook Like button, and widgets, such as the Share button. These features may collect your IP address, which page you are visiting, and may set a cookie to enable the feature to function properly.
|
|
92
|
-
|
|
93
|
-
Social media features and widgets are either hosted by a third party or hosted directly on our site. Your interactions with these features are governed by the privacy policy of the company providing it.
|
|
94
|
-
|
|
95
|
-
If you choose to connect your account with us to a social media account, we may receive personal information about you from the social media provider, including your profile information, friends or connections list, and other information you have permitted the social media provider to share with third parties.`,
|
|
96
|
-
categories: ['All'],
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
id: 'ecommerce-payments',
|
|
100
|
-
title: 'Payment Processing',
|
|
101
|
-
description: 'Information about payment processing and financial data',
|
|
102
|
-
content: `When you make a purchase through our services, your payment information is processed by our payment service providers. We do not store complete credit card or debit card details on our servers.
|
|
103
|
-
|
|
104
|
-
Our payment processors collect and store your payment information in accordance with industry standards and applicable regulations, including the Payment Card Industry Data Security Standard (PCI DSS).
|
|
105
|
-
|
|
106
|
-
We may retain certain information about your transactions, such as the date and amount of the purchase, the items purchased, and your billing and shipping information, for record-keeping, accounting, and legal compliance purposes.`,
|
|
107
|
-
categories: ['E-commerce and retail', 'Financial services and fintech'],
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
id: 'healthcare-privacy',
|
|
111
|
-
title: 'Healthcare Information Privacy',
|
|
112
|
-
description: 'Information about healthcare data protection (relevant for healthcare organizations)',
|
|
113
|
-
content: `We understand the sensitive nature of health information and are committed to protecting the privacy and security of your health data. We implement specific measures to safeguard health information in accordance with applicable healthcare privacy laws.
|
|
114
|
-
|
|
115
|
-
We only collect health information with your explicit consent or when necessary to provide our healthcare services. We limit access to health information to authorized personnel who need it to perform their duties.
|
|
116
|
-
|
|
117
|
-
We do not use or disclose your health information for marketing purposes without your explicit consent. We maintain audit trails of access to health information and regularly review our security practices to ensure the ongoing protection of your health data.`,
|
|
118
|
-
categories: ['Healthcare and medical'],
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
id: 'educational-privacy',
|
|
122
|
-
title: 'Educational Records Privacy',
|
|
123
|
-
description: 'Information about educational data protection (relevant for educational institutions)',
|
|
124
|
-
content: `We are committed to protecting the privacy of educational records and student information. We collect and process educational data only for legitimate educational purposes and in accordance with applicable education privacy laws.
|
|
125
|
-
|
|
126
|
-
We implement specific measures to safeguard educational records, including:
|
|
127
|
-
- Limiting access to authorized personnel with a legitimate educational interest
|
|
128
|
-
- Obtaining appropriate consents for certain uses of student information
|
|
129
|
-
- Providing access to students or parents/guardians to review and correct educational records
|
|
130
|
-
- Implementing security measures specific to the protection of educational data
|
|
131
|
-
|
|
132
|
-
We do not use student information for targeted advertising purposes or sell student information to third parties.`,
|
|
133
|
-
categories: ['Education and e-learning'],
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
id: 'ndpr-dpa-details',
|
|
137
|
-
title: 'NDPR and DPA Compliance Details',
|
|
138
|
-
description: 'Detailed information about compliance with Nigerian data protection laws',
|
|
139
|
-
content: `We are committed to full compliance with the Nigeria Data Protection Regulation (NDPR) of 2019 and the Data Protection Act (DPA) of 2023. Our compliance measures include:
|
|
140
|
-
|
|
141
|
-
1. **Data Protection Officer**: We have appointed a Data Protection Officer responsible for overseeing our data protection strategy and implementation.
|
|
142
|
-
|
|
143
|
-
2. **Data Protection Impact Assessments**: We conduct DPIAs for high-risk processing activities as required by Section 2.4 of the NDPR and Section 38 of the DPA.
|
|
144
|
-
|
|
145
|
-
3. **Data Protection Audit**: We conduct annual data protection audits and file audit reports with the Nigeria Data Protection Commission as required by Section 4.1 of the NDPR.
|
|
146
|
-
|
|
147
|
-
4. **Data Subject Access Request Procedure**: We have implemented a clear procedure for handling data subject access requests within the 30-day timeframe specified in Section 3.1(7) of the NDPR.
|
|
148
|
-
|
|
149
|
-
5. **Data Breach Notification**: We have established procedures to notify the Nigeria Data Protection Commission and affected data subjects of any data breaches within 72 hours, as required by Section 2.10 of the NDPR and Section 40 of the DPA.
|
|
150
|
-
|
|
151
|
-
6. **Training and Awareness**: We provide regular training to our staff on data protection principles and practices.
|
|
152
|
-
|
|
153
|
-
7. **Data Processing Agreements**: We enter into written agreements with all data processors as required by Section 2.7 of the NDPR and Section 37 of the DPA.
|
|
154
|
-
|
|
155
|
-
For more information about our NDPR and DPA compliance program, please contact our Data Protection Officer.`,
|
|
156
|
-
categories: ['All'],
|
|
157
|
-
},
|
|
158
|
-
];
|
|
159
|
-
|
|
160
|
-
// Filter template sections based on industry category
|
|
161
|
-
const filteredTemplateSections = templateSections.filter(template =>
|
|
162
|
-
template.categories.includes('All') || template.categories.includes(formData.industryCategory)
|
|
163
|
-
);
|
|
164
|
-
|
|
165
|
-
// Handle adding a template section
|
|
166
|
-
const handleAddTemplateSection = () => {
|
|
167
|
-
if (selectedTemplate) {
|
|
168
|
-
const template = templateSections.find(t => t.id === selectedTemplate);
|
|
169
|
-
if (template) {
|
|
170
|
-
onAddCustomSection(template.title, template.content);
|
|
171
|
-
setSelectedTemplate('');
|
|
172
|
-
setShowTemplateContent(false);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
// Handle adding a custom section
|
|
178
|
-
const handleAddCustomSection = () => {
|
|
179
|
-
if (titleInputRef.current && contentInputRef.current &&
|
|
180
|
-
titleInputRef.current.value.trim() && contentInputRef.current.value.trim()) {
|
|
181
|
-
onAddCustomSection(titleInputRef.current.value.trim(), contentInputRef.current.value.trim());
|
|
182
|
-
titleInputRef.current.value = '';
|
|
183
|
-
contentInputRef.current.value = '';
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
return (
|
|
188
|
-
<div className="space-y-8">
|
|
189
|
-
<Card className="overflow-hidden shadow-md border border-gray-200 dark:border-gray-700">
|
|
190
|
-
<CardHeader className="bg-gradient-to-r from-slate-100 to-gray-100 dark:from-slate-800 dark:to-gray-800 pb-3">
|
|
191
|
-
<CardTitle className="text-lg font-semibold text-gray-800 dark:text-white">Template Sections</CardTitle>
|
|
192
|
-
<CardDescription className="text-sm text-gray-600 dark:text-gray-300">
|
|
193
|
-
Add pre-written sections to your privacy policy
|
|
194
|
-
</CardDescription>
|
|
195
|
-
</CardHeader>
|
|
196
|
-
<CardContent className="pt-5">
|
|
197
|
-
<div className="space-y-3">
|
|
198
|
-
<FormField
|
|
199
|
-
id="templateSection"
|
|
200
|
-
label="Select a Template Section"
|
|
201
|
-
>
|
|
202
|
-
<Select
|
|
203
|
-
id="templateSection"
|
|
204
|
-
value={selectedTemplate}
|
|
205
|
-
onChange={(e) => {
|
|
206
|
-
setSelectedTemplate(e.target.value);
|
|
207
|
-
setShowTemplateContent(!!e.target.value);
|
|
208
|
-
}}
|
|
209
|
-
>
|
|
210
|
-
<option value="">-- Select a template section --</option>
|
|
211
|
-
{filteredTemplateSections.map((template) => (
|
|
212
|
-
<option key={template.id} value={template.id}>
|
|
213
|
-
{template.title} - {template.description}
|
|
214
|
-
</option>
|
|
215
|
-
))}
|
|
216
|
-
</Select>
|
|
217
|
-
</FormField>
|
|
218
|
-
|
|
219
|
-
{showTemplateContent && selectedTemplate && (
|
|
220
|
-
<div className="mt-3 bg-white dark:bg-gray-800 p-3 rounded border border-gray-200 dark:border-gray-600">
|
|
221
|
-
<h5 className="font-medium text-gray-900 dark:text-white mb-2">
|
|
222
|
-
{templateSections.find(t => t.id === selectedTemplate)?.title}
|
|
223
|
-
</h5>
|
|
224
|
-
<div className="text-sm text-gray-700 dark:text-gray-300 whitespace-pre-line max-h-40 overflow-y-auto">
|
|
225
|
-
{templateSections.find(t => t.id === selectedTemplate)?.content}
|
|
226
|
-
</div>
|
|
227
|
-
</div>
|
|
228
|
-
)}
|
|
229
|
-
|
|
230
|
-
<Button
|
|
231
|
-
variant="default"
|
|
232
|
-
size="sm"
|
|
233
|
-
disabled={!selectedTemplate}
|
|
234
|
-
onClick={handleAddTemplateSection}
|
|
235
|
-
>
|
|
236
|
-
Add Template Section
|
|
237
|
-
</Button>
|
|
238
|
-
</div>
|
|
239
|
-
</CardContent>
|
|
240
|
-
</Card>
|
|
241
|
-
|
|
242
|
-
{/* Custom Sections */}
|
|
243
|
-
<Card className="overflow-hidden shadow-md border border-gray-200 dark:border-gray-700">
|
|
244
|
-
<CardHeader className="bg-gradient-to-r from-slate-100 to-gray-100 dark:from-slate-800 dark:to-gray-800 pb-3">
|
|
245
|
-
<CardTitle className="text-lg font-semibold text-gray-800 dark:text-white">Create Custom Section</CardTitle>
|
|
246
|
-
<CardDescription className="text-sm text-gray-600 dark:text-gray-300">
|
|
247
|
-
Add your own custom section to the privacy policy
|
|
248
|
-
</CardDescription>
|
|
249
|
-
</CardHeader>
|
|
250
|
-
<CardContent className="pt-5">
|
|
251
|
-
<div className="space-y-3">
|
|
252
|
-
<FormField
|
|
253
|
-
id="customSectionTitle"
|
|
254
|
-
label="Section Title"
|
|
255
|
-
>
|
|
256
|
-
<Input
|
|
257
|
-
id="customSectionTitle"
|
|
258
|
-
ref={titleInputRef}
|
|
259
|
-
placeholder="e.g., Cookies Policy, International Transfers"
|
|
260
|
-
/>
|
|
261
|
-
</FormField>
|
|
262
|
-
|
|
263
|
-
<FormField
|
|
264
|
-
id="customSectionContent"
|
|
265
|
-
label="Section Content"
|
|
266
|
-
>
|
|
267
|
-
<TextArea
|
|
268
|
-
id="customSectionContent"
|
|
269
|
-
ref={contentInputRef}
|
|
270
|
-
rows={5}
|
|
271
|
-
placeholder="Enter the content for this section..."
|
|
272
|
-
/>
|
|
273
|
-
</FormField>
|
|
274
|
-
|
|
275
|
-
<Button
|
|
276
|
-
variant="default"
|
|
277
|
-
size="sm"
|
|
278
|
-
onClick={handleAddCustomSection}
|
|
279
|
-
>
|
|
280
|
-
Add Custom Section
|
|
281
|
-
</Button>
|
|
282
|
-
</div>
|
|
283
|
-
</CardContent>
|
|
284
|
-
</Card>
|
|
285
|
-
|
|
286
|
-
{/* Added Sections List */}
|
|
287
|
-
{formData.customSections.length > 0 && (
|
|
288
|
-
<Card className="overflow-hidden shadow-md border border-gray-200 dark:border-gray-700">
|
|
289
|
-
<CardHeader className="bg-gradient-to-r from-slate-100 to-gray-100 dark:from-slate-800 dark:to-gray-800 pb-3">
|
|
290
|
-
<CardTitle className="text-lg font-semibold text-gray-800 dark:text-white">Added Custom Sections</CardTitle>
|
|
291
|
-
<CardDescription className="text-sm text-gray-600 dark:text-gray-300">
|
|
292
|
-
Custom sections that will be included in your privacy policy
|
|
293
|
-
</CardDescription>
|
|
294
|
-
</CardHeader>
|
|
295
|
-
<CardContent className="pt-5">
|
|
296
|
-
<ul className="space-y-3">
|
|
297
|
-
{formData.customSections.map((section, index) => (
|
|
298
|
-
<Card key={index} className="overflow-visible">
|
|
299
|
-
<CardContent className="pt-4">
|
|
300
|
-
<div className="flex items-center justify-between mb-2">
|
|
301
|
-
<h5 className="font-medium text-gray-900 dark:text-white">{section.title}</h5>
|
|
302
|
-
<Button
|
|
303
|
-
variant="destructive"
|
|
304
|
-
size="sm"
|
|
305
|
-
onClick={() => onRemoveCustomSection(index)}
|
|
306
|
-
className="text-red-500 hover:text-red-700"
|
|
307
|
-
>
|
|
308
|
-
Remove
|
|
309
|
-
</Button>
|
|
310
|
-
</div>
|
|
311
|
-
<div className="text-sm text-gray-700 dark:text-gray-300 whitespace-pre-line max-h-32 overflow-y-auto">
|
|
312
|
-
{section.template.length > 200
|
|
313
|
-
? `${section.template.substring(0, 200)}...`
|
|
314
|
-
: section.template}
|
|
315
|
-
</div>
|
|
316
|
-
{section.template.length > 200 && (
|
|
317
|
-
<Button
|
|
318
|
-
variant="link"
|
|
319
|
-
size="sm"
|
|
320
|
-
onClick={() => alert(section.template)}
|
|
321
|
-
className="mt-2 p-0"
|
|
322
|
-
>
|
|
323
|
-
View Full Content
|
|
324
|
-
</Button>
|
|
325
|
-
)}
|
|
326
|
-
</CardContent>
|
|
327
|
-
</Card>
|
|
328
|
-
))}
|
|
329
|
-
</ul>
|
|
330
|
-
</CardContent>
|
|
331
|
-
</Card>
|
|
332
|
-
)}
|
|
333
|
-
</div>
|
|
334
|
-
);
|
|
335
|
-
}
|
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import CheckboxGroup from '../shared/CheckboxGroup';
|
|
5
|
-
import FormField from '../shared/FormField';
|
|
6
|
-
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/Card';
|
|
7
|
-
import { Select } from '@/components/ui/Select';
|
|
8
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
9
|
-
import { cn } from '@/lib/utils';
|
|
10
|
-
|
|
11
|
-
interface DataCollectionStepProps {
|
|
12
|
-
formData: {
|
|
13
|
-
dataCollectionPurposes: string[];
|
|
14
|
-
dataRetentionPeriod: string;
|
|
15
|
-
securityMeasures: string[];
|
|
16
|
-
dataSubjects: string[];
|
|
17
|
-
dataCategories: string[];
|
|
18
|
-
legalBasisForProcessing: string[];
|
|
19
|
-
};
|
|
20
|
-
errors: Record<string, string>;
|
|
21
|
-
onChange: (e: React.ChangeEvent<HTMLSelectElement>) => void;
|
|
22
|
-
onToggleItem: (
|
|
23
|
-
category:
|
|
24
|
-
'dataCollectionPurposes' |
|
|
25
|
-
'securityMeasures' |
|
|
26
|
-
'dataSubjects' |
|
|
27
|
-
'dataCategories' |
|
|
28
|
-
'legalBasisForProcessing',
|
|
29
|
-
item: string
|
|
30
|
-
) => void;
|
|
31
|
-
defaultDataPurposes: string[];
|
|
32
|
-
defaultSecurityMeasures: string[];
|
|
33
|
-
dataSubjectCategories: string[];
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export default function DataCollectionStep({
|
|
37
|
-
formData,
|
|
38
|
-
errors,
|
|
39
|
-
onChange,
|
|
40
|
-
onToggleItem,
|
|
41
|
-
defaultDataPurposes,
|
|
42
|
-
defaultSecurityMeasures,
|
|
43
|
-
dataSubjectCategories,
|
|
44
|
-
}: DataCollectionStepProps) {
|
|
45
|
-
// Define legal basis options
|
|
46
|
-
const legalBasisOptions = [
|
|
47
|
-
'Consent of the data subject',
|
|
48
|
-
'Performance of a contract',
|
|
49
|
-
'Compliance with a legal obligation',
|
|
50
|
-
'Protection of vital interests',
|
|
51
|
-
'Performance of a task in the public interest',
|
|
52
|
-
'Legitimate interests pursued by the controller',
|
|
53
|
-
'Explicit consent for special categories',
|
|
54
|
-
'Employment and social security purposes',
|
|
55
|
-
'Vital interests where consent cannot be given',
|
|
56
|
-
'Processing by non-profit bodies',
|
|
57
|
-
'Data made public by the data subject',
|
|
58
|
-
'Legal claims or judicial acts',
|
|
59
|
-
'Substantial public interest',
|
|
60
|
-
'Preventive or occupational medicine',
|
|
61
|
-
'Public health',
|
|
62
|
-
'Archiving, research and statistics'
|
|
63
|
-
];
|
|
64
|
-
|
|
65
|
-
// Define data categories
|
|
66
|
-
const dataCategories = [
|
|
67
|
-
'Personal identifiers (name, email, phone)',
|
|
68
|
-
'Contact information',
|
|
69
|
-
'Location data',
|
|
70
|
-
'Financial information',
|
|
71
|
-
'Transaction data',
|
|
72
|
-
'Technical data (IP address, device info)',
|
|
73
|
-
'Profile data',
|
|
74
|
-
'Usage data',
|
|
75
|
-
'Marketing preferences',
|
|
76
|
-
'Communications data',
|
|
77
|
-
'Employment information',
|
|
78
|
-
'Education information',
|
|
79
|
-
'Biometric data',
|
|
80
|
-
'Health data',
|
|
81
|
-
'Government identifiers'
|
|
82
|
-
];
|
|
83
|
-
|
|
84
|
-
return (
|
|
85
|
-
<div className="space-y-8">
|
|
86
|
-
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
87
|
-
{/* Left Column */}
|
|
88
|
-
<div className="space-y-6">
|
|
89
|
-
<Card className="overflow-hidden shadow-md border border-gray-200 dark:border-gray-700">
|
|
90
|
-
<CardHeader className="bg-gradient-to-r from-slate-100 to-gray-100 dark:from-slate-800 dark:to-gray-800 pb-3">
|
|
91
|
-
<CardTitle className="text-lg font-semibold text-gray-800 dark:text-white">Data Collection Purposes</CardTitle>
|
|
92
|
-
<CardDescription className="text-sm text-gray-600 dark:text-gray-300">
|
|
93
|
-
Select all the purposes for which you collect personal data
|
|
94
|
-
</CardDescription>
|
|
95
|
-
</CardHeader>
|
|
96
|
-
<CardContent className="pt-5">
|
|
97
|
-
<CheckboxGroup
|
|
98
|
-
title=""
|
|
99
|
-
items={defaultDataPurposes}
|
|
100
|
-
selectedItems={formData.dataCollectionPurposes}
|
|
101
|
-
onToggleItem={(item) => onToggleItem('dataCollectionPurposes', item)}
|
|
102
|
-
required
|
|
103
|
-
error={errors.dataCollectionPurposes}
|
|
104
|
-
columns={1}
|
|
105
|
-
className="space-y-1"
|
|
106
|
-
/>
|
|
107
|
-
</CardContent>
|
|
108
|
-
</Card>
|
|
109
|
-
|
|
110
|
-
<Card className="overflow-hidden shadow-md border border-gray-200 dark:border-gray-700">
|
|
111
|
-
<CardHeader className="bg-gradient-to-r from-slate-100 to-gray-100 dark:from-slate-800 dark:to-gray-800 pb-3">
|
|
112
|
-
<CardTitle className="text-lg font-semibold text-gray-800 dark:text-white">Data Retention</CardTitle>
|
|
113
|
-
<CardDescription className="text-sm text-gray-600 dark:text-gray-300">
|
|
114
|
-
Specify how long you retain personal data
|
|
115
|
-
</CardDescription>
|
|
116
|
-
</CardHeader>
|
|
117
|
-
<CardContent className="pt-5">
|
|
118
|
-
<FormField
|
|
119
|
-
id="dataRetentionPeriod"
|
|
120
|
-
label="Data Retention Period"
|
|
121
|
-
required
|
|
122
|
-
error={errors.dataRetentionPeriod}
|
|
123
|
-
>
|
|
124
|
-
<Select
|
|
125
|
-
id="dataRetentionPeriod"
|
|
126
|
-
name="dataRetentionPeriod"
|
|
127
|
-
value={formData.dataRetentionPeriod}
|
|
128
|
-
onChange={onChange}
|
|
129
|
-
>
|
|
130
|
-
<option value="">Select a retention period</option>
|
|
131
|
-
<option value="1 year">1 year</option>
|
|
132
|
-
<option value="2 years">2 years</option>
|
|
133
|
-
<option value="3 years">3 years</option>
|
|
134
|
-
<option value="5 years">5 years</option>
|
|
135
|
-
<option value="7 years">7 years</option>
|
|
136
|
-
<option value="10 years">10 years</option>
|
|
137
|
-
<option value="as long as necessary for the purposes described">As long as necessary</option>
|
|
138
|
-
</Select>
|
|
139
|
-
</FormField>
|
|
140
|
-
</CardContent>
|
|
141
|
-
</Card>
|
|
142
|
-
|
|
143
|
-
<Card className="overflow-hidden shadow-md border border-gray-200 dark:border-gray-700">
|
|
144
|
-
<CardHeader className="bg-gradient-to-r from-slate-100 to-gray-100 dark:from-slate-800 dark:to-gray-800 pb-3">
|
|
145
|
-
<CardTitle className="text-lg font-semibold text-gray-800 dark:text-white">Data Subjects</CardTitle>
|
|
146
|
-
<CardDescription className="text-sm text-gray-600 dark:text-gray-300">
|
|
147
|
-
Select the categories of individuals whose data you process
|
|
148
|
-
</CardDescription>
|
|
149
|
-
</CardHeader>
|
|
150
|
-
<CardContent className="pt-5">
|
|
151
|
-
<CheckboxGroup
|
|
152
|
-
title=""
|
|
153
|
-
items={dataSubjectCategories}
|
|
154
|
-
selectedItems={formData.dataSubjects}
|
|
155
|
-
onToggleItem={(item) => onToggleItem('dataSubjects', item)}
|
|
156
|
-
required
|
|
157
|
-
error={errors.dataSubjects}
|
|
158
|
-
columns={1}
|
|
159
|
-
className="space-y-1"
|
|
160
|
-
/>
|
|
161
|
-
</CardContent>
|
|
162
|
-
</Card>
|
|
163
|
-
</div>
|
|
164
|
-
|
|
165
|
-
{/* Right Column */}
|
|
166
|
-
<div className="space-y-6">
|
|
167
|
-
<Card className="overflow-hidden shadow-md border border-gray-200 dark:border-gray-700">
|
|
168
|
-
<CardHeader className="bg-gradient-to-r from-slate-100 to-gray-100 dark:from-slate-800 dark:to-gray-800 pb-3">
|
|
169
|
-
<CardTitle className="text-lg font-semibold text-gray-800 dark:text-white">Personal Data Categories</CardTitle>
|
|
170
|
-
<CardDescription className="text-sm text-gray-600 dark:text-gray-300">
|
|
171
|
-
Select the types of personal data you collect
|
|
172
|
-
</CardDescription>
|
|
173
|
-
</CardHeader>
|
|
174
|
-
<CardContent className="pt-5">
|
|
175
|
-
<CheckboxGroup
|
|
176
|
-
title=""
|
|
177
|
-
items={dataCategories}
|
|
178
|
-
selectedItems={formData.dataCategories}
|
|
179
|
-
onToggleItem={(item) => onToggleItem('dataCategories', item)}
|
|
180
|
-
required
|
|
181
|
-
error={errors.dataCategories}
|
|
182
|
-
columns={1}
|
|
183
|
-
className="space-y-1"
|
|
184
|
-
/>
|
|
185
|
-
</CardContent>
|
|
186
|
-
</Card>
|
|
187
|
-
|
|
188
|
-
<Card className="overflow-hidden shadow-md border border-gray-200 dark:border-gray-700">
|
|
189
|
-
<CardHeader className="bg-gradient-to-r from-slate-100 to-gray-100 dark:from-slate-800 dark:to-gray-800 pb-3">
|
|
190
|
-
<CardTitle className="text-lg font-semibold text-gray-800 dark:text-white">Legal Basis</CardTitle>
|
|
191
|
-
<CardDescription className="text-sm text-gray-600 dark:text-gray-300">
|
|
192
|
-
Select the legal grounds for processing personal data
|
|
193
|
-
</CardDescription>
|
|
194
|
-
</CardHeader>
|
|
195
|
-
<CardContent className="pt-5">
|
|
196
|
-
<CheckboxGroup
|
|
197
|
-
title=""
|
|
198
|
-
items={legalBasisOptions}
|
|
199
|
-
selectedItems={formData.legalBasisForProcessing}
|
|
200
|
-
onToggleItem={(item) => onToggleItem('legalBasisForProcessing', item)}
|
|
201
|
-
required
|
|
202
|
-
error={errors.legalBasisForProcessing}
|
|
203
|
-
columns={1}
|
|
204
|
-
className="space-y-1"
|
|
205
|
-
/>
|
|
206
|
-
</CardContent>
|
|
207
|
-
</Card>
|
|
208
|
-
</div>
|
|
209
|
-
</div>
|
|
210
|
-
|
|
211
|
-
<Card className="overflow-hidden shadow-md border border-gray-200 dark:border-gray-700">
|
|
212
|
-
<CardHeader className="bg-gradient-to-r from-slate-100 to-gray-100 dark:from-slate-800 dark:to-gray-800 pb-3">
|
|
213
|
-
<CardTitle className="text-lg font-semibold text-gray-800 dark:text-white">Security Measures</CardTitle>
|
|
214
|
-
<CardDescription className="text-sm text-gray-600 dark:text-gray-300">
|
|
215
|
-
Select the security measures you implement to protect personal data
|
|
216
|
-
</CardDescription>
|
|
217
|
-
</CardHeader>
|
|
218
|
-
<CardContent className="pt-5">
|
|
219
|
-
<CheckboxGroup
|
|
220
|
-
title=""
|
|
221
|
-
items={defaultSecurityMeasures}
|
|
222
|
-
selectedItems={formData.securityMeasures}
|
|
223
|
-
onToggleItem={(item) => onToggleItem('securityMeasures', item)}
|
|
224
|
-
columns={2}
|
|
225
|
-
className="space-y-1"
|
|
226
|
-
/>
|
|
227
|
-
</CardContent>
|
|
228
|
-
</Card>
|
|
229
|
-
</div>
|
|
230
|
-
);
|
|
231
|
-
}
|