diff --git a/src/Duempelkas.App/Components/Layout/MainLayout.razor b/src/Duempelkas.App/Components/Layout/MainLayout.razor
index 82d26b2..9459772 100644
--- a/src/Duempelkas.App/Components/Layout/MainLayout.razor
+++ b/src/Duempelkas.App/Components/Layout/MainLayout.razor
@@ -22,7 +22,7 @@
Über Dümpelkas · Version @AppVersion
Entwickler: Andre Beging
-
E-Mail: mail@beging.de
+
E-Mail: mail@beging.de
@if (accounts != null && accounts.Any())
diff --git a/src/Duempelkas.App/Pages/Dashboard.razor.cs b/src/Duempelkas.App/Pages/Dashboard.razor.cs
index 88c801c..6bb3fc1 100644
--- a/src/Duempelkas.App/Pages/Dashboard.razor.cs
+++ b/src/Duempelkas.App/Pages/Dashboard.razor.cs
@@ -1,5 +1,7 @@
using System.Globalization;
using Duempelkas.App.Services.Models;
+using Microsoft.AspNetCore.Components;
+using Microsoft.JSInterop;
namespace Duempelkas.App.Pages;
@@ -18,6 +20,7 @@ public partial class Dashboard
private string? operationMessage;
private string operationMessageClass = "alert-info";
private string? savedPdfPath;
+ private string currentTheme = "light";
#endregion
@@ -37,6 +40,26 @@ public partial class Dashboard
await LoadAll();
}
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ if (!firstRender)
+ {
+ return;
+ }
+
+ try
+ {
+ currentTheme = await JS.InvokeAsync
("duempelkasThemeGetCurrentTheme");
+ }
+ catch (JSException)
+ {
+ // Keep default light mode when JS interop is not ready or unavailable.
+ currentTheme = "light";
+ }
+
+ StateHasChanged();
+ }
+
#endregion
#region Data Loading
@@ -167,5 +190,24 @@ public partial class Dashboard
private string GetFilterLabel() => selectedYear?.ToString() ?? "Alle";
+ private string ThemeButtonLabel => currentTheme == "dark" ? "Hell" : "Dunkel";
+
+ private string ThemeButtonIconClass => currentTheme == "dark" ? "bi bi-sun" : "bi bi-moon-stars";
+
+ private async Task ToggleThemeAsync()
+ {
+ try
+ {
+ currentTheme = await JS.InvokeAsync("duempelkasThemeToggleTheme");
+ }
+ catch (JSException)
+ {
+ currentTheme = currentTheme == "dark" ? "light" : "dark";
+ }
+ }
+
+ [Inject]
+ private IJSRuntime JS { get; set; } = default!;
+
#endregion
}
diff --git a/src/Duempelkas.Desktop/wwwroot/css/app.css b/src/Duempelkas.Desktop/wwwroot/css/app.css
index e2ac6ac..366d9fa 100644
--- a/src/Duempelkas.Desktop/wwwroot/css/app.css
+++ b/src/Duempelkas.Desktop/wwwroot/css/app.css
@@ -1,9 +1,19 @@
-/* Duempelkas App Styles – Dark Mode */
+/* Duempelkas App Styles */
:root {
--color-income: #4ade80;
--color-expense: #f87171;
--color-transfer: #60a5fa;
+ --color-bg: #ddd;
+ --color-surface: #ffffff;
+ --color-surface-hover: #f1f5f9;
+ --color-border: #d9e2ef;
+ --color-text: #0f172a;
+ --color-text-muted: #64748b;
+ --color-accent: #4f46e5;
+}
+
+html[data-ui-theme="dark"] {
--color-bg: #1a1a2e;
--color-surface: #16213e;
--color-surface-hover: #1e2d4a;
@@ -311,7 +321,7 @@ html, body {
.btn-dark {
background-color: #334155;
border-color: #475569;
- color: var(--color-text);
+ color: #f8fafc;
}
.btn-dark:hover {
@@ -319,6 +329,12 @@ html, body {
border-color: #64748b;
}
+html[data-ui-theme="light"] .btn-dark {
+ background-color: #334155;
+ border-color: #334155;
+ color: #f8fafc;
+}
+
/* Table */
.table {
--bs-table-bg: transparent;
diff --git a/src/Duempelkas.Desktop/wwwroot/index.html b/src/Duempelkas.Desktop/wwwroot/index.html
index 15e7fcf..2f14137 100644
--- a/src/Duempelkas.Desktop/wwwroot/index.html
+++ b/src/Duempelkas.Desktop/wwwroot/index.html
@@ -1,9 +1,113 @@
-
+
+
Dümpelkas – Kassenbuch