@page "/" @page "/searches" @attribute [Authorize] @using JdeScoping.Core.ApiContracts @using JdeScoping.Client.Extensions @inject ISearchApiClient SearchApi @inject IHubConnectionService HubConnection @inject NavigationManager NavigationManager @implements IDisposable Searches - JDE Scoping Tool Searches @if (_isLoading) { } else if (!string.IsNullOrEmpty(_errorMessage)) { @_errorMessage } else { } @code { private List _searches = []; private RadzenDataGrid? _grid; private bool _isLoading = true; private string? _errorMessage; protected override async Task OnInitializedAsync() { await LoadSearchesAsync(); await SetupSignalRAsync(); } private async Task LoadSearchesAsync() { _isLoading = true; _errorMessage = null; try { var result = await SearchApi.GetUserSearchesAsync(); result.Switch( searches => { _searches = searches.ToClientList(); }, notFound => { _errorMessage = "No searches found."; _searches = []; }, validation => { _errorMessage = string.Join("; ", validation.FieldErrors.SelectMany(e => e.Value)); }, unauthorized => { _errorMessage = "Session expired. Please login again."; }, forbidden => { _errorMessage = "Access denied."; }, error => { _errorMessage = error.Message; } ); } finally { _isLoading = false; } } private async Task SetupSignalRAsync() { HubConnection.OnSearchUpdate += HandleSearchUpdate; await HubConnection.StartAsync(); } private void HandleSearchUpdate(SearchUpdate update) { InvokeAsync(() => { var existing = _searches.FirstOrDefault(s => s.Id == update.Id); if (existing != null) { existing.Status = update.Status; existing.SubmitDt = update.SubmitDt; existing.StartDt = update.StartDt; existing.EndDt = update.EndDt; } else { _searches.Insert(0, new ClientSearchViewModel { Id = update.Id, Name = update.Name, UserName = update.UserName, Status = update.Status, SubmitDt = update.SubmitDt, StartDt = update.StartDt, EndDt = update.EndDt }); } StateHasChanged(); }); } private void CreateNewSearch() { NavigationManager.NavigateTo("/search"); } private void ViewQueue() { NavigationManager.NavigateTo("/search/queue"); } private void ViewSearch(int id) { NavigationManager.NavigateTo($"/search/{id}"); } private void OnRowDoubleClick(DataGridRowMouseEventArgs args) { ViewSearch(args.Data.Id); } private static BadgeStyle GetBadgeStyle(string status) => status switch { "Error" => BadgeStyle.Danger, "Ended" => BadgeStyle.Success, "Running" => BadgeStyle.Info, "Queued" => BadgeStyle.Warning, _ => BadgeStyle.Light }; public void Dispose() { HubConnection.OnSearchUpdate -= HandleSearchUpdate; } }