@page "/cms/tracks" @rendermode InteractiveServer @using System.Net @using System.Net.Http.Headers @using AuthBlocksWeb.HierarchicalAuthorize @using Models.Common @attribute [HierarchicalRoleAuthorize("Admin")] @inject ITrackService TrackService @inject IHttpClientFactory HttpClientFactory @inject AuthBlocksWeb.Services.ITokenService TokenService @inject IDialogService DialogService @inject ISnackbar Snackbar @inject ILogger Logger Tracks — DeepDrft CMS Tracks Add Track No tracks found. Loading tracks… Track Name Artist Album Genre Release Date Entry Key Actions @context.TrackName @context.Artist @(context.Album ?? "—") @(context.Genre ?? "—") @(context.ReleaseDate?.ToString("yyyy-MM-dd") ?? "—") @context.EntryKey @code { private MudTable? _table; private async Task> LoadServerData(TableState state, CancellationToken cancellationToken) { var pageNumber = state.Page + 1; // MudTable is 0-based, service is 1-based. var sortColumn = string.IsNullOrEmpty(state.SortLabel) ? "TrackName" : state.SortLabel; var sortDescending = state.SortDirection == SortDirection.Descending; var result = await TrackService.GetPaged(pageNumber, state.PageSize, sortColumn, sortDescending, cancellationToken); if (!result.Success || result.Value is null) { var errorText = result.Messages.FirstOrDefault()?.Message ?? "Unknown error"; Snackbar.Add($"Failed to load tracks: {errorText}", Severity.Error); return new TableData { Items = Array.Empty(), TotalItems = 0 }; } var page = result.Value; return new TableData { Items = page.Items, TotalItems = page.TotalCount }; } private async Task ConfirmAndDelete(TrackEntity track) { var confirmed = await DialogService.ShowMessageBox( title: "Delete track", markupMessage: new MarkupString($"Delete {WebUtility.HtmlEncode(track.TrackName)} by {WebUtility.HtmlEncode(track.Artist)}? This removes both the metadata row and the underlying audio entry."), yesText: "Delete", cancelText: "Cancel"); if (confirmed != true) return; try { var client = HttpClientFactory.CreateClient("DeepDrft.API"); var token = await TokenService.GetAccessTokenAsync(); if (!string.IsNullOrEmpty(token)) client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); var response = await client.DeleteAsync($"api/cms/track/{track.Id}"); if (response.IsSuccessStatusCode) { Snackbar.Add($"Deleted '{track.TrackName}'.", Severity.Success); if (_table is not null) await _table.ReloadServerData(); } else { Snackbar.Add($"Delete failed ({(int)response.StatusCode} {response.ReasonPhrase}).", Severity.Error); } } catch (Exception ex) { Logger.LogError(ex, "Delete failed for track {TrackId}", track.Id); Snackbar.Add("Delete failed — please try again.", Severity.Error); } } }