diff --git a/NEW/src/JdeScoping.Client/Pages/SearchEdit.razor b/NEW/src/JdeScoping.Client/Pages/SearchEdit.razor
index 97b05a8..d1c39f2 100644
--- a/NEW/src/JdeScoping.Client/Pages/SearchEdit.razor
+++ b/NEW/src/JdeScoping.Client/Pages/SearchEdit.razor
@@ -1,7 +1,9 @@
@page "/search"
@page "/search/{Id:int}"
@attribute [Authorize]
-@inject ISearchService SearchService
+@using JdeScoping.Core.ApiContracts
+@using JdeScoping.Client.Extensions
+@inject ISearchApiClient SearchApi
@inject IHubConnectionService HubConnection
@inject IFileService FileService
@inject AuthStateProvider AuthStateProvider
@@ -25,6 +27,12 @@
{
}
+else if (!string.IsNullOrEmpty(_errorMessage))
+{
+
+ @_errorMessage
+
+}
else
{
@@ -169,6 +177,7 @@ else
private bool _isLoading = true;
private bool _isSubmitting;
+ private string? _errorMessage;
// Filter visibility flags
private bool _showTimespan;
@@ -190,25 +199,37 @@ else
private async Task LoadSearchAsync()
{
_isLoading = true;
+ _errorMessage = null;
try
{
if (CopySearchId.HasValue)
{
- var copied = await SearchService.CopySearchAsync(CopySearchId.Value);
- if (copied != null)
- {
- _search = copied;
- _search.Id = 0;
- _search.Status = "New";
- }
+ var result = await SearchApi.CopySearchAsync(CopySearchId.Value);
+ result.Switch(
+ copied =>
+ {
+ _search = copied.ToClient();
+ _search.Id = 0;
+ _search.Status = "New";
+ },
+ notFound => { _errorMessage = "Search to copy not found."; },
+ validation => { _errorMessage = FormatValidationErrors(validation.FieldErrors); },
+ unauthorized => { _errorMessage = "Session expired."; },
+ forbidden => { _errorMessage = "Access denied."; },
+ error => { _errorMessage = error.Message; }
+ );
}
else if (Id.HasValue && Id.Value > 0)
{
- var loaded = await SearchService.GetSearchAsync(Id.Value);
- if (loaded != null)
- {
- _search = loaded;
- }
+ var result = await SearchApi.GetSearchAsync(Id.Value);
+ result.Switch(
+ loaded => { _search = loaded.ToClient(); },
+ notFound => { _errorMessage = "Search not found."; },
+ validation => { _errorMessage = FormatValidationErrors(validation.FieldErrors); },
+ unauthorized => { _errorMessage = "Session expired."; },
+ forbidden => { _errorMessage = "Access denied."; },
+ error => { _errorMessage = error.Message; }
+ );
}
else
{
@@ -221,8 +242,11 @@ else
};
}
- // Detect search type from criteria
- DetectSearchType();
+ // Detect search type from criteria (only if no error)
+ if (string.IsNullOrEmpty(_errorMessage))
+ {
+ DetectSearchType();
+ }
}
finally
{
@@ -230,6 +254,12 @@ else
}
}
+ private static string FormatValidationErrors(IReadOnlyDictionary fieldErrors)
+ {
+ var messages = fieldErrors.SelectMany(kv => kv.Value);
+ return string.Join(" ", messages);
+ }
+
private void DetectSearchType()
{
var criteria = _search.Criteria;
@@ -364,15 +394,15 @@ else
_isSubmitting = true;
try
{
- var id = await SearchService.SaveSearchAsync(_search);
- if (id.HasValue)
- {
- NavigationManager.NavigateTo($"/search/{id}");
- }
- else
- {
- NotificationService.Notify(NotificationSeverity.Error, "Error", "Failed to submit search.");
- }
+ var result = await SearchApi.CreateSearchAsync(_search.ToCore());
+ result.Switch(
+ id => { NavigationManager.NavigateTo($"/search/{id}"); },
+ notFound => { NotificationService.Notify(NotificationSeverity.Error, "Error", "Search not found."); },
+ validation => { NotificationService.Notify(NotificationSeverity.Error, "Validation Error", FormatValidationErrors(validation.FieldErrors)); },
+ unauthorized => { NotificationService.Notify(NotificationSeverity.Error, "Error", "Session expired."); },
+ forbidden => { NotificationService.Notify(NotificationSeverity.Error, "Error", "Access denied."); },
+ error => { NotificationService.Notify(NotificationSeverity.Error, "Error", error.Message); }
+ );
}
finally
{
@@ -413,17 +443,26 @@ else
private async Task DownloadResultsAsync()
{
- var results = await SearchService.DownloadResultsAsync(_search.Id);
- if (results != null && results.Length > 0)
- {
- // Trigger download via JS interop
- await JSRuntime.InvokeVoidAsync("downloadFile", $"search_results_{_search.Id}.xlsx", results);
- NotificationService.Notify(NotificationSeverity.Success, "Download", "Results downloaded successfully.");
- }
- else
- {
- NotificationService.Notify(NotificationSeverity.Warning, "Download", "No results available to download.");
- }
+ var result = await SearchApi.GetResultsAsync(_search.Id);
+ result.Switch(
+ bytes =>
+ {
+ if (bytes.Length > 0)
+ {
+ _ = JSRuntime.InvokeVoidAsync("downloadFile", $"search_results_{_search.Id}.xlsx", bytes);
+ NotificationService.Notify(NotificationSeverity.Success, "Download", "Results downloaded successfully.");
+ }
+ else
+ {
+ NotificationService.Notify(NotificationSeverity.Warning, "Download", "No results available to download.");
+ }
+ },
+ notFound => { NotificationService.Notify(NotificationSeverity.Warning, "Download", "Results not found."); },
+ validation => { NotificationService.Notify(NotificationSeverity.Error, "Error", FormatValidationErrors(validation.FieldErrors)); },
+ unauthorized => { NotificationService.Notify(NotificationSeverity.Error, "Error", "Session expired."); },
+ forbidden => { NotificationService.Notify(NotificationSeverity.Error, "Error", "Access denied."); },
+ error => { NotificationService.Notify(NotificationSeverity.Error, "Error", error.Message); }
+ );
}
public void Dispose()