- 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
87 lines
3.2 KiB
Plaintext
87 lines
3.2 KiB
Plaintext
@* MainLayout: Das Grundgerüst jeder Seite.
|
|
Entspricht _Layout.cshtml im Web-Projekt.
|
|
|
|
Aufbau:
|
|
- Header: signFLOW-Logo/Titel (oben, sticky)
|
|
- Main: Der Seiteninhalt (@Body) mit ErrorBoundary
|
|
- Footer: Copyright + Privacy-Link (unten)
|
|
|
|
Sticky Footer Pattern: Der Footer klebt immer am unteren Rand,
|
|
auch wenn der Inhalt wenig Platz braucht. Das funktioniert über
|
|
Flexbox in app.css (.app-container mit min-height: 100vh). *@
|
|
|
|
@inherits LayoutComponentBase
|
|
|
|
<div class="app-container">
|
|
<Toast />
|
|
|
|
@* ── Header ── *@
|
|
<header class="app-header">
|
|
<div class="d-flex align-items-center gap-2">
|
|
@* Im Web-Projekt steht hier ein <img> mit dem signFLOW-Logo.
|
|
Wir nutzen erstmal Text. Das Logo kommt in Phase 6
|
|
wenn wir die Bilder aus dem Web-Projekt portieren. *@
|
|
<span class="app-title">signFLOW</span>
|
|
</div>
|
|
</header>
|
|
|
|
@* ── Main: Seiteninhalt mit Error-Schutz ──
|
|
ErrorBoundary fängt unbehandelte Exceptions in Komponenten ab.
|
|
Ohne ErrorBoundary würde die gesamte App abstürzen.
|
|
Mit ErrorBoundary zeigen wir stattdessen eine Fehlermeldung
|
|
und einen "Erneut versuchen"-Button. *@
|
|
<main class="app-main">
|
|
<ErrorBoundary @ref="_errorBoundary">
|
|
<ChildContent>
|
|
@Body
|
|
</ChildContent>
|
|
<ErrorContent Context="ex">
|
|
<div class="error-container text-center py-5">
|
|
<div class="status-icon locked mb-3">
|
|
<i class="bi bi-exclamation-triangle"></i>
|
|
</div>
|
|
<h2>Ein unerwarteter Fehler ist aufgetreten</h2>
|
|
<p class="text-muted">Bitte versuchen Sie es erneut.</p>
|
|
<button class="btn btn-primary" @onclick="Recover">
|
|
<i class="bi bi-arrow-counterclockwise me-2"></i>
|
|
Erneut versuchen
|
|
</button>
|
|
</div>
|
|
</ErrorContent>
|
|
</ErrorBoundary>
|
|
</main>
|
|
|
|
@* ── Footer ──
|
|
Im Web-Projekt gibt es hier drei Elemente:
|
|
1. Copyright + Link zur Firmenwebsite
|
|
2. Sprachauswahl (Dropdown mit Flaggen) → kommt in Phase 6
|
|
3. Privacy-Link (Datenschutzerklärung)
|
|
|
|
Die Datenschutz-HTML-Dateien existieren im Web-Projekt unter
|
|
wwwroot/privacy-policy.de-DE.html. Wir verlinken vorerst
|
|
auf eine statische URL. Die Datei selbst portieren wir in Phase 6. *@
|
|
<footer class="app-footer">
|
|
<small>
|
|
© signFLOW @DateTime.Now.Year
|
|
<a href="https://digitaldata.works" target="_blank" class="text-muted text-decoration-none">
|
|
Digital Data GmbH
|
|
</a>
|
|
</small>
|
|
|
|
@* Platzhalter für Sprachauswahl — kommt in Phase 6 *@
|
|
|
|
<a href="/privacy-policy.de-DE.html" target="_blank" class="text-muted text-decoration-none">
|
|
<small>Datenschutz</small>
|
|
</a>
|
|
</footer>
|
|
</div>
|
|
|
|
@code {
|
|
private ErrorBoundary? _errorBoundary;
|
|
|
|
/// <summary>
|
|
/// Setzt die ErrorBoundary zurück.
|
|
/// Blazor rendert dann @Body erneut statt der Fehlermeldung.
|
|
/// </summary>
|
|
private void Recover() => _errorBoundary?.Recover();
|
|
} |