diff --git a/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Services/EnvelopeService.cs b/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Services/EnvelopeService.cs index 69b9f78e..18d38dbc 100644 --- a/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Services/EnvelopeService.cs +++ b/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Services/EnvelopeService.cs @@ -12,6 +12,8 @@ namespace EnvelopeGenerator.Server.Client.Services; public class EnvelopeService(IHttpClientFactory clientFactory) { private static readonly JsonSerializerOptions _jsonOptions = new(JsonSerializerDefaults.Web); + private sealed record DeleteEnvelopeRequest(string Reason); + private sealed record ErrorResponse(string? Message); /// /// Fetches envelopes from the API with optional filters. @@ -61,4 +63,35 @@ public class EnvelopeService(IHttpClientFactory clientFactory) return await response.Content.ReadFromJsonAsync>(_jsonOptions, cancel); } + + public async Task DeleteAsync(int envelopeId, string reason, CancellationToken cancel = default) + { + var httpClient = clientFactory.CreateClient("EnvelopeGenerator.Server"); + using var request = new HttpRequestMessage(HttpMethod.Delete, $"/api/Envelope/{envelopeId}") + { + Content = JsonContent.Create(new DeleteEnvelopeRequest(reason), options: _jsonOptions) + }; + + var response = await httpClient.SendAsync(request, cancel); + if (response.IsSuccessStatusCode) + return; + + string? message = null; + try + { + var error = await response.Content.ReadFromJsonAsync(_jsonOptions, cancel); + message = error?.Message; + } + catch + { + message = null; + } + + var statusCode = (int)response.StatusCode; + var reasonPhrase = response.ReasonPhrase ?? "Unknown error"; + throw new HttpRequestException( + $"Failed to delete envelope. Status: {statusCode} ({reasonPhrase}){(string.IsNullOrWhiteSpace(message) ? string.Empty : $" - {message}")}", + null, + response.StatusCode); + } } diff --git a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeSenderPage.razor b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeSenderPage.razor index 3446aa48..99532253 100644 --- a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeSenderPage.razor +++ b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeSenderPage.razor @@ -521,6 +521,54 @@ + + +
+

+ Bitte geben Sie einen Grund an, warum der Umschlag gelöscht/zurückgezogen werden soll. +

+ @if (_selectedEnvelope is not null) + { +

+ Umschlag: #@_selectedEnvelope.Id - @_selectedEnvelope.Title +

+ } + + @if (!string.IsNullOrWhiteSpace(_deleteErrorMessage)) + { +
+ @_deleteErrorMessage +
+ } +
+
+ +
+ + +
+
+
+ @code { private IEnumerable? _allEnvelopes; private IEnumerable? _activeEnvelopes; @@ -549,6 +597,11 @@ private bool _exportSelectedRowsOnly = false; private bool _isExporting = false; + private bool _deletePopupVisible = false; + private bool _isDeletingEnvelope = false; + private string _deleteReason = string.Empty; + private string? _deleteErrorMessage; + // Stable keys used to store/restore each grid's layout in UserPreferences.GridLayouts private const string GridKeyActive = "sender.active-envelopes"; private const string GridKeyCompleted = "sender.completed-envelopes"; @@ -681,7 +734,51 @@ void DeleteEnvelope() { if (_selectedEnvelope == null) return; - // TODO: Show delete confirmation dialog + _deleteReason = string.Empty; + _deleteErrorMessage = null; + _deletePopupVisible = true; + } + + void CloseDeletePopup() + { + if (_isDeletingEnvelope) + return; + + _deletePopupVisible = false; + _deleteErrorMessage = null; + } + + async Task ConfirmDeleteEnvelopeAsync() + { + if (_selectedEnvelope is null) + return; + + if (string.IsNullOrWhiteSpace(_deleteReason)) + { + _deleteErrorMessage = "Bitte geben Sie einen Löschgrund an."; + return; + } + + _isDeletingEnvelope = true; + _deleteErrorMessage = null; + await InvokeAsync(StateHasChanged); + + try + { + await EnvelopeService.DeleteAsync(_selectedEnvelope.Id, _deleteReason.Trim()); + _deletePopupVisible = false; + _selectedEnvelope = null; + await LoadEnvelopesAsync(); + } + catch (Exception ex) + { + _deleteErrorMessage = ex.Message; + } + finally + { + _isDeletingEnvelope = false; + await InvokeAsync(StateHasChanged); + } } async Task LogoutAsync()