- Introduce ActionPanel, EnvelopeInfoCard, TfaForm, ConfirmDialog, StatusPage, and Toast components for modular, presentational UI - Add ToastService for pub/sub toast notifications; register in DI - Refactor AccessCodeForm for improved UX and parameterization - Enhance MainLayout with Toast integration and better error handling - Standardize and extend app.css for new components and responsive design - All new components are "dumb" (no service/API knowledge), using EventCallbacks for parent interaction - ConfirmDialog supports awaitable user confirmation via TaskCompletionSource
126 lines
4.8 KiB
Plaintext
126 lines
4.8 KiB
Plaintext
@* ActionPanel: Fixierte Button-Leiste am unteren Bildschirmrand.
|
|
Entspricht dem <div id="flex-action-panel"> in ShowEnvelope.cshtml.
|
|
|
|
Wird angezeigt wenn der Empfänger das Dokument sieht (Status = ShowDocument).
|
|
Bei ReadOnly-Dokumenten wird nichts angezeigt.
|
|
|
|
Die Buttons lösen EventCallbacks aus. Die Eltern-Komponente (EnvelopePage)
|
|
entscheidet, was passiert (API-Call etc.).
|
|
|
|
Der ConfirmDialog wird über eine Referenz aufgerufen:
|
|
var confirmed = await _confirmDialog.ShowAsync("Titel", "Text");
|
|
|
|
WARUM EventCallbacks statt direkte API-Calls?
|
|
- Die Komponente bleibt "dumm" (keine Services, kein API-Wissen)
|
|
- Die Eltern-Page kann den gleichen Button-Click anders behandeln
|
|
- Einfacher zu testen *@
|
|
|
|
@if (!ReadOnly)
|
|
{
|
|
@* position-fixed: Bleibt am unteren Rand auch beim Scrollen.
|
|
Gleiche Positionierung wie im Web-Projekt. *@
|
|
<div class="position-fixed bottom-0 end-0 p-3 d-flex gap-2" style="z-index: 1050;">
|
|
|
|
@* Zurücksetzen-Button: Setzt alle Signaturen zurück.
|
|
Im Web-Projekt ist das der graue Button mit dem
|
|
Pfeil-gegen-den-Uhrzeigersinn-Icon. *@
|
|
<button class="btn btn-secondary" @onclick="HandleRefresh" title="Zurücksetzen">
|
|
<i class="bi bi-arrow-counterclockwise"></i>
|
|
</button>
|
|
|
|
@* Ablehnen-Button: Öffnet ConfirmDialog, dann EventCallback.
|
|
Im Web-Projekt ist das der rote Button mit dem X-Icon. *@
|
|
<button class="btn btn-danger" @onclick="HandleReject" title="Ablehnen">
|
|
<i class="bi bi-x-lg me-1"></i>
|
|
<span class="d-none d-md-inline">Ablehnen</span>
|
|
</button>
|
|
|
|
@* Unterschreiben-Button: Öffnet ConfirmDialog, dann EventCallback.
|
|
Im Web-Projekt ist das der grüne Button mit dem Briefumschlag-Icon. *@
|
|
<button class="btn btn-success" @onclick="HandleSign" title="Unterschreiben">
|
|
<i class="bi bi-pen me-1"></i>
|
|
<span class="d-none d-md-inline">Unterschreiben</span>
|
|
</button>
|
|
</div>
|
|
}
|
|
|
|
@* ConfirmDialog: Wird nur gerendert wenn nötig (wenn ShowAsync aufgerufen wird).
|
|
Die Referenz (_confirmDialog) erlaubt uns, ShowAsync von den Button-Handlern aufzurufen. *@
|
|
<ConfirmDialog @ref="_confirmDialog" />
|
|
|
|
@code {
|
|
// ── Parameter ──
|
|
|
|
/// <summary>Bei ReadOnly wird das gesamte Panel ausgeblendet</summary>
|
|
[Parameter]
|
|
public bool ReadOnly { get; set; }
|
|
|
|
/// <summary>Wird ausgelöst wenn der Benutzer "Unterschreiben" bestätigt</summary>
|
|
[Parameter]
|
|
public EventCallback OnSign { get; set; }
|
|
|
|
/// <summary>Wird ausgelöst wenn der Benutzer "Ablehnen" bestätigt</summary>
|
|
[Parameter]
|
|
public EventCallback OnReject { get; set; }
|
|
|
|
/// <summary>Wird ausgelöst wenn der Benutzer "Zurücksetzen" klickt</summary>
|
|
[Parameter]
|
|
public EventCallback OnRefresh { get; set; }
|
|
|
|
// ── Referenz auf den ConfirmDialog ──
|
|
|
|
/// <summary>
|
|
/// Referenz auf die ConfirmDialog-Komponente.
|
|
///
|
|
/// WAS IST @ref?
|
|
/// Mit @ref speichert Blazor eine Referenz auf eine Kind-Komponente.
|
|
/// Dann kann man Methoden darauf aufrufen: _confirmDialog.ShowAsync(...)
|
|
/// Das ist wie document.getElementById() in JavaScript, nur typsicher.
|
|
/// </summary>
|
|
private ConfirmDialog _confirmDialog = default!;
|
|
|
|
// ── Button-Handler ──
|
|
|
|
/// <summary>
|
|
/// Unterschreiben: Erst bestätigen, dann Event auslösen.
|
|
/// Der ConfirmDialog zeigt "Möchten Sie das Dokument unterschreiben?"
|
|
/// Nur wenn der Benutzer "Ja" klickt, wird OnSign ausgelöst.
|
|
/// </summary>
|
|
private async Task HandleSign()
|
|
{
|
|
var confirmed = await _confirmDialog.ShowAsync(
|
|
"Unterschreiben",
|
|
"Möchten Sie das Dokument wirklich unterschreiben? Diese Aktion kann nicht rückgängig gemacht werden.",
|
|
confirmText: "Unterschreiben",
|
|
confirmColor: "success");
|
|
|
|
if (confirmed)
|
|
await OnSign.InvokeAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ablehnen: Erst bestätigen, dann Event auslösen.
|
|
/// Roter Button im ConfirmDialog, weil Ablehnen destruktiv ist.
|
|
/// </summary>
|
|
private async Task HandleReject()
|
|
{
|
|
var confirmed = await _confirmDialog.ShowAsync(
|
|
"Ablehnen",
|
|
"Möchten Sie das Dokument wirklich ablehnen? Diese Aktion kann nicht rückgängig gemacht werden.",
|
|
confirmText: "Ablehnen",
|
|
confirmColor: "danger");
|
|
|
|
if (confirmed)
|
|
await OnReject.InvokeAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Zurücksetzen: Kein ConfirmDialog nötig, weil es nicht destruktiv ist.
|
|
/// Setzt nur die Signatur-Positionen zurück, der Empfänger kann danach
|
|
/// erneut signieren.
|
|
/// </summary>
|
|
private async Task HandleRefresh()
|
|
{
|
|
await OnRefresh.InvokeAsync();
|
|
}
|
|
} |