Skip to content

Commit ecd05d5

Browse files
Merge pull request #19 from VedantAnand17/feature/dark-mode
Add dark mode support with theme toggle and system preference detection
2 parents ae443f2 + a2bdd13 commit ecd05d5

4 files changed

Lines changed: 242 additions & 76 deletions

File tree

webapp/index.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@
3636
<li><a href="#assessment" class="nav-link active">Assessment</a></li>
3737
<li><a href="#overview" class="nav-link">Overview</a></li>
3838
<li><a href="#export" class="nav-link">Export</a></li>
39+
<li class="theme-switcher">
40+
<button class="theme-toggle" id="themeToggle" aria-label="Toggle dark mode">
41+
<i class="fas fa-sun" id="lightIcon"></i>
42+
<i class="fas fa-moon" id="darkIcon"></i>
43+
</button>
44+
</li>
3945
<li class="language-switcher">
4046
<div class="language-dropdown">
4147
<button class="dropdown-toggle" id="languageToggle">

webapp/js/data.js

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -369,13 +369,13 @@ const gdprData = {
369369
subtitle: "Interaktive Checkliste zur Bewertung der DSGVO-Konformität Ihrer Website",
370370
categories: [
371371
{
372-
id: "sicherheit",
372+
id: "security",
373373
title: "Sicherheit",
374374
icon: "fas fa-shield-alt",
375375
description: "Technische und organisatorische Maßnahmen zum Schutz personenbezogener Daten",
376376
items: [
377377
{
378-
id: "ssl-webseite",
378+
id: "ssl-website",
379379
title: "SSL/TLS-Transportverschlüsselung Webseite",
380380
description: "Transportverschlüsselung sollte immer dann verwendet werden, wenn personenbezogene Daten übertragen werden, insbesondere bei sämtlichen Formulardaten.",
381381
required: true,
@@ -404,7 +404,7 @@ const gdprData = {
404404
]
405405
},
406406
{
407-
id: "cms-sicherheit",
407+
id: "cms-security",
408408
title: "Sicherheitskonzept des CMS (z.B. WordPress)",
409409
description: "Schutz vor Brute-Force-Attacken, Kommentar-SPAM und Sicherheitslücken in CMS, Plugins und Themes.",
410410
required: true,
@@ -419,7 +419,7 @@ const gdprData = {
419419
]
420420
},
421421
{
422-
id: "server-sicherheit",
422+
id: "server-security",
423423
title: "Sicherheitskonzept des Servers",
424424
description: "Serververantwortung variiert je nach Hosting-Typ (Shared, VPS, Dedicated Server).",
425425
required: true,
@@ -431,7 +431,7 @@ const gdprData = {
431431
]
432432
},
433433
{
434-
id: "email-verschluesselung",
434+
id: "email-encryption",
435435
title: "Signatur und/oder Inhaltsverschlüsselung bei E-Mails (Optional)",
436436
description: "Elektronische Signaturen und Inhaltsverschlüsselung fördern die E-Mail-Sicherheit und rechtliche Nachweisbarkeit.",
437437
required: false,
@@ -448,7 +448,7 @@ const gdprData = {
448448
]
449449
},
450450
{
451-
id: "webhoster",
451+
id: "hosting",
452452
title: "Webhoster",
453453
icon: "fas fa-server",
454454
description: "Auftragsverarbeitungsverträge und Log-Management mit Webhostern",
@@ -467,7 +467,7 @@ const gdprData = {
467467
]
468468
},
469469
{
470-
id: "weitere-server-logs",
470+
id: "server-logs",
471471
title: "Weitere Server Logs",
472472
description: "Webhoster sind verpflichtet, weitere Server Logs zur Sicherheitsüberwachung zu führen, die ebenfalls IP-Adressen speichern.",
473473
required: true,
@@ -479,7 +479,7 @@ const gdprData = {
479479
]
480480
},
481481
{
482-
id: "webseiten-installation",
482+
id: "dpa-hosting",
483483
title: "Auftragsverarbeitungsvertrag mit Webhoster",
484484
description: "Alle auf Servern gespeicherten personenbezogenen Daten stellen 'Verarbeitung' dar und erfordern AVV mit dem Webhoster.",
485485
required: true,
@@ -494,13 +494,13 @@ const gdprData = {
494494
]
495495
},
496496
{
497-
id: "externe-dienste",
497+
id: "external-services",
498498
title: "Externe Dienste",
499499
icon: "fas fa-plug",
500500
description: "Drittanbieter-Services und Tools, die personenbezogene Daten verarbeiten können",
501501
items: [
502502
{
503-
id: "analyse-tools",
503+
id: "analytics-tools",
504504
title: "Analyse-Tools (Google Analytics, Matomo, etc.)",
505505
description: "Analyse-Tools mit Datenspeicherung in den USA sind seit dem Schrems II-Urteil (2020) nicht DSGVO-konform.",
506506
required: true,
@@ -556,7 +556,7 @@ const gdprData = {
556556
]
557557
},
558558
{
559-
id: "verwertungsgesellschaften",
559+
id: "royalty-collecting-societies",
560560
title: "Verwertungsgesellschaften (VG-Wort)",
561561
description: "Zählpixel von Verwertungsgesellschaften übertragen IP-Adressen und erfordern Einwilligung.",
562562
required: true,
@@ -569,7 +569,7 @@ const gdprData = {
569569
]
570570
},
571571
{
572-
id: "webfonts",
572+
id: "web-fonts",
573573
title: "Webfonts (Google Fonts, Adobe Typekit, etc.)",
574574
description: "Web-Schriften erfordern Einwilligung und sollten lokalisiert werden, um Datenübertragung an Dritte zu vermeiden.",
575575
required: true,
@@ -583,7 +583,7 @@ const gdprData = {
583583
]
584584
},
585585
{
586-
id: "profile-bilder",
586+
id: "profile-pictures",
587587
title: "Profile bzw. Profilbilder (Gravatar, About.me)",
588588
description: "Externe Profilbild-Services übertragen E-Mail-Hashes und IP-Adressen an Drittanbieter.",
589589
required: true,
@@ -649,7 +649,7 @@ const gdprData = {
649649
]
650650
},
651651
{
652-
id: "video-musik-dienste",
652+
id: "video-music-services",
653653
title: "Video- und Musikdienste (YouTube, Vimeo, Spotify, SoundCloud)",
654654
description: "Eingebettete Videos und Musik von YouTube, Vimeo, Spotify, SoundCloud übertragen personenbezogene Daten und erfordern 2-Klick-Lösungen.",
655655
required: true,
@@ -663,7 +663,7 @@ const gdprData = {
663663
]
664664
},
665665
{
666-
id: "kartendienste",
666+
id: "map-services",
667667
title: "Kartendienste (Google Maps, Open Street Maps, etc.)",
668668
description: "Kartendienste wie Google Maps sammeln personenbezogene Daten beim Seitenladen und speichern meist Daten in den USA.",
669669
required: true,
@@ -679,13 +679,13 @@ const gdprData = {
679679
]
680680
},
681681
{
682-
id: "weitere-aspekte",
682+
id: "content-features",
683683
title: "Weitere Aspekte",
684684
icon: "fas fa-cogs",
685685
description: "Website-Features, die personenbezogene Daten sammeln oder verarbeiten können",
686686
items: [
687687
{
688-
id: "kommentarfunktion",
688+
id: "comments",
689689
title: "Kommentarfunktion",
690690
description: "Kommentarsysteme sollten IP-Adress-Speicherung begrenzen und Nutzer über Datensammlung informieren.",
691691
required: true,
@@ -699,7 +699,7 @@ const gdprData = {
699699
]
700700
},
701701
{
702-
id: "weblinks",
702+
id: "external-links",
703703
title: "Weblinks",
704704
description: "Externe Links sollten mit geeigneten Attributen versehen und in der Datenschutzerklärung erwähnt werden.",
705705
required: false,
@@ -712,7 +712,7 @@ const gdprData = {
712712
]
713713
},
714714
{
715-
id: "plugins-erweiterungen",
715+
id: "plugins-extensions",
716716
title: "Plugins/Erweiterungen/Module",
717717
description: "Alle Plugins und Erweiterungen auf Datenschutz-Konformität prüfen und regelmäßig aktualisieren.",
718718
required: true,
@@ -743,13 +743,13 @@ const gdprData = {
743743
]
744744
},
745745
{
746-
id: "rechtsdokumente",
746+
id: "legal-documents",
747747
title: "Rechtsdokumente",
748748
icon: "fas fa-file-contract",
749749
description: "Erforderliche rechtliche Seiten und Compliance-Dokumentation",
750750
items: [
751751
{
752-
id: "allgemein-rechtskonformitaet",
752+
id: "general-compliance",
753753
title: "Allgemeine Rechtskonformität",
754754
description: "Grundlegende rechtliche Anforderungen für alle Websites in Deutschland.",
755755
required: true,
@@ -778,7 +778,7 @@ const gdprData = {
778778
]
779779
},
780780
{
781-
id: "datenschutzerklaerung",
781+
id: "privacy-policy",
782782
title: "Datenschutzerklärung",
783783
description: "Umfassende Datenschutzerklärung von jeder Seite aus zugänglich, die alle Datenverarbeitungsaktivitäten detailliert.",
784784
required: true,
@@ -793,7 +793,7 @@ const gdprData = {
793793
]
794794
},
795795
{
796-
id: "impressum",
796+
id: "imprint",
797797
title: "Impressum",
798798
description: "Erforderliche rechtliche Angaben einschließlich Kontaktdaten und Geschäftsinformationen (deutsches/EU-Recht).",
799799
required: true,
@@ -822,7 +822,7 @@ const gdprData = {
822822
]
823823
},
824824
{
825-
id: "urheberrecht-bildnachweise",
825+
id: "copyright-credits",
826826
title: "Urheberrecht/Bildnachweise",
827827
description: "Ordnungsgemäße Quellenangaben für alle externen Werke (Bilder, Grafiken, Musik, Videos, Texte, Software).",
828828
required: true,

webapp/js/main.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ class GDPRApp {
5454
// Language switching
5555
this.setupLanguageSwitching();
5656

57+
// Theme switching
58+
this.setupThemeSwitching();
59+
5760
// Mobile navigation
5861
this.setupMobileNavigation();
5962

@@ -84,6 +87,52 @@ class GDPRApp {
8487
// Language switching is now handled by the assessment manager
8588
// This method is kept for backwards compatibility
8689
}
90+
91+
setupThemeSwitching() {
92+
const themeToggle = document.getElementById('themeToggle');
93+
if (!themeToggle) return;
94+
95+
// Initialize theme from localStorage or system preference
96+
this.initializeTheme();
97+
98+
// Setup theme toggle button
99+
themeToggle.addEventListener('click', () => {
100+
const currentTheme = document.documentElement.getAttribute('data-theme');
101+
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
102+
this.setTheme(newTheme);
103+
});
104+
}
105+
106+
initializeTheme() {
107+
// Check if user previously set a theme preference
108+
const savedTheme = localStorage.getItem('gdpr_theme');
109+
110+
if (savedTheme) {
111+
// Use saved preference
112+
this.setTheme(savedTheme);
113+
} else {
114+
// Check system preference
115+
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
116+
this.setTheme('dark');
117+
} else {
118+
this.setTheme('light');
119+
}
120+
121+
// Listen for system preference changes
122+
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
123+
const newTheme = e.matches ? 'dark' : 'light';
124+
this.setTheme(newTheme);
125+
});
126+
}
127+
}
128+
129+
setTheme(theme) {
130+
document.documentElement.setAttribute('data-theme', theme);
131+
localStorage.setItem('gdpr_theme', theme);
132+
133+
// Update icon visibility is handled by CSS
134+
console.log(`Theme set to: ${theme}`);
135+
}
87136

88137
setupMobileNavigation() {
89138
const navToggle = document.querySelector('.nav-toggle');

0 commit comments

Comments
 (0)