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

@@ -751,6 +751,12 @@
<data name="SenderEditor_RemoveAllSignatureFields" xml:space="preserve"><value>Alle Signaturfelder entfernen</value></data>
<data name="SenderEditor_RemoveAllSignatureFieldsConfirm" xml:space="preserve"><value>Diese Aktion entfernt alle platzierten Signaturfelder unwiderruflich. Fortfahren?</value></data>
<data name="SenderEditor_SelectPdf" xml:space="preserve"><value>Bitte wählen Sie eine PDF-Datei aus.</value></data>
<data name="SenderEditor_SendConfirm_Message" xml:space="preserve"><value>Wollen Sie den Umschlag jetzt versenden? Hinweis: Nach der Übergabe kann der Vorgang nicht mehr bearbeitet werden.</value></data>
<data name="SenderEditor_SendConfirm_Title" xml:space="preserve"><value>Umschlag jetzt versenden?</value></data>
<data name="SenderEditor_SendConfirm_Note" xml:space="preserve"><value>Bitte prüfen Sie Empfänger, Signaturfelder und Einstellungen vor dem Versenden.</value></data>
<data name="SenderEditor_SendConfirm_Action" xml:space="preserve"><value>Jetzt versenden</value></data>
<data name="SenderEditor_SendConfirm_InProgress" xml:space="preserve"><value>Umschlag wird versendet...</value></data>
<data name="SenderEditor_SendConfirm_InProgressHint" xml:space="preserve"><value>Bitte warten Sie einen Moment. Der Vorgang wird abgeschlossen.</value></data>
<data name="SenderEditor_Sent_Body" xml:space="preserve"><value>Der bestehende Entwurf wurde versendet.</value></data>
<data name="SenderEditor_Sent_Header" xml:space="preserve"><value>Umschlag gesendet</value></data>
<data name="SenderEditor_Sent_Title" xml:space="preserve"><value>Umschlag wurde erfolgreich gesendet.</value></data>

View File

@@ -751,6 +751,12 @@
<data name="SenderEditor_RemoveAllSignatureFields" xml:space="preserve"><value>Remove all signature fields</value></data>
<data name="SenderEditor_RemoveAllSignatureFieldsConfirm" xml:space="preserve"><value>This action will permanently remove all placed signature fields. Continue?</value></data>
<data name="SenderEditor_SelectPdf" xml:space="preserve"><value>Please select a PDF file.</value></data>
<data name="SenderEditor_SendConfirm_Message" xml:space="preserve"><value>Do you want to send the envelope now? Note: After handover, the process can no longer be edited.</value></data>
<data name="SenderEditor_SendConfirm_Title" xml:space="preserve"><value>Send envelope now?</value></data>
<data name="SenderEditor_SendConfirm_Note" xml:space="preserve"><value>Please review recipients, signature fields, and settings before sending.</value></data>
<data name="SenderEditor_SendConfirm_Action" xml:space="preserve"><value>Send now</value></data>
<data name="SenderEditor_SendConfirm_InProgress" xml:space="preserve"><value>Sending envelope...</value></data>
<data name="SenderEditor_SendConfirm_InProgressHint" xml:space="preserve"><value>Please wait a moment while we complete the process.</value></data>
<data name="SenderEditor_Sent_Body" xml:space="preserve"><value>The existing draft has been sent.</value></data>
<data name="SenderEditor_Sent_Header" xml:space="preserve"><value>Envelope sent</value></data>
<data name="SenderEditor_Sent_Title" xml:space="preserve"><value>Envelope was sent successfully.</value></data>

View File

@@ -751,6 +751,12 @@
<data name="SenderEditor_RemoveAllSignatureFields" xml:space="preserve"><value>Supprimer tous les champs de signature</value></data>
<data name="SenderEditor_RemoveAllSignatureFieldsConfirm" xml:space="preserve"><value>Cette action supprimera définitivement tous les champs de signature placés. Continuer?</value></data>
<data name="SenderEditor_SelectPdf" xml:space="preserve"><value>Veuillez sélectionner un fichier PDF.</value></data>
<data name="SenderEditor_SendConfirm_Message" xml:space="preserve"><value>Voulez-vous envoyer l'enveloppe maintenant ? Remarque : après la transmission, le processus ne peut plus être modifié.</value></data>
<data name="SenderEditor_SendConfirm_Title" xml:space="preserve"><value>Envoyer l'enveloppe maintenant ?</value></data>
<data name="SenderEditor_SendConfirm_Note" xml:space="preserve"><value>Veuillez vérifier les destinataires, les champs de signature et les paramètres avant l'envoi.</value></data>
<data name="SenderEditor_SendConfirm_Action" xml:space="preserve"><value>Envoyer maintenant</value></data>
<data name="SenderEditor_SendConfirm_InProgress" xml:space="preserve"><value>Envoi de l'enveloppe...</value></data>
<data name="SenderEditor_SendConfirm_InProgressHint" xml:space="preserve"><value>Veuillez patienter un instant pendant la finalisation du traitement.</value></data>
<data name="SenderEditor_Sent_Body" xml:space="preserve"><value>Le brouillon existant a été envoyé.</value></data>
<data name="SenderEditor_Sent_Header" xml:space="preserve"><value>Enveloppe envoyée</value></data>
<data name="SenderEditor_Sent_Title" xml:space="preserve"><value>L'enveloppe a été envoyée avec succès.</value></data>

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();

View File

@@ -2103,3 +2103,61 @@ body.resizing {
gap: 0.5rem;
justify-content: flex-end;
}
.sender-confirm-popup--send {
padding: 0.5rem 0.25rem;
}
.sender-confirm-popup--send .sender-confirm-popup__note {
margin: 0;
text-align: center;
}
.sender-confirm-popup__title {
margin: 0 0 0.4rem;
font-size: 1.02rem;
font-weight: 600;
color: #0f172a;
}
.sender-confirm-popup__note {
margin: 0 0 1rem;
font-size: 0.84rem;
color: #475569;
}
.sender-send-progress {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.5rem 0.25rem;
}
.sender-send-progress__spinner {
width: 1.15rem;
height: 1.15rem;
color: #2563eb;
}
.sender-send-progress__title {
margin: 0 0 0.2rem;
font-size: 0.95rem;
font-weight: 600;
color: #0f172a;
}
.sender-send-progress__hint {
margin: 0;
font-size: 0.83rem;
color: #475569;
}
[data-sf-theme="blazing-dark"] .sender-confirm-popup__title,
[data-sf-theme="blazing-dark"] .sender-send-progress__title {
color: #e2e8f0;
}
[data-sf-theme="blazing-dark"] .sender-confirm-popup__note,
[data-sf-theme="blazing-dark"] .sender-send-progress__hint {
color: #94a3b8;
}