refactor(app): add theme toggle functionality and improve theme management

This commit is contained in:
2026-04-03 14:51:45 +02:00
parent 68c7a1ca6a
commit e21a2fc1c5
5 changed files with 169 additions and 4 deletions

View File

@@ -1,9 +1,113 @@
<!DOCTYPE html>
<html lang="de" data-bs-theme="dark">
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
<script>
(function () {
function getCookie(name) {
var parts = document.cookie ? document.cookie.split(';') : [];
for (var i = 0; i < parts.length; i++) {
var part = parts[i].trim();
if (part.indexOf(name + '=') === 0) {
return decodeURIComponent(part.substring(name.length + 1));
}
}
return null;
}
function setCookie(name, value) {
document.cookie = name + '=' + encodeURIComponent(value) + '; path=/; max-age=31536000; samesite=lax';
}
function getStoredTheme() {
try {
var fromStorage = localStorage.getItem('duempelkas-theme');
if (fromStorage === 'light' || fromStorage === 'dark') {
return fromStorage;
}
} catch (_) {
// Ignore storage access issues and fall back to cookies/system.
}
var fromCookie = getCookie('duempelkas-theme');
if (fromCookie === 'light' || fromCookie === 'dark') {
return fromCookie;
}
return null;
}
function detectSystemTheme() {
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark';
}
return 'light';
}
function normalizeTheme(value) {
return value === 'dark' ? 'dark' : 'light';
}
function applyTheme(theme, persist) {
var resolved = normalizeTheme(theme);
document.documentElement.setAttribute('data-ui-theme', resolved);
document.documentElement.setAttribute('data-bs-theme', resolved);
if (document.body) {
document.body.setAttribute('data-ui-theme', resolved);
document.body.setAttribute('data-bs-theme', resolved);
}
if (persist) {
try {
localStorage.setItem('duempelkas-theme', resolved);
} catch (_) {
// Ignore storage access issues and keep cookie as fallback.
}
setCookie('duempelkas-theme', resolved);
}
return resolved;
}
var initialTheme = getStoredTheme() || detectSystemTheme() || 'light';
applyTheme(initialTheme, false);
var duempelkasThemeGetCurrentTheme = function () {
var current = document.documentElement.getAttribute('data-ui-theme');
return normalizeTheme(current);
};
var duempelkasThemeSetTheme = function (theme) {
return applyTheme(theme, true);
};
var duempelkasThemeToggleTheme = function () {
var current = document.documentElement.getAttribute('data-ui-theme');
var next = current === 'dark' ? 'light' : 'dark';
return applyTheme(next, true);
};
globalThis.duempelkasThemeGetCurrentTheme = duempelkasThemeGetCurrentTheme;
globalThis.duempelkasThemeSetTheme = duempelkasThemeSetTheme;
globalThis.duempelkasThemeToggleTheme = duempelkasThemeToggleTheme;
window.duempelkasThemeGetCurrentTheme = duempelkasThemeGetCurrentTheme;
window.duempelkasThemeSetTheme = duempelkasThemeSetTheme;
window.duempelkasThemeToggleTheme = duempelkasThemeToggleTheme;
// Keep object-style API for compatibility with older calls.
window.duempelkasTheme = {
getCurrentTheme: duempelkasThemeGetCurrentTheme,
setTheme: duempelkasThemeSetTheme,
toggleTheme: duempelkasThemeToggleTheme
};
})();
</script>
<title>Dümpelkas Kassenbuch</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet"