diff --git a/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Pages/EnvelopeSenderPage.razor b/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Pages/EnvelopeSenderPage.razor index 25de4614..c8111cbf 100644 --- a/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Pages/EnvelopeSenderPage.razor +++ b/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Pages/EnvelopeSenderPage.razor @@ -8,6 +8,8 @@ @using EnvelopeGenerator.Application.Common.Dto @inject EnvelopeGenerator.Server.Client.Services.EnvelopeService EnvelopeService @inject EnvelopeGenerator.Server.Client.Services.AuthService AuthService +@inject EnvelopeGenerator.Server.Client.Services.ThemeService ThemeService +@inject EnvelopeGenerator.Server.Client.Services.UserPreferencesService UserPreferencesService @inject NavigationManager Navigation @inject IJSRuntime JSRuntime @inject AppVersionService AppVersion @@ -130,7 +132,9 @@ SelectionMode="GridSelectionMode.Single" SelectedDataItem="@_selectedEnvelope" SelectedDataItemChanged="@OnSelectedEnvelopeChanged" - CustomizeElement="OnCustomizeElement"> + CustomizeElement="OnCustomizeElement" + LayoutAutoLoading="OnActiveGridLayoutAutoLoading" + LayoutAutoSaving="OnActiveGridLayoutAutoSaving"> + CustomizeElement="OnCustomizeElement" + LayoutAutoLoading="OnCompletedGridLayoutAutoLoading" + LayoutAutoSaving="OnCompletedGridLayoutAutoSaving"> ((EnvelopeStatus)e.Status).IsActive()).ToList(); _completedEnvelopes = envelopes.Where(e => ((EnvelopeStatus)e.Status).IsCompleted()).ToList(); - - await JSRuntime.InvokeVoidAsync("console.log", $"Loaded {_activeEnvelopes.Count()} active and {_completedEnvelopes.Count()} completed envelopes"); } catch (Exception ex) { _errorMessage = ex.Message; - await JSRuntime.InvokeVoidAsync("console.error", "Fehler beim Laden der Umschläge:", ex.ToString()); } finally { @@ -390,20 +403,19 @@ { if (_selectedEnvelope == null) return; // TODO: Navigate to envelope editor - JSRuntime.InvokeVoidAsync("console.log", $"Edit envelope {_selectedEnvelope.Id} clicked - not yet implemented"); } void DeleteEnvelope() { if (_selectedEnvelope == null) return; // TODO: Show delete confirmation dialog - JSRuntime.InvokeVoidAsync("console.log", $"Delete envelope {_selectedEnvelope.Id} clicked - not yet implemented"); } async Task LogoutAsync() { _isLoggingOut = true; await InvokeAsync(StateHasChanged); + UserPreferencesService.InvalidateCache(); await AuthService.LogoutSenderAsync(); Navigation.NavigateTo("/sender/login", forceLoad: true); } @@ -440,4 +452,45 @@ { _selectedEnvelope = envelope as EnvelopeDto; } + + // ── Grid Layout Persistence ─────────────────────────────────────────────── + // LayoutAutoLoading fires when the grid initializes — restore saved layout. + // LayoutAutoSaving fires when the user changes column order/width/sort — persist it. + // UserPreferencesService.GetAsync() uses the 1h in-memory cache → 0 HTTP on restore. + // UserPreferencesService.SaveGridLayoutAsync() merges the single key → 1 PUT. + + async Task OnActiveGridLayoutAutoLoading(GridPersistentLayoutEventArgs e) + { + // Use cached preferences only — avoid HTTP during grid initialization. + // If cache is empty (LoadFromServerAsync failed), skip layout restore silently. + var prefs = UserPreferencesService.GetCached(); + if (prefs is not null && prefs.GridLayouts.TryGetValue(GridKeyActive, out var json)) + e.Layout = JsonSerializer.Deserialize(json); + } + + async Task OnActiveGridLayoutAutoSaving(GridPersistentLayoutEventArgs e) + { + try + { + var json = JsonSerializer.Serialize(e.Layout); + await UserPreferencesService.SaveGridLayoutAsync(GridKeyActive, json); + } + catch (Exception ex) + { + await JSRuntime.InvokeVoidAsync("console.warn", $"[Sender] Grid layout save failed: {ex.Message}"); + } + } + + async Task OnCompletedGridLayoutAutoLoading(GridPersistentLayoutEventArgs e) + { + var prefs = UserPreferencesService.GetCached(); + if (prefs is not null && prefs.GridLayouts.TryGetValue(GridKeyCompleted, out var json)) + e.Layout = JsonSerializer.Deserialize(json); + } + + async Task OnCompletedGridLayoutAutoSaving(GridPersistentLayoutEventArgs e) + { + var json = JsonSerializer.Serialize(e.Layout); + await UserPreferencesService.SaveGridLayoutAsync(GridKeyCompleted, json); + } } \ No newline at end of file