@tantainnovative/ndpr-toolkit 1.0.3 → 1.0.5

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 (110) hide show
  1. package/next-env.d.ts +5 -0
  2. package/package.json +1 -1
  3. package/packages/ndpr-toolkit/dist/components/breach/BreachNotificationManager.d.ts +62 -0
  4. package/packages/ndpr-toolkit/dist/components/breach/BreachReportForm.d.ts +66 -0
  5. package/packages/ndpr-toolkit/dist/components/breach/BreachRiskAssessment.d.ts +50 -0
  6. package/packages/ndpr-toolkit/dist/components/breach/RegulatoryReportGenerator.d.ts +94 -0
  7. package/packages/ndpr-toolkit/dist/components/consent/ConsentBanner.d.ts +79 -0
  8. package/packages/ndpr-toolkit/dist/components/consent/ConsentManager.d.ts +73 -0
  9. package/packages/ndpr-toolkit/dist/components/consent/ConsentStorage.d.ts +41 -0
  10. package/packages/ndpr-toolkit/dist/components/dpia/DPIAQuestionnaire.d.ts +70 -0
  11. package/packages/ndpr-toolkit/dist/components/dpia/DPIAReport.d.ts +40 -0
  12. package/packages/ndpr-toolkit/dist/components/dpia/StepIndicator.d.ts +64 -0
  13. package/packages/ndpr-toolkit/dist/components/dsr/DSRDashboard.d.ts +58 -0
  14. package/packages/ndpr-toolkit/dist/components/dsr/DSRRequestForm.d.ts +74 -0
  15. package/packages/ndpr-toolkit/dist/components/dsr/DSRTracker.d.ts +56 -0
  16. package/packages/ndpr-toolkit/dist/components/policy/PolicyExporter.d.ts +65 -0
  17. package/packages/ndpr-toolkit/dist/components/policy/PolicyGenerator.d.ts +54 -0
  18. package/packages/ndpr-toolkit/dist/components/policy/PolicyPreview.d.ts +71 -0
  19. package/packages/ndpr-toolkit/dist/hooks/useBreach.d.ts +97 -0
  20. package/packages/ndpr-toolkit/dist/hooks/useConsent.d.ts +63 -0
  21. package/packages/ndpr-toolkit/dist/hooks/useDPIA.d.ts +92 -0
  22. package/packages/ndpr-toolkit/dist/hooks/useDSR.d.ts +72 -0
  23. package/packages/ndpr-toolkit/dist/hooks/usePrivacyPolicy.d.ts +87 -0
  24. package/packages/ndpr-toolkit/dist/index.d.ts +31 -0
  25. package/packages/ndpr-toolkit/dist/index.esm.js +2 -0
  26. package/packages/ndpr-toolkit/dist/index.esm.js.map +1 -0
  27. package/packages/ndpr-toolkit/dist/index.js +2 -0
  28. package/packages/ndpr-toolkit/dist/index.js.map +1 -0
  29. package/packages/ndpr-toolkit/dist/setupTests.d.ts +2 -0
  30. package/packages/ndpr-toolkit/dist/types/breach.d.ts +239 -0
  31. package/packages/ndpr-toolkit/dist/types/consent.d.ts +95 -0
  32. package/packages/ndpr-toolkit/dist/types/dpia.d.ts +196 -0
  33. package/packages/ndpr-toolkit/dist/types/dsr.d.ts +162 -0
  34. package/packages/ndpr-toolkit/dist/types/privacy.d.ts +204 -0
  35. package/packages/ndpr-toolkit/dist/utils/breach.d.ts +14 -0
  36. package/packages/ndpr-toolkit/dist/utils/consent.d.ts +10 -0
  37. package/packages/ndpr-toolkit/dist/utils/dpia.d.ts +12 -0
  38. package/packages/ndpr-toolkit/dist/utils/dsr.d.ts +11 -0
  39. package/packages/ndpr-toolkit/dist/utils/privacy.d.ts +12 -0
  40. package/src/components/consent/ConsentBanner.tsx +82 -48
  41. package/src/components/data-subject-rights/DataSubjectRequestForm.tsx +240 -129
  42. package/src/components/dpia/DPIAQuestionnaire.tsx +162 -122
  43. package/src/components/privacy-policy/PolicyGenerator.tsx +5 -5
  44. package/src/components/privacy-policy/steps/CustomSectionsStep.tsx +103 -77
  45. package/src/components/privacy-policy/steps/PolicyPreviewStep.tsx +117 -63
  46. package/src/hooks/useConsent.ts +16 -10
  47. package/src/lib/consentService.ts +44 -37
  48. package/src/lib/dpiaQuestions.ts +139 -99
  49. package/src/lib/requestService.ts +21 -17
  50. package/src/types/index.ts +13 -8
  51. package/.claude/settings.local.json +0 -20
  52. package/.eslintrc.json +0 -10
  53. package/.github/workflows/ci.yml +0 -36
  54. package/.github/workflows/nextjs.yml +0 -104
  55. package/.husky/commit-msg +0 -4
  56. package/.husky/pre-commit +0 -4
  57. package/.lintstagedrc.js +0 -4
  58. package/.nvmrc +0 -1
  59. package/.versionrc +0 -17
  60. package/CLAUDE.md +0 -90
  61. package/commitlint.config.js +0 -36
  62. package/jest.config.js +0 -31
  63. package/jest.setup.js +0 -15
  64. package/packages/ndpr-toolkit/jest.config.js +0 -23
  65. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentBanner.test.tsx +0 -119
  66. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentManager.test.tsx +0 -122
  67. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentStorage.test.tsx +0 -270
  68. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRDashboard.test.tsx +0 -199
  69. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRRequestForm.test.tsx +0 -224
  70. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRTracker.test.tsx +0 -104
  71. package/packages/ndpr-toolkit/src/__tests__/hooks/useConsent.test.tsx +0 -161
  72. package/packages/ndpr-toolkit/src/__tests__/hooks/useDSR.test.tsx +0 -330
  73. package/packages/ndpr-toolkit/src/__tests__/utils/breach.test.ts +0 -149
  74. package/packages/ndpr-toolkit/src/__tests__/utils/consent.test.ts +0 -88
  75. package/packages/ndpr-toolkit/src/__tests__/utils/dpia.test.ts +0 -160
  76. package/packages/ndpr-toolkit/src/__tests__/utils/dsr.test.ts +0 -110
  77. package/packages/ndpr-toolkit/src/__tests__/utils/privacy.test.ts +0 -97
  78. package/src/__tests__/example.test.ts +0 -13
  79. package/src/__tests__/requestService.test.ts +0 -57
  80. package/src/app/docs/components/DocLayout.tsx +0 -267
  81. package/src/app/docs/components/breach-notification/page.tsx +0 -797
  82. package/src/app/docs/components/consent-management/page.tsx +0 -576
  83. package/src/app/docs/components/data-subject-rights/page.tsx +0 -511
  84. package/src/app/docs/components/dpia-questionnaire/layout.tsx +0 -15
  85. package/src/app/docs/components/dpia-questionnaire/metadata.ts +0 -31
  86. package/src/app/docs/components/dpia-questionnaire/page.tsx +0 -666
  87. package/src/app/docs/components/hooks/page.tsx +0 -305
  88. package/src/app/docs/components/page.tsx +0 -84
  89. package/src/app/docs/components/privacy-policy-generator/page.tsx +0 -634
  90. package/src/app/docs/guides/breach-notification-process/components/BestPractices.tsx +0 -123
  91. package/src/app/docs/guides/breach-notification-process/components/ImplementationSteps.tsx +0 -328
  92. package/src/app/docs/guides/breach-notification-process/components/Introduction.tsx +0 -28
  93. package/src/app/docs/guides/breach-notification-process/components/NotificationTimeline.tsx +0 -91
  94. package/src/app/docs/guides/breach-notification-process/components/Resources.tsx +0 -118
  95. package/src/app/docs/guides/breach-notification-process/page.tsx +0 -39
  96. package/src/app/docs/guides/conducting-dpia/page.tsx +0 -593
  97. package/src/app/docs/guides/data-subject-requests/page.tsx +0 -666
  98. package/src/app/docs/guides/managing-consent/page.tsx +0 -738
  99. package/src/app/docs/guides/ndpr-compliance-checklist/components/ComplianceChecklist.tsx +0 -296
  100. package/src/app/docs/guides/ndpr-compliance-checklist/components/ImplementationTools.tsx +0 -145
  101. package/src/app/docs/guides/ndpr-compliance-checklist/components/Introduction.tsx +0 -33
  102. package/src/app/docs/guides/ndpr-compliance-checklist/components/KeyRequirements.tsx +0 -99
  103. package/src/app/docs/guides/ndpr-compliance-checklist/components/Resources.tsx +0 -159
  104. package/src/app/docs/guides/ndpr-compliance-checklist/page.tsx +0 -38
  105. package/src/app/docs/guides/page.tsx +0 -67
  106. package/src/app/docs/layout.tsx +0 -15
  107. package/src/app/docs/metadata.ts +0 -31
  108. package/src/app/docs/page.tsx +0 -572
  109. package/src/components/docs/DocLayout.tsx +0 -289
  110. package/src/components/docs/index.ts +0 -2
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Represents a section in a privacy policy
3
+ */
4
+ export interface PolicySection {
5
+ /**
6
+ * Unique identifier for the section
7
+ */
8
+ id: string;
9
+ /**
10
+ * Title of the section
11
+ */
12
+ title: string;
13
+ /**
14
+ * Description of the section
15
+ */
16
+ description?: string;
17
+ /**
18
+ * Order of the section in the policy
19
+ */
20
+ order?: number;
21
+ /**
22
+ * Whether the section is required by NDPR
23
+ */
24
+ required: boolean;
25
+ /**
26
+ * Template text for the section
27
+ */
28
+ template: string;
29
+ /**
30
+ * Default content for the section (legacy field)
31
+ * @deprecated Use template instead
32
+ */
33
+ defaultContent?: string;
34
+ /**
35
+ * Custom content for the section (overrides default content)
36
+ * @deprecated Use template instead
37
+ */
38
+ customContent?: string;
39
+ /**
40
+ * Whether the section is included in the policy
41
+ */
42
+ included: boolean;
43
+ /**
44
+ * Variables that can be used in the section content
45
+ */
46
+ variables?: string[];
47
+ }
48
+ /**
49
+ * Represents a privacy policy template
50
+ */
51
+ export interface PolicyTemplate {
52
+ /**
53
+ * Unique identifier for the template
54
+ */
55
+ id: string;
56
+ /**
57
+ * Name of the template
58
+ */
59
+ name: string;
60
+ /**
61
+ * Description of the template
62
+ */
63
+ description: string;
64
+ /**
65
+ * Type of organization the template is designed for
66
+ */
67
+ organizationType: 'business' | 'nonprofit' | 'government' | 'educational';
68
+ /**
69
+ * Sections included in the template
70
+ */
71
+ sections: PolicySection[];
72
+ /**
73
+ * Variables used across the template
74
+ */
75
+ variables: Record<string, {
76
+ name: string;
77
+ description: string;
78
+ required: boolean;
79
+ defaultValue?: string;
80
+ }>;
81
+ /**
82
+ * Version of the template
83
+ */
84
+ version: string;
85
+ /**
86
+ * Last updated date of the template
87
+ */
88
+ lastUpdated: number;
89
+ }
90
+ /**
91
+ * Represents organization information for a privacy policy
92
+ */
93
+ export interface OrganizationInfo {
94
+ /**
95
+ * Name of the organization
96
+ */
97
+ name: string;
98
+ /**
99
+ * Website URL of the organization
100
+ */
101
+ website: string;
102
+ /**
103
+ * Contact email for privacy inquiries
104
+ */
105
+ privacyEmail: string;
106
+ /**
107
+ * Physical address of the organization
108
+ */
109
+ address?: string;
110
+ /**
111
+ * Phone number for privacy inquiries
112
+ */
113
+ privacyPhone?: string;
114
+ /**
115
+ * Name of the Data Protection Officer (if applicable)
116
+ */
117
+ dpoName?: string;
118
+ /**
119
+ * Email of the Data Protection Officer (if applicable)
120
+ */
121
+ dpoEmail?: string;
122
+ /**
123
+ * Industry or sector of the organization
124
+ */
125
+ industry?: string;
126
+ }
127
+ /**
128
+ * Represents a variable in a privacy policy
129
+ */
130
+ export interface PolicyVariable {
131
+ /**
132
+ * Unique identifier for the variable
133
+ */
134
+ id: string;
135
+ /**
136
+ * Name of the variable as it appears in the template
137
+ */
138
+ name: string;
139
+ /**
140
+ * Description of the variable
141
+ */
142
+ description: string;
143
+ /**
144
+ * Default value for the variable
145
+ */
146
+ defaultValue?: string;
147
+ /**
148
+ * Current value of the variable
149
+ */
150
+ value: string;
151
+ /**
152
+ * Type of input for the variable
153
+ */
154
+ inputType: 'text' | 'textarea' | 'email' | 'url' | 'date' | 'select';
155
+ /**
156
+ * Options for select inputs
157
+ */
158
+ options?: string[];
159
+ /**
160
+ * Whether the variable is required
161
+ */
162
+ required: boolean;
163
+ }
164
+ /**
165
+ * Represents a generated privacy policy
166
+ */
167
+ export interface PrivacyPolicy {
168
+ /**
169
+ * Unique identifier for the policy
170
+ */
171
+ id: string;
172
+ /**
173
+ * Title of the policy
174
+ */
175
+ title: string;
176
+ /**
177
+ * Template used to generate the policy
178
+ */
179
+ templateId: string;
180
+ /**
181
+ * Organization information
182
+ */
183
+ organizationInfo: OrganizationInfo;
184
+ /**
185
+ * Sections of the policy
186
+ */
187
+ sections: PolicySection[];
188
+ /**
189
+ * Values for the variables used in the policy
190
+ */
191
+ variableValues: Record<string, string>;
192
+ /**
193
+ * Effective date of the policy
194
+ */
195
+ effectiveDate: number;
196
+ /**
197
+ * Last updated date of the policy
198
+ */
199
+ lastUpdated: number;
200
+ /**
201
+ * Version of the policy
202
+ */
203
+ version: string;
204
+ }
@@ -0,0 +1,14 @@
1
+ import { BreachReport, RiskAssessment } from '../types/breach';
2
+ /**
3
+ * Calculates the severity of a data breach based on various factors
4
+ * @param report The breach report
5
+ * @param assessment The risk assessment (if available)
6
+ * @returns The calculated severity and notification requirements
7
+ */
8
+ export declare function calculateBreachSeverity(report: BreachReport, assessment?: RiskAssessment): {
9
+ severityLevel: 'low' | 'medium' | 'high' | 'critical';
10
+ notificationRequired: boolean;
11
+ urgentNotificationRequired: boolean;
12
+ timeframeHours: number;
13
+ justification: string;
14
+ };
@@ -0,0 +1,10 @@
1
+ import { ConsentSettings } from '../types/consent';
2
+ /**
3
+ * Validates consent settings to ensure they meet NDPR requirements
4
+ * @param settings The consent settings to validate
5
+ * @returns An object containing validation result and any error messages
6
+ */
7
+ export declare function validateConsent(settings: ConsentSettings): {
8
+ valid: boolean;
9
+ errors: string[];
10
+ };
@@ -0,0 +1,12 @@
1
+ import { DPIAResult } from '../types/dpia';
2
+ /**
3
+ * Assesses the risk level of a DPIA based on the identified risks
4
+ * @param dpiaResult The DPIA result containing risks to assess
5
+ * @returns Assessment result with overall risk level and recommendations
6
+ */
7
+ export declare function assessDPIARisk(dpiaResult: DPIAResult): {
8
+ overallRiskLevel: 'low' | 'medium' | 'high' | 'critical';
9
+ requiresConsultation: boolean;
10
+ canProceed: boolean;
11
+ recommendations: string[];
12
+ };
@@ -0,0 +1,11 @@
1
+ import { DSRRequest } from '../types/dsr';
2
+ /**
3
+ * Formats a DSR request for display or submission
4
+ * @param request The DSR request to format
5
+ * @returns Formatted request data
6
+ */
7
+ export declare function formatDSRRequest(request: DSRRequest): {
8
+ formattedRequest: Record<string, any>;
9
+ isValid: boolean;
10
+ validationErrors: string[];
11
+ };
@@ -0,0 +1,12 @@
1
+ import { PolicySection, OrganizationInfo } from '../types/privacy';
2
+ /**
3
+ * Generates policy text by replacing variables in a template with organization-specific values
4
+ * @param sectionsOrTemplate The policy sections or template string to generate text for
5
+ * @param organizationInfoOrVariables The organization information or variable map to use for replacement
6
+ * @returns The generated policy text or an object with the generated text and metadata
7
+ */
8
+ export declare function generatePolicyText(sectionsOrTemplate: PolicySection[] | string, organizationInfoOrVariables: OrganizationInfo | Record<string, string>): string | {
9
+ fullText: string;
10
+ sectionTexts: Record<string, string>;
11
+ missingVariables: string[];
12
+ };
@@ -1,11 +1,18 @@
1
- 'use client';
1
+ "use client";
2
2
 
3
- import { useState } from 'react';
4
- import { ConsentOption } from '@/types';
5
- import { Button } from '@/components/ui/Button';
6
- import { Checkbox } from '@/components/ui/Checkbox';
7
- import { Card, CardContent, CardFooter, CardHeader, CardTitle, CardDescription } from '@/components/ui/Card';
8
- import { Badge } from '@/components/ui/Badge';
3
+ import { useState } from "react";
4
+ import { ConsentOption } from "@/types";
5
+ import { Button } from "@/components/ui/Button";
6
+ import { Checkbox } from "@/components/ui/Checkbox";
7
+ import {
8
+ Card,
9
+ CardContent,
10
+ CardFooter,
11
+ CardHeader,
12
+ CardTitle,
13
+ CardDescription,
14
+ } from "@/components/ui/Card";
15
+ import { Badge } from "@/components/ui/Badge";
9
16
 
10
17
  interface ConsentBannerProps {
11
18
  title?: string;
@@ -18,36 +25,42 @@ interface ConsentBannerProps {
18
25
  }
19
26
 
20
27
  export default function ConsentBanner({
21
- title = 'Privacy Preferences',
22
- description = 'We use cookies and similar technologies to provide certain features, enhance the user experience and deliver content that is relevant to your interests.',
23
- privacyPolicyUrl = '/privacy-policy',
28
+ title = "Privacy Preferences",
29
+ description = "We use cookies and similar technologies to provide certain features, enhance the user experience and deliver content that is relevant to your interests.",
30
+ privacyPolicyUrl = "/privacy-policy",
24
31
  options,
25
32
  onSave,
26
- className = '',
33
+ className = "",
27
34
  }: ConsentBannerProps) {
28
35
  const [consents, setConsents] = useState<Record<string, boolean>>(
29
- options.reduce((acc, option) => {
30
- acc[option.id] = option.defaultValue ?? false;
31
- return acc;
32
- }, {} as Record<string, boolean>)
36
+ options.reduce(
37
+ (acc, option) => {
38
+ acc[option.id] = option.defaultValue ?? false;
39
+ return acc;
40
+ },
41
+ {} as Record<string, boolean>,
42
+ ),
33
43
  );
34
44
 
35
45
  const handleToggle = (id: string) => {
36
- const option = options.find(opt => opt.id === id);
46
+ const option = options.find((opt) => opt.id === id);
37
47
  if (option?.required) return;
38
-
39
- setConsents(prev => ({
48
+
49
+ setConsents((prev) => ({
40
50
  ...prev,
41
- [id]: !prev[id]
51
+ [id]: !prev[id],
42
52
  }));
43
53
  };
44
54
 
45
55
  const handleAcceptAll = () => {
46
- const allConsents = options.reduce((acc, option) => {
47
- acc[option.id] = true;
48
- return acc;
49
- }, {} as Record<string, boolean>);
50
-
56
+ const allConsents = options.reduce(
57
+ (acc, option) => {
58
+ acc[option.id] = true;
59
+ return acc;
60
+ },
61
+ {} as Record<string, boolean>,
62
+ );
63
+
51
64
  setConsents(allConsents);
52
65
  onSave(allConsents);
53
66
  };
@@ -57,17 +70,22 @@ export default function ConsentBanner({
57
70
  };
58
71
 
59
72
  const handleRejectAll = () => {
60
- const rejectedConsents = options.reduce((acc, option) => {
61
- acc[option.id] = option.required ? true : false;
62
- return acc;
63
- }, {} as Record<string, boolean>);
64
-
73
+ const rejectedConsents = options.reduce(
74
+ (acc, option) => {
75
+ acc[option.id] = option.required ? true : false;
76
+ return acc;
77
+ },
78
+ {} as Record<string, boolean>,
79
+ );
80
+
65
81
  setConsents(rejectedConsents);
66
82
  onSave(rejectedConsents);
67
83
  };
68
84
 
69
85
  return (
70
- <div className={`fixed inset-0 z-50 flex items-end sm:items-center justify-center p-4 bg-black/50 ${className}`}>
86
+ <div
87
+ className={`fixed inset-0 z-50 flex items-end sm:items-center justify-center p-4 bg-black/50 ${className}`}
88
+ >
71
89
  <Card className="w-full max-w-3xl max-h-[90vh] overflow-auto shadow-xl animate-in fade-in slide-in-from-bottom-5 duration-300">
72
90
  <CardHeader className="border-b border-gray-200 dark:border-gray-700">
73
91
  <div className="flex items-center justify-between">
@@ -75,25 +93,38 @@ export default function ConsentBanner({
75
93
  <CardTitle className="text-xl">{title}</CardTitle>
76
94
  <CardDescription className="mt-2">{description}</CardDescription>
77
95
  </div>
78
- <Badge variant="primary" className="hidden sm:flex">Privacy Settings</Badge>
96
+ <Badge variant="primary" className="hidden sm:flex">
97
+ Privacy Settings
98
+ </Badge>
79
99
  </div>
80
- <a
81
- href={privacyPolicyUrl}
100
+ <a
101
+ href={privacyPolicyUrl}
82
102
  className="text-sm text-blue-600 dark:text-blue-400 hover:underline mt-2 inline-flex items-center"
83
103
  >
84
- <svg className="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
85
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" />
104
+ <svg
105
+ className="w-4 h-4 mr-1"
106
+ fill="none"
107
+ stroke="currentColor"
108
+ viewBox="0 0 24 24"
109
+ xmlns="http://www.w3.org/2000/svg"
110
+ >
111
+ <path
112
+ strokeLinecap="round"
113
+ strokeLinejoin="round"
114
+ strokeWidth={2}
115
+ d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"
116
+ />
86
117
  </svg>
87
118
  View our Privacy Policy
88
119
  </a>
89
120
  </CardHeader>
90
-
121
+
91
122
  <CardContent className="space-y-4 p-6">
92
123
  <div className="grid gap-4">
93
124
  {options.map((option) => (
94
- <div
95
- key={option.id}
96
- className={`p-4 rounded-lg border ${consents[option.id] ? 'border-blue-200 bg-blue-50 dark:border-blue-800 dark:bg-blue-900/20' : 'border-gray-200 dark:border-gray-700'} transition-colors duration-200`}
125
+ <div
126
+ key={option.id}
127
+ className={`p-4 rounded-lg border ${consents[option.id] ? "border-blue-200 bg-blue-50 dark:border-blue-800 dark:bg-blue-900/20" : "border-gray-200 dark:border-gray-700"} transition-colors duration-200`}
97
128
  >
98
129
  <div className="flex items-start">
99
130
  <div className="flex-1">
@@ -102,7 +133,9 @@ export default function ConsentBanner({
102
133
  {option.label}
103
134
  </h3>
104
135
  {option.required && (
105
- <Badge variant="secondary" className="ml-2 text-xs">Required</Badge>
136
+ <Badge variant="secondary" className="ml-2 text-xs">
137
+ Required
138
+ </Badge>
106
139
  )}
107
140
  </div>
108
141
  <p className="mt-1 text-sm text-gray-500 dark:text-gray-400">
@@ -122,30 +155,31 @@ export default function ConsentBanner({
122
155
  ))}
123
156
  </div>
124
157
  </CardContent>
125
-
158
+
126
159
  <CardFooter className="flex flex-col sm:flex-row sm:justify-between border-t border-gray-200 dark:border-gray-700 p-6 bg-gray-50 dark:bg-gray-800">
127
160
  <div className="mb-4 sm:mb-0">
128
161
  <p className="text-xs text-gray-500 dark:text-gray-400">
129
- You can change your preferences at any time by visiting your account settings.
162
+ You can change your preferences at any time by visiting your
163
+ account settings.
130
164
  </p>
131
165
  </div>
132
166
  <div className="flex flex-col sm:flex-row space-y-2 sm:space-y-0 sm:space-x-2">
133
- <Button
134
- variant="outline"
167
+ <Button
168
+ variant="outline"
135
169
  onClick={handleRejectAll}
136
170
  className="sm:order-1"
137
171
  >
138
172
  Reject All
139
173
  </Button>
140
- <Button
141
- variant="secondary"
174
+ <Button
175
+ variant="secondary"
142
176
  onClick={handleSave}
143
177
  className="sm:order-2"
144
178
  >
145
179
  Save Preferences
146
180
  </Button>
147
- <Button
148
- variant="default"
181
+ <Button
182
+ variant="default"
149
183
  onClick={handleAcceptAll}
150
184
  className="sm:order-3"
151
185
  >