@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.
Files changed (156) hide show
  1. package/next-env.d.ts +5 -0
  2. package/package.json +1 -1
  3. package/.claude/settings.local.json +0 -20
  4. package/.eslintrc.json +0 -10
  5. package/.github/workflows/ci.yml +0 -36
  6. package/.github/workflows/nextjs.yml +0 -104
  7. package/.husky/commit-msg +0 -4
  8. package/.husky/pre-commit +0 -4
  9. package/.lintstagedrc.js +0 -4
  10. package/.nvmrc +0 -1
  11. package/.versionrc +0 -17
  12. package/CLAUDE.md +0 -90
  13. package/commitlint.config.js +0 -36
  14. package/eslint.config.mjs +0 -16
  15. package/jest.config.js +0 -31
  16. package/jest.setup.js +0 -15
  17. package/next.config.js +0 -15
  18. package/next.config.ts +0 -62
  19. package/packages/ndpr-toolkit/README.md +0 -467
  20. package/packages/ndpr-toolkit/jest.config.js +0 -23
  21. package/packages/ndpr-toolkit/package-lock.json +0 -8197
  22. package/packages/ndpr-toolkit/package.json +0 -71
  23. package/packages/ndpr-toolkit/rollup.config.js +0 -34
  24. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentBanner.test.tsx +0 -119
  25. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentManager.test.tsx +0 -122
  26. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentStorage.test.tsx +0 -270
  27. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRDashboard.test.tsx +0 -199
  28. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRRequestForm.test.tsx +0 -224
  29. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRTracker.test.tsx +0 -104
  30. package/packages/ndpr-toolkit/src/__tests__/hooks/useConsent.test.tsx +0 -161
  31. package/packages/ndpr-toolkit/src/__tests__/hooks/useDSR.test.tsx +0 -330
  32. package/packages/ndpr-toolkit/src/__tests__/utils/breach.test.ts +0 -149
  33. package/packages/ndpr-toolkit/src/__tests__/utils/consent.test.ts +0 -88
  34. package/packages/ndpr-toolkit/src/__tests__/utils/dpia.test.ts +0 -160
  35. package/packages/ndpr-toolkit/src/__tests__/utils/dsr.test.ts +0 -110
  36. package/packages/ndpr-toolkit/src/__tests__/utils/privacy.test.ts +0 -97
  37. package/packages/ndpr-toolkit/src/components/breach/BreachNotificationManager.tsx +0 -701
  38. package/packages/ndpr-toolkit/src/components/breach/BreachReportForm.tsx +0 -631
  39. package/packages/ndpr-toolkit/src/components/breach/BreachRiskAssessment.tsx +0 -569
  40. package/packages/ndpr-toolkit/src/components/breach/RegulatoryReportGenerator.tsx +0 -496
  41. package/packages/ndpr-toolkit/src/components/consent/ConsentBanner.tsx +0 -270
  42. package/packages/ndpr-toolkit/src/components/consent/ConsentManager.tsx +0 -217
  43. package/packages/ndpr-toolkit/src/components/consent/ConsentStorage.tsx +0 -206
  44. package/packages/ndpr-toolkit/src/components/dpia/DPIAQuestionnaire.tsx +0 -342
  45. package/packages/ndpr-toolkit/src/components/dpia/DPIAReport.tsx +0 -373
  46. package/packages/ndpr-toolkit/src/components/dpia/StepIndicator.tsx +0 -174
  47. package/packages/ndpr-toolkit/src/components/dsr/DSRDashboard.tsx +0 -717
  48. package/packages/ndpr-toolkit/src/components/dsr/DSRRequestForm.tsx +0 -476
  49. package/packages/ndpr-toolkit/src/components/dsr/DSRTracker.tsx +0 -620
  50. package/packages/ndpr-toolkit/src/components/policy/PolicyExporter.tsx +0 -541
  51. package/packages/ndpr-toolkit/src/components/policy/PolicyGenerator.tsx +0 -454
  52. package/packages/ndpr-toolkit/src/components/policy/PolicyPreview.tsx +0 -333
  53. package/packages/ndpr-toolkit/src/hooks/useBreach.ts +0 -409
  54. package/packages/ndpr-toolkit/src/hooks/useConsent.ts +0 -263
  55. package/packages/ndpr-toolkit/src/hooks/useDPIA.ts +0 -457
  56. package/packages/ndpr-toolkit/src/hooks/useDSR.ts +0 -236
  57. package/packages/ndpr-toolkit/src/hooks/usePrivacyPolicy.ts +0 -428
  58. package/packages/ndpr-toolkit/src/index.ts +0 -44
  59. package/packages/ndpr-toolkit/src/setupTests.ts +0 -5
  60. package/packages/ndpr-toolkit/src/types/breach.ts +0 -283
  61. package/packages/ndpr-toolkit/src/types/consent.ts +0 -111
  62. package/packages/ndpr-toolkit/src/types/dpia.ts +0 -236
  63. package/packages/ndpr-toolkit/src/types/dsr.ts +0 -192
  64. package/packages/ndpr-toolkit/src/types/index.ts +0 -42
  65. package/packages/ndpr-toolkit/src/types/privacy.ts +0 -246
  66. package/packages/ndpr-toolkit/src/utils/breach.ts +0 -122
  67. package/packages/ndpr-toolkit/src/utils/consent.ts +0 -51
  68. package/packages/ndpr-toolkit/src/utils/dpia.ts +0 -104
  69. package/packages/ndpr-toolkit/src/utils/dsr.ts +0 -77
  70. package/packages/ndpr-toolkit/src/utils/privacy.ts +0 -100
  71. package/packages/ndpr-toolkit/tsconfig.json +0 -23
  72. package/postcss.config.mjs +0 -5
  73. package/src/__tests__/example.test.ts +0 -13
  74. package/src/__tests__/requestService.test.ts +0 -57
  75. package/src/app/accessibility.css +0 -70
  76. package/src/app/docs/components/DocLayout.tsx +0 -267
  77. package/src/app/docs/components/breach-notification/page.tsx +0 -797
  78. package/src/app/docs/components/consent-management/page.tsx +0 -576
  79. package/src/app/docs/components/data-subject-rights/page.tsx +0 -511
  80. package/src/app/docs/components/dpia-questionnaire/layout.tsx +0 -15
  81. package/src/app/docs/components/dpia-questionnaire/metadata.ts +0 -31
  82. package/src/app/docs/components/dpia-questionnaire/page.tsx +0 -666
  83. package/src/app/docs/components/hooks/page.tsx +0 -305
  84. package/src/app/docs/components/page.tsx +0 -84
  85. package/src/app/docs/components/privacy-policy-generator/page.tsx +0 -634
  86. package/src/app/docs/guides/breach-notification-process/components/BestPractices.tsx +0 -123
  87. package/src/app/docs/guides/breach-notification-process/components/ImplementationSteps.tsx +0 -328
  88. package/src/app/docs/guides/breach-notification-process/components/Introduction.tsx +0 -28
  89. package/src/app/docs/guides/breach-notification-process/components/NotificationTimeline.tsx +0 -91
  90. package/src/app/docs/guides/breach-notification-process/components/Resources.tsx +0 -118
  91. package/src/app/docs/guides/breach-notification-process/page.tsx +0 -39
  92. package/src/app/docs/guides/conducting-dpia/page.tsx +0 -593
  93. package/src/app/docs/guides/data-subject-requests/page.tsx +0 -666
  94. package/src/app/docs/guides/managing-consent/page.tsx +0 -738
  95. package/src/app/docs/guides/ndpr-compliance-checklist/components/ComplianceChecklist.tsx +0 -296
  96. package/src/app/docs/guides/ndpr-compliance-checklist/components/ImplementationTools.tsx +0 -145
  97. package/src/app/docs/guides/ndpr-compliance-checklist/components/Introduction.tsx +0 -33
  98. package/src/app/docs/guides/ndpr-compliance-checklist/components/KeyRequirements.tsx +0 -99
  99. package/src/app/docs/guides/ndpr-compliance-checklist/components/Resources.tsx +0 -159
  100. package/src/app/docs/guides/ndpr-compliance-checklist/page.tsx +0 -38
  101. package/src/app/docs/guides/page.tsx +0 -67
  102. package/src/app/docs/layout.tsx +0 -15
  103. package/src/app/docs/metadata.ts +0 -31
  104. package/src/app/docs/page.tsx +0 -572
  105. package/src/app/favicon.ico +0 -0
  106. package/src/app/globals.css +0 -123
  107. package/src/app/layout.tsx +0 -37
  108. package/src/app/ndpr-demos/breach/page.tsx +0 -354
  109. package/src/app/ndpr-demos/consent/page.tsx +0 -366
  110. package/src/app/ndpr-demos/dpia/page.tsx +0 -495
  111. package/src/app/ndpr-demos/dsr/page.tsx +0 -280
  112. package/src/app/ndpr-demos/page.tsx +0 -73
  113. package/src/app/ndpr-demos/policy/page.tsx +0 -771
  114. package/src/app/page.tsx +0 -452
  115. package/src/components/ErrorBoundary.tsx +0 -90
  116. package/src/components/breach-notification/BreachNotificationForm.tsx +0 -479
  117. package/src/components/consent/ConsentBanner.tsx +0 -159
  118. package/src/components/data-subject-rights/DataSubjectRequestForm.tsx +0 -419
  119. package/src/components/docs/DocLayout.tsx +0 -289
  120. package/src/components/docs/index.ts +0 -2
  121. package/src/components/dpia/DPIAQuestionnaire.tsx +0 -483
  122. package/src/components/privacy-policy/PolicyGenerator.tsx +0 -1062
  123. package/src/components/privacy-policy/data.ts +0 -98
  124. package/src/components/privacy-policy/shared/CheckboxField.tsx +0 -38
  125. package/src/components/privacy-policy/shared/CheckboxGroup.tsx +0 -85
  126. package/src/components/privacy-policy/shared/FormField.tsx +0 -79
  127. package/src/components/privacy-policy/shared/StepIndicator.tsx +0 -86
  128. package/src/components/privacy-policy/steps/CustomSectionsStep.tsx +0 -335
  129. package/src/components/privacy-policy/steps/DataCollectionStep.tsx +0 -231
  130. package/src/components/privacy-policy/steps/DataSharingStep.tsx +0 -418
  131. package/src/components/privacy-policy/steps/OrganizationInfoStep.tsx +0 -202
  132. package/src/components/privacy-policy/steps/PolicyPreviewStep.tsx +0 -172
  133. package/src/components/ui/Badge.tsx +0 -46
  134. package/src/components/ui/Button.tsx +0 -59
  135. package/src/components/ui/Card.tsx +0 -92
  136. package/src/components/ui/Checkbox.tsx +0 -57
  137. package/src/components/ui/FormField.tsx +0 -50
  138. package/src/components/ui/Input.tsx +0 -38
  139. package/src/components/ui/Loading.tsx +0 -201
  140. package/src/components/ui/Select.tsx +0 -42
  141. package/src/components/ui/TextArea.tsx +0 -38
  142. package/src/components/ui/label.tsx +0 -24
  143. package/src/components/ui/switch.tsx +0 -31
  144. package/src/components/ui/tabs.tsx +0 -66
  145. package/src/hooks/useConsent.ts +0 -64
  146. package/src/hooks/useLoadingState.ts +0 -85
  147. package/src/lib/consentService.ts +0 -137
  148. package/src/lib/dpiaQuestions.ts +0 -148
  149. package/src/lib/requestService.ts +0 -75
  150. package/src/lib/sanitize.ts +0 -108
  151. package/src/lib/storage.ts +0 -222
  152. package/src/lib/utils.ts +0 -6
  153. package/src/types/html-to-docx.d.ts +0 -30
  154. package/src/types/index.ts +0 -72
  155. package/tailwind.config.ts +0 -65
  156. package/tsconfig.json +0 -41
@@ -1,104 +0,0 @@
1
- import { DPIAResult, DPIARisk } from '../types/dpia';
2
-
3
- /**
4
- * Assesses the risk level of a DPIA based on the identified risks
5
- * @param dpiaResult The DPIA result containing risks to assess
6
- * @returns Assessment result with overall risk level and recommendations
7
- */
8
- export function assessDPIARisk(dpiaResult: DPIAResult): {
9
- overallRiskLevel: 'low' | 'medium' | 'high' | 'critical';
10
- requiresConsultation: boolean;
11
- canProceed: boolean;
12
- recommendations: string[];
13
- } {
14
- // Count risks by level
15
- const riskCounts = {
16
- low: 0,
17
- medium: 0,
18
- high: 0,
19
- critical: 0
20
- };
21
-
22
- // Calculate the highest risk score
23
- let highestRiskScore = 0;
24
-
25
- // Track unmitigated high/critical risks
26
- const unmitigatedHighRisks: DPIARisk[] = [];
27
-
28
- // Analyze each risk
29
- dpiaResult.risks.forEach(risk => {
30
- // Count by level
31
- riskCounts[risk.level]++;
32
-
33
- // Track highest score
34
- if (risk.score > highestRiskScore) {
35
- highestRiskScore = risk.score;
36
- }
37
-
38
- // Track unmitigated high/critical risks
39
- if ((risk.level === 'high' || risk.level === 'critical') && !risk.mitigated) {
40
- unmitigatedHighRisks.push(risk);
41
- }
42
- });
43
-
44
- // Determine overall risk level
45
- let overallRiskLevel: 'low' | 'medium' | 'high' | 'critical';
46
-
47
- if (riskCounts.critical > 0) {
48
- overallRiskLevel = 'critical';
49
- } else if (riskCounts.high > 2 || (riskCounts.high > 0 && riskCounts.medium > 3)) {
50
- overallRiskLevel = 'high';
51
- } else if (riskCounts.high > 0 || riskCounts.medium > 1) {
52
- overallRiskLevel = 'medium';
53
- } else {
54
- overallRiskLevel = 'low';
55
- }
56
-
57
- // Determine if NITDA consultation is required
58
- // Under NDPR, consultation is required for high-risk processing
59
- const requiresConsultation = overallRiskLevel === 'high' || overallRiskLevel === 'critical';
60
-
61
- // Determine if processing can proceed
62
- // Processing can proceed if all high/critical risks are mitigated
63
- const canProceed = unmitigatedHighRisks.length === 0;
64
-
65
- // Generate recommendations
66
- const recommendations: string[] = [];
67
-
68
- if (unmitigatedHighRisks.length > 0) {
69
- recommendations.push(
70
- `Mitigate the following high/critical risks before proceeding: ${
71
- unmitigatedHighRisks.map(risk => risk.description).join(', ')
72
- }`
73
- );
74
- }
75
-
76
- if (requiresConsultation) {
77
- recommendations.push(
78
- 'Consult with NITDA before proceeding with this processing activity, as required by NDPR for high-risk processing.'
79
- );
80
- }
81
-
82
- if (riskCounts.medium > 0) {
83
- recommendations.push(
84
- 'Implement additional safeguards to reduce medium-level risks where possible.'
85
- );
86
- }
87
-
88
- if (overallRiskLevel !== 'low') {
89
- recommendations.push(
90
- 'Schedule a review of this DPIA in 6 months to reassess risks and effectiveness of mitigation measures.'
91
- );
92
- } else {
93
- recommendations.push(
94
- 'Schedule a review of this DPIA in 12 months as part of regular compliance activities.'
95
- );
96
- }
97
-
98
- return {
99
- overallRiskLevel,
100
- requiresConsultation,
101
- canProceed,
102
- recommendations
103
- };
104
- }
@@ -1,77 +0,0 @@
1
- import { DSRRequest } from '../types/dsr';
2
-
3
- /**
4
- * Formats a DSR request for display or submission
5
- * @param request The DSR request to format
6
- * @returns Formatted request data
7
- */
8
- export function formatDSRRequest(request: DSRRequest): {
9
- formattedRequest: Record<string, any>;
10
- isValid: boolean;
11
- validationErrors: string[];
12
- } {
13
- const validationErrors: string[] = [];
14
-
15
- // Validate required fields
16
- if (!request.id) {
17
- validationErrors.push('Request ID is required');
18
- }
19
-
20
- if (!request.type) {
21
- validationErrors.push('Request type is required');
22
- }
23
-
24
- if (!request.status) {
25
- validationErrors.push('Request status is required');
26
- }
27
-
28
- if (!request.createdAt) {
29
- validationErrors.push('Creation timestamp is required');
30
- }
31
-
32
- if (!request.subject?.name) {
33
- validationErrors.push('Data subject name is required');
34
- }
35
-
36
- if (!request.subject?.email) {
37
- validationErrors.push('Data subject email is required');
38
- }
39
-
40
- // Format the request for display or submission
41
- const formattedRequest = {
42
- requestId: request.id,
43
- requestType: request.type,
44
- status: request.status,
45
- createdDate: new Date(request.createdAt).toISOString(),
46
- lastUpdated: request.updatedAt ? new Date(request.updatedAt).toISOString() : undefined,
47
- dueDate: request.dueDate
48
- ? new Date(request.dueDate).toISOString()
49
- : undefined,
50
- dataSubject: {
51
- name: request.subject.name,
52
- email: request.subject.email,
53
- phone: request.subject.phone || 'Not provided',
54
- identifier: {
55
- type: request.subject.identifierType || 'Not specified',
56
- value: request.subject.identifierValue || 'Not provided'
57
- }
58
- },
59
- additionalInformation: request.additionalInfo || {},
60
- verificationStatus: request.verification
61
- ? `${request.verification.verified ? 'Verified' : 'Not verified'}${request.verification.method ? ` via ${request.verification.method}` : ''}`
62
- : 'Pending verification',
63
- attachments: request.attachments
64
- ? request.attachments.map(attachment => ({
65
- name: attachment.name,
66
- type: attachment.type,
67
- addedOn: new Date(attachment.addedAt).toISOString()
68
- }))
69
- : []
70
- };
71
-
72
- return {
73
- formattedRequest,
74
- isValid: validationErrors.length === 0,
75
- validationErrors
76
- };
77
- }
@@ -1,100 +0,0 @@
1
- import { PolicySection, OrganizationInfo, PolicyVariable } from '../types/privacy';
2
-
3
- /**
4
- * Generates policy text by replacing variables in a template with organization-specific values
5
- * @param sectionsOrTemplate The policy sections or template string to generate text for
6
- * @param organizationInfoOrVariables The organization information or variable map to use for replacement
7
- * @returns The generated policy text or an object with the generated text and metadata
8
- */
9
- export function generatePolicyText(
10
- sectionsOrTemplate: PolicySection[] | string,
11
- organizationInfoOrVariables: OrganizationInfo | Record<string, string>
12
- ): string | {
13
- fullText: string;
14
- sectionTexts: Record<string, string>;
15
- missingVariables: string[];
16
- } {
17
- // Check if we're using the new API (template string and variable map)
18
- if (typeof sectionsOrTemplate === 'string') {
19
- const template = sectionsOrTemplate;
20
- const variableMap = organizationInfoOrVariables as Record<string, string>;
21
-
22
- // Replace variables in the template
23
- let result = template;
24
- const variableRegex = /\{\{([^}]+)\}\}/g;
25
- let match;
26
-
27
- // Find and replace all variables in the content
28
- while ((match = variableRegex.exec(template)) !== null) {
29
- const variable = match[1].trim();
30
- const replacement = variableMap[variable] || '';
31
-
32
- // Replace the variable in the content
33
- result = result.replace(
34
- new RegExp(`\\{\\{\\s*${variable}\\s*\\}\\}`, 'g'),
35
- replacement
36
- );
37
- }
38
-
39
- return result;
40
- }
41
- // Otherwise use the original API (sections array and organization info)
42
- else {
43
- const sections = sectionsOrTemplate;
44
- const organizationInfo = organizationInfoOrVariables as OrganizationInfo;
45
- const sectionTexts: Record<string, string> = {};
46
- const missingVariables: string[] = [];
47
-
48
- // Process each section
49
- sections
50
- .filter(section => section.included)
51
- .sort((a, b) => (a.order || 0) - (b.order || 0))
52
- .forEach(section => {
53
- // Use template if available, otherwise fall back to custom/default content
54
- let content = section.template || section.customContent || section.defaultContent || '';
55
-
56
- // Replace variables in the content
57
- const variableRegex = /\{\{([^}]+)\}\}/g;
58
- let match;
59
-
60
- // Find all variables in the content
61
- const contentVariables: string[] = [];
62
- while ((match = variableRegex.exec(content)) !== null) {
63
- contentVariables.push(match[1].trim());
64
- }
65
-
66
- // Replace each variable with its value
67
- contentVariables.forEach(variable => {
68
- let replacement = '';
69
-
70
- // Check if the variable exists in organizationInfo
71
- if (variable in organizationInfo) {
72
- replacement = organizationInfo[variable as keyof OrganizationInfo] as string || '';
73
- }
74
-
75
- // If replacement is empty, add to missing variables
76
- if (!replacement) {
77
- missingVariables.push(variable);
78
- }
79
-
80
- // Replace the variable in the content
81
- content = content.replace(
82
- new RegExp(`\\{\\{\\s*${variable}\\s*\\}\\}`, 'g'),
83
- replacement
84
- );
85
- });
86
-
87
- // Store the processed section text
88
- sectionTexts[section.id] = content;
89
- });
90
-
91
- // Combine all sections into full text
92
- const fullText = Object.values(sectionTexts).join('\n\n');
93
-
94
- return {
95
- fullText,
96
- sectionTexts,
97
- missingVariables: Array.from(new Set(missingVariables)) // Remove duplicates
98
- };
99
- }
100
- }
@@ -1,23 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es5",
4
- "lib": ["dom", "dom.iterable", "esnext"],
5
- "allowJs": true,
6
- "skipLibCheck": true,
7
- "esModuleInterop": true,
8
- "allowSyntheticDefaultImports": true,
9
- "strict": true,
10
- "forceConsistentCasingInFileNames": true,
11
- "noFallthroughCasesInSwitch": true,
12
- "module": "esnext",
13
- "moduleResolution": "node",
14
- "resolveJsonModule": true,
15
- "isolatedModules": true,
16
- "jsx": "react-jsx",
17
- "declaration": true,
18
- "declarationDir": "dist",
19
- "outDir": "dist"
20
- },
21
- "include": ["src"],
22
- "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
23
- }
@@ -1,5 +0,0 @@
1
- const config = {
2
- plugins: ["@tailwindcss/postcss", "autoprefixer"],
3
- };
4
-
5
- export default config;
@@ -1,13 +0,0 @@
1
- /**
2
- * Example test file for NDPR-Toolkit
3
- *
4
- * This file demonstrates how to structure tests for the NDPR-Toolkit.
5
- * Add your actual tests in this directory following a similar pattern.
6
- */
7
-
8
- describe('NDPR-Toolkit', () => {
9
- test('example test setup', () => {
10
- // This is just a placeholder test to demonstrate the test structure
11
- expect(true).toBe(true);
12
- });
13
- });
@@ -1,57 +0,0 @@
1
- import requestService from '@/lib/requestService';
2
-
3
- describe('requestService', () => {
4
- beforeEach(() => {
5
- const localStorageMock = (() => {
6
- let store: Record<string, string> = {};
7
- return {
8
- getItem: (key: string) => (key in store ? store[key] : null),
9
- setItem: (key: string, value: string) => {
10
- store[key] = value;
11
- },
12
- removeItem: (key: string) => {
13
- delete store[key];
14
- },
15
- clear: () => {
16
- store = {};
17
- }
18
- };
19
- })();
20
-
21
- Object.defineProperty(window, 'localStorage', {
22
- value: localStorageMock,
23
- writable: true,
24
- });
25
- requestService.clear();
26
- });
27
-
28
- test('creates and retrieves a request', () => {
29
- const req = requestService.createRequest('access', 'John Doe', 'john@example.com', 'details', true);
30
- const stored = requestService.getRequest(req.id);
31
- expect(stored).not.toBeNull();
32
- expect(stored?.requestType).toBe('access');
33
- expect(stored?.status).toBe('pending');
34
- });
35
-
36
- test('updates request status', () => {
37
- const req = requestService.createRequest('erasure', 'Jane', 'jane@example.com', 'erase', true);
38
- const updated = requestService.updateStatus(req.id, 'completed');
39
- expect(updated?.status).toBe('completed');
40
- const stored = requestService.getRequest(req.id);
41
- expect(stored?.status).toBe('completed');
42
- });
43
-
44
- test('retrieves all requests', () => {
45
- requestService.createRequest('access', 'A', 'a@example.com', 'a', true);
46
- requestService.createRequest('erasure', 'B', 'b@example.com', 'b', true);
47
- const all = requestService.getAllRequests();
48
- expect(all.length).toBe(2);
49
- });
50
-
51
- test('clears storage', () => {
52
- requestService.createRequest('access', 'A', 'a@example.com', 'a', true);
53
- requestService.clear();
54
- const all = requestService.getAllRequests();
55
- expect(all.length).toBe(0);
56
- });
57
- });
@@ -1,70 +0,0 @@
1
- /* Accessibility-focused styles with improved color contrast */
2
-
3
- /* Badge styles with WCAG AA compliant contrast ratios */
4
- .badge-success {
5
- @apply bg-green-700 text-white dark:bg-green-600 dark:text-white;
6
- }
7
-
8
- .badge-warning {
9
- @apply bg-amber-700 text-white dark:bg-amber-600 dark:text-white;
10
- }
11
-
12
- .badge-error {
13
- @apply bg-red-700 text-white dark:bg-red-600 dark:text-white;
14
- }
15
-
16
- .badge-info {
17
- @apply bg-blue-700 text-white dark:bg-blue-600 dark:text-white;
18
- }
19
-
20
- .badge-neutral {
21
- @apply bg-gray-700 text-white dark:bg-gray-500 dark:text-white;
22
- }
23
-
24
- /* Text colors with improved contrast */
25
- .text-muted-accessible {
26
- @apply text-gray-700 dark:text-gray-300;
27
- }
28
-
29
- .text-secondary-accessible {
30
- @apply text-gray-600 dark:text-gray-400;
31
- }
32
-
33
- /* Focus indicators for better keyboard navigation */
34
- .focus-visible-ring {
35
- @apply focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-blue-600 dark:focus-visible:ring-blue-400 focus-visible:ring-offset-background;
36
- }
37
-
38
- /* High contrast mode support */
39
- @media (prefers-contrast: high) {
40
- .badge-success,
41
- .badge-warning,
42
- .badge-error,
43
- .badge-info,
44
- .badge-neutral {
45
- @apply border-2 border-current;
46
- }
47
-
48
- .text-muted-accessible {
49
- @apply text-gray-900 dark:text-gray-100;
50
- }
51
- }
52
-
53
- /* Ensure interactive elements have sufficient size */
54
- .interactive-target {
55
- @apply min-h-[44px] min-w-[44px];
56
- }
57
-
58
- /* Skip link for keyboard navigation */
59
- .skip-link {
60
- @apply sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-50 focus:px-4 focus:py-2 focus:bg-blue-600 focus:text-white focus:rounded-md;
61
- }
62
-
63
- /* Aria live region styles */
64
- .aria-live-polite {
65
- @apply sr-only;
66
- }
67
-
68
- [role="alert"] {
69
- @apply font-medium;
70
- }