@page "/" @rendermode InteractiveWebAssembly @attribute [Authorize] @inject ITimetrackerService TrackerService @inject AuthenticationStateProvider AuthStateProvider @inject IJSRuntime JSRuntime Dashboard – Timetracker @if (_loading) { Lade Dashboard… } else { @* ── Header & Einstellungen ── *@ @* ── Gamification Widgets ── *@ @if (_showEarlyBird) { 🌅 Early Bird @FormatTimeSpan(_stats.EarliestStart) Frühester Beginn im Monat } @if (_showNightOwl) { 🦉 Night Owl @FormatTimeSpan(_stats.LatestEnd) Spätestes Ende im Monat } @if (_showPausenkonig) { Pausenkönig @((int)_stats.AverageBreak.TotalMinutes) Min. Ø Pause im Monat } @if (_showStreaks) { 🔥 Streak @_stats.CurrentStreak / @_stats.LongestStreak Aktuell / Bester (Tage) } @* ── Diagramme ── *@ @if (_showCharts) { Gleitzeit-Verlauf @DateTime.Today.Year Jahres-Verteilung } } @code { private bool _loading = true; private DashboardStatsVm _stats = new(); private DashboardChartDataVm _chartData = new(); private bool _showEarlyBird = true; private bool _showNightOwl = true; private bool _showPausenkonig = true; private bool _showStreaks = true; private bool _showCharts = true; private List> _barChartSeries = new(); private string[] _barChartLabels = Array.Empty(); private double[] _pieChartData = Array.Empty(); private string[] _pieChartLabels = Array.Empty(); protected override async Task OnInitializedAsync() { var authState = await AuthStateProvider.GetAuthenticationStateAsync(); var claim = authState.User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier); if (claim == null) return; int userId = int.Parse(claim.Value); int year = DateTime.Today.Year; int month = DateTime.Today.Month; await LoadSettings(); _stats = await TrackerService.GetDashboardStatsAsync(userId, year, month); _chartData = await TrackerService.GetDashboardChartDataAsync(userId, year); // Prepare Bar Chart _barChartSeries = new List> { new ChartSeries { Name = "Überstunden", Data = _chartData.MonthlyOvertime.Select(m => m.OvertimeHours).ToArray() } }; _barChartLabels = _chartData.MonthlyOvertime.Select(m => m.MonthName).ToArray(); // Prepare Pie Chart _pieChartData = new double[] { _chartData.WorkDaysCount, _chartData.VacationDaysCount, _chartData.PublicHolidaysCount }; _pieChartLabels = new string[] { "Arbeit", "Urlaub", "Feiertage" }; _loading = false; } private async Task LoadSettings() { try { var eb = await JSRuntime.InvokeAsync("localStorage.getItem", "widget_EarlyBird"); if (eb != null) _showEarlyBird = eb == "true"; var no = await JSRuntime.InvokeAsync("localStorage.getItem", "widget_NightOwl"); if (no != null) _showNightOwl = no == "true"; var pk = await JSRuntime.InvokeAsync("localStorage.getItem", "widget_Pausenkonig"); if (pk != null) _showPausenkonig = pk == "true"; var st = await JSRuntime.InvokeAsync("localStorage.getItem", "widget_Streaks"); if (st != null) _showStreaks = st == "true"; var ch = await JSRuntime.InvokeAsync("localStorage.getItem", "widget_Charts"); if (ch != null) _showCharts = ch == "true"; } catch { // SSR Fallback } } private async Task ToggleWidget(string widget) { bool newState = true; if (widget == "EarlyBird") { _showEarlyBird = !_showEarlyBird; newState = _showEarlyBird; } if (widget == "NightOwl") { _showNightOwl = !_showNightOwl; newState = _showNightOwl; } if (widget == "Pausenkonig") { _showPausenkonig = !_showPausenkonig; newState = _showPausenkonig; } if (widget == "Streaks") { _showStreaks = !_showStreaks; newState = _showStreaks; } if (widget == "Charts") { _showCharts = !_showCharts; newState = _showCharts; } try { await JSRuntime.InvokeVoidAsync("localStorage.setItem", $"widget_{widget}", newState.ToString().ToLower()); } catch { } } private string FormatTimeSpan(TimeSpan? ts) { if (!ts.HasValue) return "-"; return $"{ts.Value.Hours:D2}:{ts.Value.Minutes:D2}"; } }