feat: add theme mode support with AppThemeMode enum and AppThemeState service

- Introduced AppThemeMode enum to define theme options: System, Light, Dark.
- Updated AppSettingsDocument to include ThemeMode property.
- Created AppThemeState service to manage current theme mode and handle changes.
- Integrated theme mode handling in CouchbaseLiteAppSettingsService for persistence.
- Added JavaScript for theme management in the frontend, supporting system preference detection.
- Enhanced CSS with theme variables for consistent styling across light and dark modes.
- Updated Playwright tests to ensure sidebar functionality and responsiveness.
This commit is contained in:
MaddoScientisto 2026-04-20 22:58:25 +02:00
commit 158906fa28
19 changed files with 889 additions and 82 deletions

View file

@ -0,0 +1,41 @@
using WorkTracker.Domain;
namespace WorkTracker.Services.Settings;
public sealed class AppThemeState
{
private readonly IAppSettingsService appSettingsService;
private AppThemeMode? currentThemeMode;
public AppThemeState(IAppSettingsService appSettingsService)
{
this.appSettingsService = appSettingsService;
}
public event Action<AppThemeMode>? ThemeModeChanged;
public AppThemeMode CurrentThemeMode => currentThemeMode ?? AppThemeMode.System;
public async Task<AppThemeMode> EnsureLoadedAsync(CancellationToken cancellationToken = default)
{
if (currentThemeMode.HasValue)
{
return currentThemeMode.Value;
}
var settings = await appSettingsService.GetAsync(cancellationToken);
currentThemeMode = settings.ThemeMode;
return CurrentThemeMode;
}
public void SetThemeMode(AppThemeMode themeMode)
{
if (currentThemeMode == themeMode)
{
return;
}
currentThemeMode = themeMode;
ThemeModeChanged?.Invoke(themeMode);
}
}

View file

@ -47,6 +47,7 @@ public sealed class CouchbaseLiteAppSettingsService : IAppSettingsService
private void SaveDocument(AppSettingsDocument settings)
{
var document = new MutableDocument(DefaultSettingsId);
document.SetString("themeMode", settings.ThemeMode.ToString());
document.SetDouble("standardWorkHoursPerDay", Decimal.ToDouble(settings.StandardWorkHoursPerDay));
document.SetDouble("hourlyGrossRate", Decimal.ToDouble(settings.HourlyGrossRate));
document.SetDouble("profitabilityCoefficient", Decimal.ToDouble(settings.ProfitabilityCoefficient));
@ -65,6 +66,7 @@ public sealed class CouchbaseLiteAppSettingsService : IAppSettingsService
return new AppSettingsDocument
{
Id = document.Id,
ThemeMode = ReadThemeMode(document),
StandardWorkHoursPerDay = ReadDecimal(document, "standardWorkHoursPerDay", 8m),
HourlyGrossRate = ReadDecimal(document, "hourlyGrossRate", 17.5m),
ProfitabilityCoefficient = ReadDecimal(document, "profitabilityCoefficient", 0.67m),
@ -84,6 +86,14 @@ public sealed class CouchbaseLiteAppSettingsService : IAppSettingsService
: defaultValue;
}
private static AppThemeMode ReadThemeMode(Document document)
{
var value = document.GetString("themeMode");
return Enum.TryParse<AppThemeMode>(value, ignoreCase: true, out var themeMode)
? themeMode
: AppThemeMode.System;
}
private static DateTimeOffset ReadDateTimeOffset(Document document, string key)
{
var value = document.GetString(key);