Add reusable UI components and toast notification system
- 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
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
@* Toast: Zeigt kurze Benachrichtigungen an. Ersetzt AlertifyJS aus dem Web-Projekt.
|
||||
|
||||
Wird einmal im MainLayout platziert. Hört auf den ToastService.
|
||||
Wenn eine Komponente irgendwo _toast.ShowSuccess("Text") aufruft,
|
||||
erscheint hier ein Toast und verschwindet nach 4 Sekunden automatisch.
|
||||
|
||||
Bootstrap Toast-Klassen werden genutzt:
|
||||
- toast-container: Positionierung (oben rechts)
|
||||
- toast: Einzelner Toast
|
||||
- bg-success/bg-danger/etc: Farbe basierend auf Typ *@
|
||||
|
||||
@inject ToastService ToastService
|
||||
@implements IDisposable
|
||||
|
||||
@if (ToastService.Messages.Count > 0)
|
||||
{
|
||||
@* toast-container: Bootstrap-Klasse die Toasts oben rechts positioniert.
|
||||
position-fixed: Bleibt an der Stelle auch beim Scrollen.
|
||||
z-index 1080: Über dem Modal-Backdrop (1070) damit Toasts
|
||||
auch während eines ConfirmDialogs sichtbar sind. *@
|
||||
<div class="toast-container position-fixed top-0 end-0 p-3" style="z-index: 1080;">
|
||||
@foreach (var message in ToastService.Messages)
|
||||
{
|
||||
<div class="toast show align-items-center text-white bg-@message.Type border-0"
|
||||
role="alert">
|
||||
<div class="d-flex">
|
||||
<div class="toast-body">
|
||||
<i class="bi @message.IconClass me-2"></i>
|
||||
@message.Text
|
||||
</div>
|
||||
<button type="button"
|
||||
class="btn-close btn-close-white me-2 m-auto"
|
||||
@onclick="() => ToastService.Dismiss(message)">
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
// Subscriber: Wenn der ToastService eine Änderung meldet,
|
||||
// zeichnet diese Komponente sich neu (StateHasChanged).
|
||||
// So erscheinen/verschwinden Toasts automatisch.
|
||||
ToastService.OnChange += HandleChange;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// InvokeAsync ist nötig weil OnChange von einem
|
||||
/// async void (dem Timer im ToastService) ausgelöst wird.
|
||||
/// Das kann auf einem anderen Thread passieren.
|
||||
/// InvokeAsync wechselt zurück auf den Blazor UI-Thread.
|
||||
/// </summary>
|
||||
private async void HandleChange()
|
||||
{
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event-Handler abmelden wenn die Komponente entfernt wird.
|
||||
/// Ohne das würde der ToastService eine Referenz auf eine
|
||||
/// nicht mehr existierende Komponente halten → Memory Leak.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
ToastService.OnChange -= HandleChange;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user