From 3b66de0691d07e7a8622a016d94c7e50983b5da4 Mon Sep 17 00:00:00 2001 From: TekH Date: Mon, 15 Jun 2026 17:00:23 +0200 Subject: [PATCH] Enhance EnvelopeSenderPage with new UI and features Integrated DevExpress Blazor components and added a responsive, modern UI for the sender dashboard. Replaced placeholder content with a functional layout, including a grid-based envelope viewer with filtering, pagination, and detailed row templates. Added status badges, progress indicators, and a sender action bar with buttons for creating, editing, deleting, refreshing envelopes, and logging out. Introduced loading and error handling states for better user experience. Refactored data loading with `LoadEnvelopesAsync` to fetch and categorize envelopes. Added methods for envelope management and logout functionality. Improved state management and removed unused code. These changes lay the groundwork for future enhancements. --- .../Pages/EnvelopeSenderPage.razor | 702 +++++++++++++++++- 1 file changed, 691 insertions(+), 11 deletions(-) diff --git a/EnvelopeGenerator.ReceiverUI/Pages/EnvelopeSenderPage.razor b/EnvelopeGenerator.ReceiverUI/Pages/EnvelopeSenderPage.razor index a91c9290..6b6dfcc8 100644 --- a/EnvelopeGenerator.ReceiverUI/Pages/EnvelopeSenderPage.razor +++ b/EnvelopeGenerator.ReceiverUI/Pages/EnvelopeSenderPage.razor @@ -3,35 +3,715 @@ @using System.Text.Json @using EnvelopeGenerator.ReceiverUI.Models +@using DevExpress.Blazor @inject EnvelopeGenerator.ReceiverUI.Services.EnvelopeService EnvelopeService +@inject EnvelopeGenerator.ReceiverUI.Services.AuthService AuthService +@inject NavigationManager Navigation @inject IJSRuntime JSRuntime -

Umschläge

+ + -

Daten werden geladen und in der Konsole ausgegeben...

+ + +
+
+
+
+ +
Umschlag-Übersicht
+
+ +
+ + + + + + + + + +
+
+
+ +
+ @if (_isLoading && _allEnvelopes == null) { +
+
+
+ Lädt... +
+

Umschläge werden geladen...

+
+
+ } else if (_errorMessage != null) { +
+
+
+ + + + +
+
Fehler beim Laden der Umschläge
+

@_errorMessage

+
+
+
+
+ } else { +
+
+ + +
+ +
+ @if (_activeTab == "active") { + + + + + + @((cellContext.DataItem as EnvelopeDto)?.Title) + + + + + @{ + var envelope = cellContext.DataItem as EnvelopeDto; + if (envelope != null) { + var statusInfo = GetStatusInfo(envelope.Status); +
+ + @statusInfo.Label +
+ } + } +
+
+ + + @{ + var envelope = cellContext.DataItem as EnvelopeDto; + if (envelope != null) { + var receivers = envelope.EnvelopeReceivers ?? new List(); + var signed = receivers.Count(r => r.Signed); + var total = receivers.Count; +
+ + @signed / @total unterschrieben + + @if (total > 0) { +
+
+
+ } +
+ } + } +
+
+
+ +
+
Empfänger
+ @{ + var envelope = detailContext.DataItem as EnvelopeDto; + if (envelope?.EnvelopeReceivers?.Any() == true) { +
+ @foreach (var receiver in envelope.EnvelopeReceivers) { +
+ + @if (receiver.Signed) { + + + + Unterschrieben + } else { + + + + + Ausstehend + } + +
+ @receiver.Name + @receiver.Email +
+
+ } +
+ } else { +

Keine Empfänger

+ } + } +
+
+
+ } else { + + + + + + @((cellContext.DataItem as EnvelopeDto)?.Title) + + + + + @{ + var envelope = cellContext.DataItem as EnvelopeDto; + if (envelope != null) { + var statusInfo = GetStatusInfo(envelope.Status); +
+ + @statusInfo.Label +
+ } + } +
+
+ + + @{ + var envelope = cellContext.DataItem as EnvelopeDto; + if (envelope != null) { + var receivers = envelope.EnvelopeReceivers ?? new List(); + var signed = receivers.Count(r => r.Signed); + var total = receivers.Count; +
+ + @signed / @total unterschrieben + + @if (total > 0) { +
+
+
+ } +
+ } + } +
+
+
+ +
+
Empfänger
+ @{ + var envelope = detailContext.DataItem as EnvelopeDto; + if (envelope?.EnvelopeReceivers?.Any() == true) { +
+ @foreach (var receiver in envelope.EnvelopeReceivers) { +
+ + @if (receiver.Signed) { + + + + Unterschrieben + } else { + + + + + Ausstehend + } + +
+ @receiver.Name + @receiver.Email +
+
+ } +
+ } else { +

Keine Empfänger

+ } + } +
+
+
+ } +
+
+ } +
+
@code { + private IEnumerable? _allEnvelopes; private IEnumerable? _activeEnvelopes; private IEnumerable? _completedEnvelopes; - - private static readonly JsonSerializerOptions _jsonOptions = new(JsonSerializerDefaults.Web); + private EnvelopeDto? _selectedEnvelope; + private string _activeTab = "active"; + private bool _isLoading = true; + private bool _isLoggingOut = false; + private string? _errorMessage; + private DxGrid? _gridActive; + private DxGrid? _gridCompleted; protected override async Task OnInitializedAsync() { + await LoadEnvelopesAsync(); + } + + async Task LoadEnvelopesAsync() + { + _isLoading = true; + _errorMessage = null; + await InvokeAsync(StateHasChanged); + try { - _activeEnvelopes = await EnvelopeService.GetAsync(onlyActive: true); - _completedEnvelopes = await EnvelopeService.GetAsync(onlyCompleted: true); + _allEnvelopes = await EnvelopeService.GetAsync(); + + // Split into active and completed based on status + var envelopes = _allEnvelopes.ToList(); + _activeEnvelopes = envelopes.Where(e => ((EnvelopeStatus)e.Status).IsActive()).ToList(); + _completedEnvelopes = envelopes.Where(e => ((EnvelopeStatus)e.Status).IsCompleted()).ToList(); - await JSRuntime.InvokeVoidAsync("console.log", "----- Aktive Umschläge -----"); - await JSRuntime.InvokeVoidAsync("console.log", _activeEnvelopes); - - await JSRuntime.InvokeVoidAsync("console.log", "----- Abgeschlossene Umschläge -----"); - await JSRuntime.InvokeVoidAsync("console.log", _completedEnvelopes); + 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 + { + _isLoading = false; + await InvokeAsync(StateHasChanged); + } + } + + async Task RefreshEnvelopes() + { + await LoadEnvelopesAsync(); + } + + void CreateEnvelope() + { + // TODO: Navigate to envelope creation page + JSRuntime.InvokeVoidAsync("console.log", "Create envelope clicked - not yet implemented"); + } + + void EditEnvelope() + { + 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); + await AuthService.LogoutSenderAsync(); + Navigation.NavigateTo("/sender/login", forceLoad: true); + } + + bool IsEnvelopeSent(EnvelopeDto envelope) + { + var status = (EnvelopeStatus)envelope.Status; + return status >= EnvelopeStatus.EnvelopeQueued; + } + + (string Label, string CssClass, string DotColor) GetStatusInfo(int statusCode) + { + var status = (EnvelopeStatus)statusCode; + return status switch + { + EnvelopeStatus.EnvelopePartlySigned => ("Teilweise unterschrieben", "partly-signed", "green"), + EnvelopeStatus.EnvelopeQueued => ("In Warteschlange", "queued", "orange"), + EnvelopeStatus.EnvelopeSent => ("Gesendet", "sent", "orange"), + EnvelopeStatus.EnvelopeCompletelySigned => ("Vollständig unterschrieben", "completed", "green"), + EnvelopeStatus.EnvelopeDeleted => ("Gelöscht", "deleted", "red"), + EnvelopeStatus.EnvelopeRejected => ("Abgelehnt", "rejected", "red"), + EnvelopeStatus.EnvelopeWithdrawn => ("Zurückgezogen", "withdrawn", "red"), + EnvelopeStatus.EnvelopeCreated => ("Erstellt", "created", "blue"), + EnvelopeStatus.EnvelopeSaved => ("Gespeichert", "saved", "blue"), + _ => ("Unbekannt", "unknown", "blue") + }; + } + + void OnCustomizeElement(GridCustomizeElementEventArgs e) + { + // Future: Add custom row coloring based on status if needed + } + + void OnSelectedEnvelopeChanged(object envelope) + { + _selectedEnvelope = envelope as EnvelopeDto; } } \ No newline at end of file