@tantainnovative/ndpr-toolkit 1.0.2 → 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.
- package/.claude/settings.local.json +20 -0
- package/.eslintrc.json +10 -0
- package/.github/workflows/ci.yml +36 -0
- package/.github/workflows/nextjs.yml +104 -0
- package/.husky/commit-msg +4 -0
- package/.husky/pre-commit +4 -0
- package/.lintstagedrc.js +4 -0
- package/.nvmrc +1 -0
- package/.versionrc +17 -0
- package/CHANGELOG.md +16 -0
- package/CLAUDE.md +90 -0
- package/CNAME +1 -0
- package/CONTRIBUTING.md +87 -0
- package/README.md +84 -447
- package/RELEASE-NOTES-v1.0.0.md +140 -0
- package/RELEASE-NOTES-v1.0.1.md +69 -0
- package/SECURITY.md +21 -0
- package/commitlint.config.js +36 -0
- package/components.json +21 -0
- package/eslint.config.mjs +16 -0
- package/jest.config.js +31 -0
- package/jest.setup.js +15 -0
- package/next.config.js +15 -0
- package/next.config.ts +62 -0
- package/package.json +70 -52
- package/packages/ndpr-toolkit/README.md +467 -0
- package/packages/ndpr-toolkit/jest.config.js +23 -0
- package/packages/ndpr-toolkit/package-lock.json +8197 -0
- package/packages/ndpr-toolkit/package.json +71 -0
- package/packages/ndpr-toolkit/rollup.config.js +34 -0
- package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentBanner.test.tsx +119 -0
- package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentManager.test.tsx +122 -0
- package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentStorage.test.tsx +270 -0
- package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRDashboard.test.tsx +199 -0
- package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRRequestForm.test.tsx +224 -0
- package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRTracker.test.tsx +104 -0
- package/packages/ndpr-toolkit/src/__tests__/hooks/useConsent.test.tsx +161 -0
- package/packages/ndpr-toolkit/src/__tests__/hooks/useDSR.test.tsx +330 -0
- package/packages/ndpr-toolkit/src/__tests__/utils/breach.test.ts +149 -0
- package/packages/ndpr-toolkit/src/__tests__/utils/consent.test.ts +88 -0
- package/packages/ndpr-toolkit/src/__tests__/utils/dpia.test.ts +160 -0
- package/packages/ndpr-toolkit/src/__tests__/utils/dsr.test.ts +110 -0
- package/packages/ndpr-toolkit/src/__tests__/utils/privacy.test.ts +97 -0
- package/packages/ndpr-toolkit/src/components/breach/BreachNotificationManager.tsx +701 -0
- package/packages/ndpr-toolkit/src/components/breach/BreachReportForm.tsx +631 -0
- package/packages/ndpr-toolkit/src/components/breach/BreachRiskAssessment.tsx +569 -0
- package/packages/ndpr-toolkit/src/components/breach/RegulatoryReportGenerator.tsx +496 -0
- package/packages/ndpr-toolkit/src/components/consent/ConsentBanner.tsx +270 -0
- package/packages/ndpr-toolkit/src/components/consent/ConsentManager.tsx +217 -0
- package/packages/ndpr-toolkit/src/components/consent/ConsentStorage.tsx +206 -0
- package/packages/ndpr-toolkit/src/components/dpia/DPIAQuestionnaire.tsx +342 -0
- package/packages/ndpr-toolkit/src/components/dpia/DPIAReport.tsx +373 -0
- package/packages/ndpr-toolkit/src/components/dpia/StepIndicator.tsx +174 -0
- package/packages/ndpr-toolkit/src/components/dsr/DSRDashboard.tsx +717 -0
- package/packages/ndpr-toolkit/src/components/dsr/DSRRequestForm.tsx +476 -0
- package/packages/ndpr-toolkit/src/components/dsr/DSRTracker.tsx +620 -0
- package/packages/ndpr-toolkit/src/components/policy/PolicyExporter.tsx +541 -0
- package/packages/ndpr-toolkit/src/components/policy/PolicyGenerator.tsx +454 -0
- package/packages/ndpr-toolkit/src/components/policy/PolicyPreview.tsx +333 -0
- package/packages/ndpr-toolkit/src/hooks/useBreach.ts +409 -0
- package/packages/ndpr-toolkit/src/hooks/useConsent.ts +263 -0
- package/packages/ndpr-toolkit/src/hooks/useDPIA.ts +457 -0
- package/packages/ndpr-toolkit/src/hooks/useDSR.ts +236 -0
- package/packages/ndpr-toolkit/src/hooks/usePrivacyPolicy.ts +428 -0
- package/{dist/index.d.ts → packages/ndpr-toolkit/src/index.ts} +13 -0
- package/packages/ndpr-toolkit/src/setupTests.ts +5 -0
- package/packages/ndpr-toolkit/src/types/breach.ts +283 -0
- package/packages/ndpr-toolkit/src/types/consent.ts +111 -0
- package/packages/ndpr-toolkit/src/types/dpia.ts +236 -0
- package/packages/ndpr-toolkit/src/types/dsr.ts +192 -0
- package/packages/ndpr-toolkit/src/types/index.ts +42 -0
- package/packages/ndpr-toolkit/src/types/privacy.ts +246 -0
- package/packages/ndpr-toolkit/src/utils/breach.ts +122 -0
- package/packages/ndpr-toolkit/src/utils/consent.ts +51 -0
- package/packages/ndpr-toolkit/src/utils/dpia.ts +104 -0
- package/packages/ndpr-toolkit/src/utils/dsr.ts +77 -0
- package/packages/ndpr-toolkit/src/utils/privacy.ts +100 -0
- package/packages/ndpr-toolkit/tsconfig.json +23 -0
- package/postcss.config.mjs +5 -0
- package/public/NDPR TOOLKIT.svg +1 -0
- package/public/favicon/android-chrome-192x192.png +0 -0
- package/public/favicon/android-chrome-512x512.png +0 -0
- package/public/favicon/apple-touch-icon.png +0 -0
- package/public/favicon/favicon-16x16.png +0 -0
- package/public/favicon/favicon-32x32.png +0 -0
- package/public/favicon/site.webmanifest +1 -0
- package/public/file.svg +1 -0
- package/public/globe.svg +1 -0
- package/public/ndpr-toolkit-logo.svg +108 -0
- package/public/next.svg +1 -0
- package/public/vercel.svg +1 -0
- package/public/window.svg +1 -0
- package/src/__tests__/example.test.ts +13 -0
- package/src/__tests__/requestService.test.ts +57 -0
- package/src/app/accessibility.css +70 -0
- package/src/app/docs/components/DocLayout.tsx +267 -0
- package/src/app/docs/components/breach-notification/page.tsx +797 -0
- package/src/app/docs/components/consent-management/page.tsx +576 -0
- package/src/app/docs/components/data-subject-rights/page.tsx +511 -0
- package/src/app/docs/components/dpia-questionnaire/layout.tsx +15 -0
- package/src/app/docs/components/dpia-questionnaire/metadata.ts +31 -0
- package/src/app/docs/components/dpia-questionnaire/page.tsx +666 -0
- package/src/app/docs/components/hooks/page.tsx +305 -0
- package/src/app/docs/components/page.tsx +84 -0
- package/src/app/docs/components/privacy-policy-generator/page.tsx +634 -0
- package/src/app/docs/guides/breach-notification-process/components/BestPractices.tsx +123 -0
- package/src/app/docs/guides/breach-notification-process/components/ImplementationSteps.tsx +328 -0
- package/src/app/docs/guides/breach-notification-process/components/Introduction.tsx +28 -0
- package/src/app/docs/guides/breach-notification-process/components/NotificationTimeline.tsx +91 -0
- package/src/app/docs/guides/breach-notification-process/components/Resources.tsx +118 -0
- package/src/app/docs/guides/breach-notification-process/page.tsx +39 -0
- package/src/app/docs/guides/conducting-dpia/page.tsx +593 -0
- package/src/app/docs/guides/data-subject-requests/page.tsx +666 -0
- package/src/app/docs/guides/managing-consent/page.tsx +738 -0
- package/src/app/docs/guides/ndpr-compliance-checklist/components/ComplianceChecklist.tsx +296 -0
- package/src/app/docs/guides/ndpr-compliance-checklist/components/ImplementationTools.tsx +145 -0
- package/src/app/docs/guides/ndpr-compliance-checklist/components/Introduction.tsx +33 -0
- package/src/app/docs/guides/ndpr-compliance-checklist/components/KeyRequirements.tsx +99 -0
- package/src/app/docs/guides/ndpr-compliance-checklist/components/Resources.tsx +159 -0
- package/src/app/docs/guides/ndpr-compliance-checklist/page.tsx +38 -0
- package/src/app/docs/guides/page.tsx +67 -0
- package/src/app/docs/layout.tsx +15 -0
- package/src/app/docs/metadata.ts +31 -0
- package/src/app/docs/page.tsx +572 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/globals.css +123 -0
- package/src/app/layout.tsx +37 -0
- package/src/app/ndpr-demos/breach/page.tsx +354 -0
- package/src/app/ndpr-demos/consent/page.tsx +366 -0
- package/src/app/ndpr-demos/dpia/page.tsx +495 -0
- package/src/app/ndpr-demos/dsr/page.tsx +280 -0
- package/src/app/ndpr-demos/page.tsx +73 -0
- package/src/app/ndpr-demos/policy/page.tsx +771 -0
- package/src/app/page.tsx +452 -0
- package/src/components/ErrorBoundary.tsx +90 -0
- package/src/components/breach-notification/BreachNotificationForm.tsx +479 -0
- package/src/components/consent/ConsentBanner.tsx +159 -0
- package/src/components/data-subject-rights/DataSubjectRequestForm.tsx +419 -0
- package/src/components/docs/DocLayout.tsx +289 -0
- package/src/components/docs/index.ts +2 -0
- package/src/components/dpia/DPIAQuestionnaire.tsx +483 -0
- package/src/components/privacy-policy/PolicyGenerator.tsx +1062 -0
- package/src/components/privacy-policy/data.ts +98 -0
- package/src/components/privacy-policy/shared/CheckboxField.tsx +38 -0
- package/src/components/privacy-policy/shared/CheckboxGroup.tsx +85 -0
- package/src/components/privacy-policy/shared/FormField.tsx +79 -0
- package/src/components/privacy-policy/shared/StepIndicator.tsx +86 -0
- package/src/components/privacy-policy/steps/CustomSectionsStep.tsx +335 -0
- package/src/components/privacy-policy/steps/DataCollectionStep.tsx +231 -0
- package/src/components/privacy-policy/steps/DataSharingStep.tsx +418 -0
- package/src/components/privacy-policy/steps/OrganizationInfoStep.tsx +202 -0
- package/src/components/privacy-policy/steps/PolicyPreviewStep.tsx +172 -0
- package/src/components/ui/Badge.tsx +46 -0
- package/src/components/ui/Button.tsx +59 -0
- package/src/components/ui/Card.tsx +92 -0
- package/src/components/ui/Checkbox.tsx +57 -0
- package/src/components/ui/FormField.tsx +50 -0
- package/src/components/ui/Input.tsx +38 -0
- package/src/components/ui/Loading.tsx +201 -0
- package/src/components/ui/Select.tsx +42 -0
- package/src/components/ui/TextArea.tsx +38 -0
- package/src/components/ui/label.tsx +24 -0
- package/src/components/ui/switch.tsx +31 -0
- package/src/components/ui/tabs.tsx +66 -0
- package/src/hooks/useConsent.ts +64 -0
- package/src/hooks/useLoadingState.ts +85 -0
- package/src/lib/consentService.ts +137 -0
- package/src/lib/dpiaQuestions.ts +148 -0
- package/src/lib/requestService.ts +75 -0
- package/src/lib/sanitize.ts +108 -0
- package/src/lib/storage.ts +222 -0
- package/src/lib/utils.ts +6 -0
- package/src/types/html-to-docx.d.ts +30 -0
- package/src/types/index.ts +72 -0
- package/tailwind.config.ts +65 -0
- package/tsconfig.json +41 -0
- package/dist/components/breach/BreachNotificationManager.d.ts +0 -62
- package/dist/components/breach/BreachReportForm.d.ts +0 -66
- package/dist/components/breach/BreachRiskAssessment.d.ts +0 -50
- package/dist/components/breach/RegulatoryReportGenerator.d.ts +0 -94
- package/dist/components/consent/ConsentBanner.d.ts +0 -79
- package/dist/components/consent/ConsentManager.d.ts +0 -73
- package/dist/components/consent/ConsentStorage.d.ts +0 -41
- package/dist/components/dpia/DPIAQuestionnaire.d.ts +0 -70
- package/dist/components/dpia/DPIAReport.d.ts +0 -40
- package/dist/components/dpia/StepIndicator.d.ts +0 -64
- package/dist/components/dsr/DSRDashboard.d.ts +0 -58
- package/dist/components/dsr/DSRRequestForm.d.ts +0 -74
- package/dist/components/dsr/DSRTracker.d.ts +0 -56
- package/dist/components/policy/PolicyExporter.d.ts +0 -65
- package/dist/components/policy/PolicyGenerator.d.ts +0 -54
- package/dist/components/policy/PolicyPreview.d.ts +0 -71
- package/dist/hooks/useBreach.d.ts +0 -97
- package/dist/hooks/useConsent.d.ts +0 -63
- package/dist/hooks/useDPIA.d.ts +0 -92
- package/dist/hooks/useDSR.d.ts +0 -72
- package/dist/hooks/usePrivacyPolicy.d.ts +0 -87
- package/dist/index.esm.js +0 -2
- package/dist/index.esm.js.map +0 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +0 -1
- package/dist/setupTests.d.ts +0 -2
- package/dist/types/breach.d.ts +0 -239
- package/dist/types/consent.d.ts +0 -95
- package/dist/types/dpia.d.ts +0 -196
- package/dist/types/dsr.d.ts +0 -162
- package/dist/types/privacy.d.ts +0 -204
- package/dist/utils/breach.d.ts +0 -14
- package/dist/utils/consent.d.ts +0 -10
- package/dist/utils/dpia.d.ts +0 -12
- package/dist/utils/dsr.d.ts +0 -11
- package/dist/utils/privacy.d.ts +0 -12
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { PolicySection, PolicyVariable } from '../../types/privacy';
|
|
3
|
+
|
|
4
|
+
export interface PolicyPreviewProps {
|
|
5
|
+
/**
|
|
6
|
+
* The policy content to preview
|
|
7
|
+
*/
|
|
8
|
+
content: string;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The policy sections
|
|
12
|
+
*/
|
|
13
|
+
sections?: PolicySection[];
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The policy variables
|
|
17
|
+
*/
|
|
18
|
+
variables?: PolicyVariable[];
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Callback function called when the policy is exported
|
|
22
|
+
*/
|
|
23
|
+
onExport?: (format: 'pdf' | 'html' | 'markdown' | 'docx') => void;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Callback function called when the policy is edited
|
|
27
|
+
*/
|
|
28
|
+
onEdit?: () => void;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Title displayed on the preview
|
|
32
|
+
* @default "Privacy Policy Preview"
|
|
33
|
+
*/
|
|
34
|
+
title?: string;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Description text displayed on the preview
|
|
38
|
+
* @default "Preview your NDPR-compliant privacy policy before exporting."
|
|
39
|
+
*/
|
|
40
|
+
description?: string;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Custom CSS class for the preview
|
|
44
|
+
*/
|
|
45
|
+
className?: string;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Custom CSS class for the buttons
|
|
49
|
+
*/
|
|
50
|
+
buttonClassName?: string;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Whether to show the export options
|
|
54
|
+
* @default true
|
|
55
|
+
*/
|
|
56
|
+
showExportOptions?: boolean;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Whether to show the edit button
|
|
60
|
+
* @default true
|
|
61
|
+
*/
|
|
62
|
+
showEditButton?: boolean;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Whether to show the table of contents
|
|
66
|
+
* @default true
|
|
67
|
+
*/
|
|
68
|
+
showTableOfContents?: boolean;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Whether to show the policy metadata
|
|
72
|
+
* @default true
|
|
73
|
+
*/
|
|
74
|
+
showMetadata?: boolean;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The organization name to display in the policy
|
|
78
|
+
*/
|
|
79
|
+
organizationName?: string;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The last updated date to display in the policy
|
|
83
|
+
*/
|
|
84
|
+
lastUpdated?: Date;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const PolicyPreview: React.FC<PolicyPreviewProps> = ({
|
|
88
|
+
content,
|
|
89
|
+
sections,
|
|
90
|
+
variables,
|
|
91
|
+
onExport,
|
|
92
|
+
onEdit,
|
|
93
|
+
title = "Privacy Policy Preview",
|
|
94
|
+
description = "Preview your NDPR-compliant privacy policy before exporting.",
|
|
95
|
+
className = "",
|
|
96
|
+
buttonClassName = "",
|
|
97
|
+
showExportOptions = true,
|
|
98
|
+
showEditButton = true,
|
|
99
|
+
showTableOfContents = true,
|
|
100
|
+
showMetadata = true,
|
|
101
|
+
organizationName,
|
|
102
|
+
lastUpdated = new Date()
|
|
103
|
+
}) => {
|
|
104
|
+
const [activeTab, setActiveTab] = useState<'preview' | 'markdown'>('preview');
|
|
105
|
+
|
|
106
|
+
// Parse the content to extract section titles for the table of contents
|
|
107
|
+
const extractSectionTitles = (): { id: string, title: string, level: number }[] => {
|
|
108
|
+
const lines = content.split('\n');
|
|
109
|
+
const sectionTitles: { id: string, title: string, level: number }[] = [];
|
|
110
|
+
|
|
111
|
+
lines.forEach(line => {
|
|
112
|
+
if (line.startsWith('## ')) {
|
|
113
|
+
const title = line.substring(3).trim();
|
|
114
|
+
const id = title.toLowerCase().replace(/[^a-z0-9]+/g, '-');
|
|
115
|
+
sectionTitles.push({ id, title, level: 2 });
|
|
116
|
+
} else if (line.startsWith('### ')) {
|
|
117
|
+
const title = line.substring(4).trim();
|
|
118
|
+
const id = title.toLowerCase().replace(/[^a-z0-9]+/g, '-');
|
|
119
|
+
sectionTitles.push({ id, title, level: 3 });
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
return sectionTitles;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// Get the section titles for the table of contents
|
|
127
|
+
const sectionTitles = extractSectionTitles();
|
|
128
|
+
|
|
129
|
+
// Handle export button click
|
|
130
|
+
const handleExport = (format: 'pdf' | 'html' | 'markdown' | 'docx') => {
|
|
131
|
+
if (onExport) {
|
|
132
|
+
onExport(format);
|
|
133
|
+
} else {
|
|
134
|
+
// Fallback export functionality
|
|
135
|
+
if (format === 'markdown') {
|
|
136
|
+
const element = document.createElement('a');
|
|
137
|
+
const file = new Blob([content], {type: 'text/markdown'});
|
|
138
|
+
element.href = URL.createObjectURL(file);
|
|
139
|
+
element.download = `privacy-policy-${new Date().toISOString().split('T')[0]}.md`;
|
|
140
|
+
document.body.appendChild(element);
|
|
141
|
+
element.click();
|
|
142
|
+
document.body.removeChild(element);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// Render the table of contents
|
|
148
|
+
const renderTableOfContents = () => {
|
|
149
|
+
if (!showTableOfContents || sectionTitles.length === 0) {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return (
|
|
154
|
+
<div className="mb-6 p-4 bg-gray-50 dark:bg-gray-700 rounded-md">
|
|
155
|
+
<h3 className="text-lg font-medium mb-3">Table of Contents</h3>
|
|
156
|
+
<ul className="space-y-1">
|
|
157
|
+
{sectionTitles.map((section, index) => (
|
|
158
|
+
<li key={index} style={{ marginLeft: `${(section.level - 2) * 1.5}rem` }}>
|
|
159
|
+
<a
|
|
160
|
+
href={`#${section.id}`}
|
|
161
|
+
className="text-blue-600 dark:text-blue-400 hover:underline"
|
|
162
|
+
>
|
|
163
|
+
{section.title}
|
|
164
|
+
</a>
|
|
165
|
+
</li>
|
|
166
|
+
))}
|
|
167
|
+
</ul>
|
|
168
|
+
</div>
|
|
169
|
+
);
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
// Render the policy metadata
|
|
173
|
+
const renderMetadata = () => {
|
|
174
|
+
if (!showMetadata) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
<div className="mb-6">
|
|
180
|
+
<h1 className="text-2xl font-bold mb-2">
|
|
181
|
+
{organizationName ? `${organizationName} Privacy Policy` : 'Privacy Policy'}
|
|
182
|
+
</h1>
|
|
183
|
+
<p className="text-sm text-gray-500 dark:text-gray-400">
|
|
184
|
+
Last Updated: {lastUpdated.toLocaleDateString()}
|
|
185
|
+
</p>
|
|
186
|
+
</div>
|
|
187
|
+
);
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// Render the policy content in HTML format
|
|
191
|
+
const renderHTMLContent = () => {
|
|
192
|
+
return (
|
|
193
|
+
<div className="prose dark:prose-invert max-w-none">
|
|
194
|
+
{content.split('\n').map((line, index) => {
|
|
195
|
+
if (line.startsWith('## ')) {
|
|
196
|
+
const title = line.substring(3).trim();
|
|
197
|
+
const id = title.toLowerCase().replace(/[^a-z0-9]+/g, '-');
|
|
198
|
+
return <h2 id={id} key={index} className="text-xl font-bold mt-6 mb-3">{title}</h2>;
|
|
199
|
+
} else if (line.startsWith('### ')) {
|
|
200
|
+
const title = line.substring(4).trim();
|
|
201
|
+
const id = title.toLowerCase().replace(/[^a-z0-9]+/g, '-');
|
|
202
|
+
return <h3 id={id} key={index} className="text-lg font-bold mt-4 mb-2">{title}</h3>;
|
|
203
|
+
} else if (line === '') {
|
|
204
|
+
return <br key={index} />;
|
|
205
|
+
} else {
|
|
206
|
+
return <p key={index} className="mb-2">{line}</p>;
|
|
207
|
+
}
|
|
208
|
+
})}
|
|
209
|
+
</div>
|
|
210
|
+
);
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
// Render the export options
|
|
214
|
+
const renderExportOptions = () => {
|
|
215
|
+
if (!showExportOptions) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return (
|
|
220
|
+
<div className="mt-6">
|
|
221
|
+
<h3 className="text-lg font-medium mb-3">Export Options</h3>
|
|
222
|
+
<div className="flex flex-wrap gap-3">
|
|
223
|
+
<button
|
|
224
|
+
onClick={() => handleExport('pdf')}
|
|
225
|
+
className={`px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 ${buttonClassName}`}
|
|
226
|
+
>
|
|
227
|
+
Export as PDF
|
|
228
|
+
</button>
|
|
229
|
+
<button
|
|
230
|
+
onClick={() => handleExport('docx')}
|
|
231
|
+
className={`px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 ${buttonClassName}`}
|
|
232
|
+
>
|
|
233
|
+
Export as DOCX
|
|
234
|
+
</button>
|
|
235
|
+
<button
|
|
236
|
+
onClick={() => handleExport('html')}
|
|
237
|
+
className={`px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 ${buttonClassName}`}
|
|
238
|
+
>
|
|
239
|
+
Export as HTML
|
|
240
|
+
</button>
|
|
241
|
+
<button
|
|
242
|
+
onClick={() => handleExport('markdown')}
|
|
243
|
+
className={`px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 ${buttonClassName}`}
|
|
244
|
+
>
|
|
245
|
+
Export as Markdown
|
|
246
|
+
</button>
|
|
247
|
+
</div>
|
|
248
|
+
</div>
|
|
249
|
+
);
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
return (
|
|
253
|
+
<div className={`bg-white dark:bg-gray-800 p-6 rounded-lg shadow-md ${className}`}>
|
|
254
|
+
<div className="flex justify-between items-start mb-6">
|
|
255
|
+
<div>
|
|
256
|
+
<h2 className="text-xl font-bold mb-2">{title}</h2>
|
|
257
|
+
<p className="text-gray-600 dark:text-gray-300">{description}</p>
|
|
258
|
+
</div>
|
|
259
|
+
|
|
260
|
+
{showEditButton && onEdit && (
|
|
261
|
+
<button
|
|
262
|
+
onClick={onEdit}
|
|
263
|
+
className={`px-4 py-2 bg-gray-200 text-gray-800 dark:bg-gray-700 dark:text-white rounded hover:bg-gray-300 dark:hover:bg-gray-600 ${buttonClassName}`}
|
|
264
|
+
>
|
|
265
|
+
Edit Policy
|
|
266
|
+
</button>
|
|
267
|
+
)}
|
|
268
|
+
</div>
|
|
269
|
+
|
|
270
|
+
{/* NDPR Notice */}
|
|
271
|
+
<div className="mb-6 p-4 bg-blue-50 dark:bg-blue-900/20 rounded-md">
|
|
272
|
+
<h3 className="text-sm font-bold text-blue-800 dark:text-blue-200 mb-2">NDPR Compliance Notice</h3>
|
|
273
|
+
<p className="text-blue-700 dark:text-blue-300 text-sm">
|
|
274
|
+
This privacy policy has been generated to align with the Nigeria Data Protection Regulation (NDPR).
|
|
275
|
+
We recommend having the final policy reviewed by a legal professional familiar with NDPR requirements
|
|
276
|
+
before publishing it on your website or sharing it with your users.
|
|
277
|
+
</p>
|
|
278
|
+
</div>
|
|
279
|
+
|
|
280
|
+
{/* Tabs */}
|
|
281
|
+
<div className="mb-6 border-b border-gray-200 dark:border-gray-700">
|
|
282
|
+
<ul className="flex flex-wrap -mb-px">
|
|
283
|
+
<li className="mr-2">
|
|
284
|
+
<button
|
|
285
|
+
onClick={() => setActiveTab('preview')}
|
|
286
|
+
className={`inline-block p-4 ${
|
|
287
|
+
activeTab === 'preview'
|
|
288
|
+
? 'text-blue-600 border-b-2 border-blue-600 dark:text-blue-500 dark:border-blue-500'
|
|
289
|
+
: 'text-gray-500 hover:text-gray-600 hover:border-gray-300 dark:text-gray-400 dark:hover:text-gray-300'
|
|
290
|
+
}`}
|
|
291
|
+
>
|
|
292
|
+
Preview
|
|
293
|
+
</button>
|
|
294
|
+
</li>
|
|
295
|
+
<li className="mr-2">
|
|
296
|
+
<button
|
|
297
|
+
onClick={() => setActiveTab('markdown')}
|
|
298
|
+
className={`inline-block p-4 ${
|
|
299
|
+
activeTab === 'markdown'
|
|
300
|
+
? 'text-blue-600 border-b-2 border-blue-600 dark:text-blue-500 dark:border-blue-500'
|
|
301
|
+
: 'text-gray-500 hover:text-gray-600 hover:border-gray-300 dark:text-gray-400 dark:hover:text-gray-300'
|
|
302
|
+
}`}
|
|
303
|
+
>
|
|
304
|
+
Markdown
|
|
305
|
+
</button>
|
|
306
|
+
</li>
|
|
307
|
+
</ul>
|
|
308
|
+
</div>
|
|
309
|
+
|
|
310
|
+
{/* Content */}
|
|
311
|
+
<div className="bg-white dark:bg-gray-800 p-4 rounded-md">
|
|
312
|
+
{activeTab === 'preview' ? (
|
|
313
|
+
<div>
|
|
314
|
+
{renderMetadata()}
|
|
315
|
+
{renderTableOfContents()}
|
|
316
|
+
<div className="bg-gray-50 dark:bg-gray-700 p-6 rounded-md">
|
|
317
|
+
{renderHTMLContent()}
|
|
318
|
+
</div>
|
|
319
|
+
</div>
|
|
320
|
+
) : (
|
|
321
|
+
<div>
|
|
322
|
+
<pre className="bg-gray-50 dark:bg-gray-700 p-4 rounded-md overflow-auto whitespace-pre-wrap font-mono text-sm text-gray-800 dark:text-gray-200">
|
|
323
|
+
{content}
|
|
324
|
+
</pre>
|
|
325
|
+
</div>
|
|
326
|
+
)}
|
|
327
|
+
</div>
|
|
328
|
+
|
|
329
|
+
{/* Export Options */}
|
|
330
|
+
{renderExportOptions()}
|
|
331
|
+
</div>
|
|
332
|
+
);
|
|
333
|
+
};
|