Add recent receiver suggestions to wizard
Introduced a feature to display and apply recent receiver suggestions in the `CreateEnvelopeWizardPopup` component. Added a new section in step 2 to show recently used receivers, with loading and state management logic. Updated the `ReceiverService` to fetch suggestions from the backend API. Enhanced the UI with new styles for the suggestions section and improved localization support. Refactored state management to handle loading, resetting, and applying suggestions. Minor cleanup and adjustments to ensure proper state transitions.
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
@using EnvelopeGenerator.Application.Common.Dto
|
||||
@using EnvelopeGenerator.Application.Common.Dto.Receiver
|
||||
@using EnvelopeGenerator.Application.Resources
|
||||
@using EnvelopeGenerator.Domain.Resources
|
||||
@using EnvelopeGenerator.Server.Client.Services
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.Extensions.Localization
|
||||
@inject IStringLocalizer<Model> ModelLocalizer
|
||||
@inject IStringLocalizer<Resource> UiLocalizer
|
||||
@inject ReceiverService ReceiverService
|
||||
|
||||
<DxPopup Visible="@_isVisible"
|
||||
VisibleChanged="OnPopupVisibleChangedAsync"
|
||||
@@ -102,6 +105,30 @@
|
||||
}
|
||||
else if (_currentStep == 2)
|
||||
{
|
||||
<div class="sender-create-wizard__suggestions">
|
||||
<div class="sender-create-wizard__suggestions-title">@L("SenderWizard_RecentReceivers", "Zuletzt verwendete Empfänger")</div>
|
||||
|
||||
@if (_isLoadingRecentSuggestions)
|
||||
{
|
||||
<div class="sender-create-wizard__empty-list">@L("Loading", "Lädt...")</div>
|
||||
}
|
||||
else if (_recentReceiverSuggestions.Count > 0)
|
||||
{
|
||||
<div class="sender-create-wizard__suggestion-list">
|
||||
@foreach (var suggestion in _recentReceiverSuggestions)
|
||||
{
|
||||
<button type="button"
|
||||
class="sender-create-wizard__suggestion-item"
|
||||
@onclick="() => ApplyRecentSuggestion(suggestion)"
|
||||
disabled="@IsActionLocked">
|
||||
<span class="sender-create-wizard__suggestion-name">@suggestion.FullName</span>
|
||||
<span class="sender-create-wizard__suggestion-email">@suggestion.EmailAddress</span>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="sender-create-wizard__form-grid">
|
||||
<div class="sender-create-wizard__field">
|
||||
<label class="sender-create-wizard__label">
|
||||
@@ -261,6 +288,9 @@
|
||||
private string _receiverName = string.Empty;
|
||||
private string _receiverEmail = string.Empty;
|
||||
private readonly List<CreateEnvelopeWizardReceiver> _receivers = [];
|
||||
private readonly List<RecentReceiverSuggestionDto> _recentReceiverSuggestions = [];
|
||||
private bool _isLoadingRecentSuggestions;
|
||||
private bool _recentSuggestionsLoaded;
|
||||
|
||||
private byte[]? _documentBytes;
|
||||
private string? _documentFileName;
|
||||
@@ -458,7 +488,12 @@
|
||||
_validationMessage = null;
|
||||
|
||||
if (!IsLastStep)
|
||||
{
|
||||
_currentStep++;
|
||||
|
||||
if (_currentStep == 2)
|
||||
await EnsureRecentSuggestionsLoadedAsync();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -569,6 +604,41 @@
|
||||
await VisibleChanged.InvokeAsync(value);
|
||||
}
|
||||
|
||||
private async Task EnsureRecentSuggestionsLoadedAsync()
|
||||
{
|
||||
if (_recentSuggestionsLoaded || _isLoadingRecentSuggestions)
|
||||
return;
|
||||
|
||||
_isLoadingRecentSuggestions = true;
|
||||
try
|
||||
{
|
||||
var suggestions = await ReceiverService.GetRecentReceiverSuggestionsAsync();
|
||||
_recentReceiverSuggestions.Clear();
|
||||
_recentReceiverSuggestions.AddRange(suggestions);
|
||||
_recentSuggestionsLoaded = true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
_recentReceiverSuggestions.Clear();
|
||||
_recentSuggestionsLoaded = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isLoadingRecentSuggestions = false;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyRecentSuggestion(RecentReceiverSuggestionDto suggestion)
|
||||
{
|
||||
if (IsActionLocked)
|
||||
return;
|
||||
|
||||
_receiverName = suggestion.FullName;
|
||||
_receiverEmail = suggestion.EmailAddress;
|
||||
_validationMessage = null;
|
||||
}
|
||||
|
||||
private bool ValidateCurrentStep()
|
||||
{
|
||||
if (_currentStep == 0)
|
||||
@@ -640,6 +710,9 @@
|
||||
_receiverName = string.Empty;
|
||||
_receiverEmail = string.Empty;
|
||||
_receivers.Clear();
|
||||
_recentReceiverSuggestions.Clear();
|
||||
_isLoadingRecentSuggestions = false;
|
||||
_recentSuggestionsLoaded = false;
|
||||
|
||||
_documentBytes = null;
|
||||
_documentFileName = null;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json;
|
||||
using EnvelopeGenerator.Application.Common.Dto.Receiver;
|
||||
|
||||
namespace EnvelopeGenerator.Server.Client.Services;
|
||||
|
||||
@@ -26,4 +27,21 @@ public class ReceiverService(IHttpClientFactory httpClientFactory)
|
||||
var emails = await response.Content.ReadFromJsonAsync<List<string>>(JsonOptions, cancel);
|
||||
return emails ?? [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches recent receiver suggestions for the authenticated sender.
|
||||
/// Calls GET /api/EnvelopeReceiver/recent-suggestions?take={take}.
|
||||
/// </summary>
|
||||
public async Task<IReadOnlyList<RecentReceiverSuggestionDto>> GetRecentReceiverSuggestionsAsync(int take = 5, CancellationToken cancel = default)
|
||||
{
|
||||
using var http = httpClientFactory.CreateClient("EnvelopeGenerator.Server");
|
||||
var url = $"/api/EnvelopeReceiver/recent-suggestions?take={take}";
|
||||
var response = await http.GetAsync(url, cancel);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
return [];
|
||||
|
||||
var suggestions = await response.Content.ReadFromJsonAsync<List<RecentReceiverSuggestionDto>>(JsonOptions, cancel);
|
||||
return suggestions ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user