- 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
133 lines
4.8 KiB
Plaintext
133 lines
4.8 KiB
Plaintext
@* ConfirmDialog: Ersetzt SweetAlert2 aus dem Web-Projekt.
|
|
|
|
Zeigt einen modalen Bestätigungsdialog mit Titel, Text und Ja/Nein-Buttons.
|
|
Wird NICHT über Parameter gesteuert, sondern über eine Methode:
|
|
|
|
var confirmed = await _dialog.ShowAsync("Titel", "Text");
|
|
|
|
WARUM eine Methode statt Parameter?
|
|
- Ein Dialog ist ein "einmaliges Ereignis", kein dauerhafter Zustand
|
|
- Die aufrufende Komponente will auf das Ergebnis WARTEN (await)
|
|
- Mit Parametern müsste man den State manuell hin- und herschalten
|
|
|
|
WARUM kein SweetAlert2?
|
|
- SweetAlert2 ist eine JavaScript-Bibliothek
|
|
- In Blazor können wir das nativ in C# lösen, ohne JS-Interop
|
|
- Weniger Abhängigkeiten = weniger Wartung = weniger Fehlerquellen *@
|
|
|
|
@if (_isVisible)
|
|
{
|
|
@* Hintergrund-Overlay: Dunkler Hintergrund hinter dem Dialog.
|
|
Im Web-Projekt macht SweetAlert2 das automatisch.
|
|
Hier bauen wir es selbst mit CSS. *@
|
|
<div class="modal-backdrop fade show"></div>
|
|
|
|
@* Modal-Dialog: Bootstrap 5 Modal-Markup.
|
|
Normalerweise braucht Bootstrap-Modal JavaScript (bootstrap.js)
|
|
um zu öffnen/schließen. Wir steuern die Sichtbarkeit stattdessen
|
|
über die _isVisible-Variable — Blazor macht das DOM-Update. *@
|
|
<div class="modal fade show d-block" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog modal-dialog-centered" role="document">
|
|
<div class="modal-content">
|
|
|
|
@* Header: Titel + Schließen-Button *@
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">@_title</h5>
|
|
<button type="button" class="btn-close" @onclick="Cancel"></button>
|
|
</div>
|
|
|
|
@* Body: Beschreibungstext *@
|
|
<div class="modal-body">
|
|
<p>@_message</p>
|
|
</div>
|
|
|
|
@* Footer: Abbrechen + Bestätigen *@
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" @onclick="Cancel">
|
|
@_cancelText
|
|
</button>
|
|
<button type="button" class="btn btn-@_confirmColor" @onclick="Confirm">
|
|
@_confirmText
|
|
</button>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
@code {
|
|
// ── Interner State (NICHT Parameter — wird über ShowAsync gesetzt) ──
|
|
|
|
private bool _isVisible;
|
|
private string _title = string.Empty;
|
|
private string _message = string.Empty;
|
|
private string _confirmText = "Ja";
|
|
private string _cancelText = "Abbrechen";
|
|
private string _confirmColor = "primary";
|
|
|
|
/// <summary>
|
|
/// TaskCompletionSource: Das Herzstück dieser Komponente.
|
|
///
|
|
/// WAS IST DAS?
|
|
/// Ein TaskCompletionSource erstellt einen Task, der erst dann
|
|
/// "fertig" wird, wenn jemand SetResult() aufruft.
|
|
///
|
|
/// WIE FUNKTIONIERT ES?
|
|
/// 1. ShowAsync() erstellt ein neues TaskCompletionSource
|
|
/// 2. ShowAsync() gibt dessen Task zurück → der Aufrufer wartet (await)
|
|
/// 3. Der Benutzer klickt "Ja" → Confirm() ruft SetResult(true) auf
|
|
/// 4. Der await in der aufrufenden Komponente kommt zurück mit true
|
|
///
|
|
/// Das ist wie ein "Promise" in JavaScript, nur in C#.
|
|
/// </summary>
|
|
private TaskCompletionSource<bool>? _tcs;
|
|
|
|
/// <summary>
|
|
/// Zeigt den Dialog und wartet auf die Benutzer-Entscheidung.
|
|
///
|
|
/// Beispiel-Aufruf:
|
|
/// var confirmed = await _dialog.ShowAsync(
|
|
/// "Unterschreiben",
|
|
/// "Möchten Sie das Dokument wirklich unterschreiben?");
|
|
/// </summary>
|
|
/// <param name="title">Dialog-Überschrift</param>
|
|
/// <param name="message">Beschreibungstext</param>
|
|
/// <param name="confirmText">Text auf dem Bestätigen-Button (Standard: "Ja")</param>
|
|
/// <param name="cancelText">Text auf dem Abbrechen-Button (Standard: "Abbrechen")</param>
|
|
/// <param name="confirmColor">Bootstrap-Farbe des Bestätigen-Buttons (Standard: "primary")</param>
|
|
/// <returns>true wenn bestätigt, false wenn abgebrochen</returns>
|
|
public Task<bool> ShowAsync(
|
|
string title,
|
|
string message,
|
|
string confirmText = "Ja",
|
|
string cancelText = "Abbrechen",
|
|
string confirmColor = "primary")
|
|
{
|
|
_title = title;
|
|
_message = message;
|
|
_confirmText = confirmText;
|
|
_cancelText = cancelText;
|
|
_confirmColor = confirmColor;
|
|
|
|
_tcs = new TaskCompletionSource<bool>();
|
|
_isVisible = true;
|
|
StateHasChanged();
|
|
|
|
return _tcs.Task;
|
|
}
|
|
|
|
private void Confirm()
|
|
{
|
|
_isVisible = false;
|
|
_tcs?.TrySetResult(true);
|
|
StateHasChanged();
|
|
}
|
|
|
|
private void Cancel()
|
|
{
|
|
_isVisible = false;
|
|
_tcs?.TrySetResult(false);
|
|
StateHasChanged();
|
|
}
|
|
} |