Add "Send Confirmation" feature for envelope sending

Introduced a "Send Confirmation" popup to improve user experience
when sending envelopes. The popup allows users to review recipients,
signature fields, and settings before confirming the send action.

- Added localized strings in `Resource.de-DE.resx`, `Resource.en-US.resx`,
  and `Resource.fr-FR.resx` for confirmation messages and actions.
- Updated `SenderEditorPage.razor` to include the confirmation popup
  (`DxPopup`) with body and footer templates.
- Added `RequestSendAsync` and `ConfirmSendAsync` methods to manage
  the confirmation process and sending logic.
- Replaced the old success popup logic with direct navigation to the
  sender dashboard after a successful send.
- Updated the toolbar button to trigger the confirmation popup.
- Styled the confirmation popup in `envelope-viewer.css`, including
  support for dark themes.
- Ensured proper state management for the popup and sending process.

These changes enhance usability by providing a clear confirmation
step and progress feedback during envelope sending.
This commit is contained in:
2026-11-11 16:17:34 +01:00
parent 47c4f33dfc
commit 31933f5568
5 changed files with 152 additions and 8 deletions

View File

@@ -318,7 +318,7 @@
</button>
<button class="pdf-toolbar__btn pdf-toolbar__btn--success"
@onclick="SendAsync"
@onclick="RequestSendAsync"
disabled="@_isSaving"
title='@L("SendEnvelope", "Umschlag senden")'>
@if (_isSaving)
@@ -530,6 +530,46 @@
</BodyContentTemplate>
</DxPopup>
@* ── Send confirmation popup ── *@
<DxPopup @bind-Visible="_sendConfirmVisible"
HeaderText='@L("SenderEditor_SendConfirm_Title", "Umschlag jetzt versenden?")'
SizeMode="SizeMode.Medium"
Width="460px"
MaxWidth="95vw"
ShowFooter="@(!_isSendConfirmSubmitting)"
ShowCloseButton="@(!_isSendConfirmSubmitting)"
CloseOnEscape="@(!_isSendConfirmSubmitting)"
CloseOnOutsideClick="false">
<BodyContentTemplate>
@if (_isSendConfirmSubmitting)
{
<div class="sender-send-progress">
<DxWaitIndicator Visible="true" />
<div>
<p class="sender-send-progress__title">@L("SenderEditor_SendConfirm_InProgress", "Umschlag wird versendet...")</p>
<p class="sender-send-progress__hint">@L("SenderEditor_SendConfirm_InProgressHint", "Bitte warten Sie einen Moment. Der Vorgang wird abgeschlossen.")</p>
</div>
</div>
}
else
{
<div class="sender-confirm-popup sender-confirm-popup--send">
<p class="sender-confirm-popup__note">
@L("SenderEditor_SendConfirm_Message", "Wollen Sie den Umschlag jetzt versenden? Hinweis: Nach der Übergabe kann der Vorgang nicht mehr bearbeitet werden.")
</p>
</div>
}
</BodyContentTemplate>
<FooterContentTemplate>
<DxButton Text='@L("No", "Nein")'
RenderStyle="ButtonRenderStyle.Secondary"
Click='() => _sendConfirmVisible = false' />
<DxButton Text='@L("SenderEditor_SendConfirm_Action", "Ja, versenden")'
RenderStyle="ButtonRenderStyle.Primary"
Click="ConfirmSendAsync" />
</FooterContentTemplate>
</DxPopup>
@* ── Save result popup (success + error) ── *@
<DxPopup @bind-Visible="_savePopupVisible"
HeaderText='@(_saveErrorMessage is null ? _saveSuccessHeader : L("Error", "Fehler"))'
@@ -645,6 +685,8 @@
bool _isSaving = false;
bool _savePopupVisible = false;
bool _clearFieldsConfirmVisible = false;
bool _sendConfirmVisible = false;
bool _isSendConfirmSubmitting = false;
string? _saveErrorMessage = null;
string _saveSuccessHeader = "Erfolg";
string _saveSuccessTitle = "Vorgang erfolgreich abgeschlossen.";
@@ -1241,13 +1283,7 @@
Logger.LogInformation("[SenderEditor] Envelope sent from draft. Id={Id} Status={Status}", sendResult.Id, sendResult.Status);
// Success — show popup; GoToDashboard clears cache and navigates
_saveErrorMessage = null;
_saveSuccessHeader = L("SenderEditor_Sent_Header", "Umschlag gesendet");
_saveSuccessTitle = L("SenderEditor_Sent_Title", "Umschlag wurde erfolgreich gesendet.");
_saveSuccessBody = L("SenderEditor_Sent_Body", "Der bestehende Entwurf wurde versendet.");
_saveNavigateToDashboard = true;
_savePopupVisible = true;
NavigationManager.NavigateTo("/sender", forceLoad: false);
}
catch (Exception ex)
{
@@ -1261,6 +1297,38 @@
}
}
Task RequestSendAsync()
{
if (_isSaving)
return Task.CompletedTask;
_sendConfirmVisible = true;
return Task.CompletedTask;
}
async Task ConfirmSendAsync()
{
if (_isSendConfirmSubmitting)
return;
_isSendConfirmSubmitting = true;
await InvokeAsync(StateHasChanged);
try
{
await SendAsync();
}
finally
{
_isSendConfirmSubmitting = false;
if (_savePopupVisible)
_sendConfirmVisible = false;
await InvokeAsync(StateHasChanged);
}
}
CreateEnvelopeCommand BuildCreateEnvelopeCommand(bool send)
{
NormalizeSettings();