- Introduce IReceiverAuthService and ReceiverAuthService for all envelope receiver authentication and status API calls - Add ReceiverAuthModel as a client-side DTO for API responses - Refactor EnvelopeState to store all relevant fields and update via ApplyApiResponse - Overhaul EnvelopePage.razor to use new service and state, with improved status handling and UI - Enhance ApiResponse and ApiServiceBase to support structured error deserialization - Register IReceiverAuthService in DI container
159 lines
5.0 KiB
Plaintext
159 lines
5.0 KiB
Plaintext
@page "/envelope/{EnvelopeKey}"
|
|
@rendermode InteractiveAuto
|
|
@inject IReceiverAuthService ReceiverAuthService
|
|
@inject EnvelopeState State
|
|
@implements IDisposable
|
|
|
|
<PageTitle>Dokument</PageTitle>
|
|
|
|
@switch (State.Status)
|
|
{
|
|
case EnvelopePageStatus.Loading:
|
|
<LoadingIndicator Message="Dokument wird geladen..." />
|
|
break;
|
|
|
|
case EnvelopePageStatus.NotFound:
|
|
<StatusPage Type="not_found" />
|
|
break;
|
|
|
|
case EnvelopePageStatus.AlreadySigned:
|
|
<StatusPage Type="signed"
|
|
Title="@State.Title"
|
|
SenderEmail="@State.SenderEmail" />
|
|
break;
|
|
|
|
case EnvelopePageStatus.Rejected:
|
|
<StatusPage Type="rejected"
|
|
Title="@State.Title"
|
|
SenderEmail="@State.SenderEmail" />
|
|
break;
|
|
|
|
case EnvelopePageStatus.Expired:
|
|
<StatusPage Type="expired" />
|
|
break;
|
|
|
|
case EnvelopePageStatus.RequiresAccessCode:
|
|
<AccessCodeForm EnvelopeKey="@EnvelopeKey"
|
|
ErrorMessage="@State.ErrorMessage"
|
|
SenderEmail="@State.SenderEmail"
|
|
Title="@State.Title"
|
|
TfaEnabled="@State.TfaEnabled"
|
|
HasPhoneNumber="@State.HasPhoneNumber"
|
|
OnSubmit="HandleAccessCodeSubmit" />
|
|
break;
|
|
|
|
case EnvelopePageStatus.RequiresTwoFactor:
|
|
<TfaForm EnvelopeKey="@EnvelopeKey"
|
|
TfaType="@(State.TfaType ?? "authenticator")"
|
|
TfaExpiration="@State.TfaExpiration"
|
|
HasPhoneNumber="@State.HasPhoneNumber"
|
|
ErrorMessage="@State.ErrorMessage"
|
|
OnSubmit="HandleTfaSubmit" />
|
|
break;
|
|
|
|
case EnvelopePageStatus.ShowDocument:
|
|
@* Phase 4 (PSPDFKit) kommt später — vorerst Platzhalter *@
|
|
<div class="text-center mt-5">
|
|
<div class="status-icon signed">
|
|
<i class="bi bi-file-earmark-check"></i>
|
|
</div>
|
|
<h2>Dokument bereit</h2>
|
|
<p class="text-muted">
|
|
«@State.Title» — PDF-Viewer wird in Phase 4 integriert.
|
|
</p>
|
|
@if (State.ReadOnly)
|
|
{
|
|
<span class="badge bg-secondary">Nur Lesen</span>
|
|
}
|
|
</div>
|
|
break;
|
|
|
|
case EnvelopePageStatus.Error:
|
|
<ErrorDisplay Title="Fehler" Message="@State.ErrorMessage" />
|
|
break;
|
|
}
|
|
|
|
@code {
|
|
[Parameter] public string EnvelopeKey { get; set; } = default!;
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
State.OnChange += StateHasChanged;
|
|
await LoadStatusAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Erster API-Call: Status prüfen.
|
|
/// Entspricht dem GET /Envelope/{key} im Web-Projekt.
|
|
/// Die API entscheidet, was passiert (AccessCode nötig? Bereits signiert? etc.)
|
|
/// </summary>
|
|
private async Task LoadStatusAsync()
|
|
{
|
|
State.SetLoading();
|
|
|
|
var result = await ReceiverAuthService.GetStatusAsync(EnvelopeKey);
|
|
|
|
if (result.IsSuccess && result.Data is not null)
|
|
{
|
|
State.ApplyApiResponse(result.Data);
|
|
}
|
|
else if (result.StatusCode == 404)
|
|
{
|
|
State.SetNotFound();
|
|
}
|
|
else
|
|
{
|
|
State.SetError(result.ErrorMessage ?? "Verbindung zum Server fehlgeschlagen.");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Zweiter API-Call: AccessCode senden.
|
|
/// Wird von AccessCodeForm aufgerufen (OnSubmit-Callback).
|
|
/// Die API prüft den Code und antwortet mit dem nächsten Status.
|
|
/// </summary>
|
|
private async Task HandleAccessCodeSubmit((string Code, bool PreferSms) submission)
|
|
{
|
|
var result = await ReceiverAuthService.SubmitAccessCodeAsync(
|
|
EnvelopeKey, submission.Code, submission.PreferSms);
|
|
|
|
if (result.IsSuccess && result.Data is not null)
|
|
{
|
|
State.ApplyApiResponse(result.Data);
|
|
}
|
|
else if (result.Data is not null)
|
|
{
|
|
// 401 mit Body → falscher Code, API gibt trotzdem ReceiverAuthModel zurück
|
|
State.ApplyApiResponse(result.Data);
|
|
}
|
|
else
|
|
{
|
|
State.SetError(result.ErrorMessage ?? "Fehler bei der Code-Prüfung.");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dritter API-Call: TFA-Code senden.
|
|
/// Wird von TfaForm aufgerufen (OnSubmit-Callback).
|
|
/// </summary>
|
|
private async Task HandleTfaSubmit((string Code, string Type) submission)
|
|
{
|
|
var result = await ReceiverAuthService.SubmitTfaCodeAsync(
|
|
EnvelopeKey, submission.Code, submission.Type);
|
|
|
|
if (result.IsSuccess && result.Data is not null)
|
|
{
|
|
State.ApplyApiResponse(result.Data);
|
|
}
|
|
else if (result.Data is not null)
|
|
{
|
|
State.ApplyApiResponse(result.Data);
|
|
}
|
|
else
|
|
{
|
|
State.SetError(result.ErrorMessage ?? "Fehler bei der TFA-Prüfung.");
|
|
}
|
|
}
|
|
|
|
public void Dispose() => State.OnChange -= StateHasChanged;
|
|
} |