@page "/cms/tracks/{Id:int}"
@rendermode InteractiveServer
@using AuthBlocksWeb.HierarchicalAuthorize
@using AuthBlocksWeb.Services
@using DeepDrftWeb.Services
@using System.Net.Http.Headers
@using System.Net.Http.Json
@attribute [HierarchicalRoleAuthorize("Admin")]
@inject ITrackService TrackService
@inject IHttpClientFactory HttpClientFactory
@inject ITokenService TokenService
@inject ISnackbar Snackbar
@inject IDialogService DialogService
@inject NavigationManager Nav
Edit Track — DeepDrft CMS
Back to tracks
@if (_loading)
{
}
else if (_track is null)
{
Track not found.
}
else
{
Edit Track
@_track.EntryKey
Vault reference — not editable.
Delete
Save Changes
}
@code {
[Parameter] public int Id { get; set; }
private TrackEntity? _track;
private TrackEditForm _form = new();
private bool _loading = true;
private bool _busy;
private bool CanSave =>
!string.IsNullOrWhiteSpace(_form.TrackName)
&& !string.IsNullOrWhiteSpace(_form.Artist);
protected override async Task OnInitializedAsync()
{
await LoadAsync();
}
private async Task LoadAsync()
{
_loading = true;
var result = await TrackService.GetById(Id);
_track = result.Success ? result.Value : null;
if (_track is not null)
{
_form = TrackEditForm.From(_track);
}
_loading = false;
}
private async Task SaveAsync()
{
if (_track is null || !CanSave) return;
_busy = true;
try
{
var http = HttpClientFactory.CreateClient("DeepDrft.API");
await AttachBearerAsync(http);
var payload = new
{
TrackName = _form.TrackName,
Artist = _form.Artist,
Album = string.IsNullOrWhiteSpace(_form.Album) ? null : _form.Album,
Genre = string.IsNullOrWhiteSpace(_form.Genre) ? null : _form.Genre,
ReleaseDate = _form.ReleaseDate is { } d ? DateOnly.FromDateTime(d) : (DateOnly?)null
};
var response = await http.PutAsJsonAsync($"api/cms/track/{Id}", payload);
if (response.IsSuccessStatusCode)
{
Snackbar.Add("Track updated.", Severity.Success);
await LoadAsync();
}
else
{
Snackbar.Add($"Save failed: {(int)response.StatusCode} {response.ReasonPhrase}", Severity.Error);
}
}
catch (Exception ex)
{
Snackbar.Add($"Save failed: {ex.Message}", Severity.Error);
}
finally
{
_busy = false;
}
}
private async Task ConfirmDelete()
{
if (_track is null) return;
var confirmed = await DialogService.ShowMessageBox(
"Delete track",
$"Permanently delete \"{_track.TrackName}\" by {_track.Artist}? This cannot be undone.",
yesText: "Delete",
cancelText: "Cancel");
if (confirmed != true) return;
_busy = true;
try
{
var http = HttpClientFactory.CreateClient("DeepDrft.API");
await AttachBearerAsync(http);
var response = await http.DeleteAsync($"api/cms/track/{Id}");
if (response.IsSuccessStatusCode)
{
Snackbar.Add("Track deleted.", Severity.Success);
Nav.NavigateTo("/cms/tracks");
}
else
{
Snackbar.Add($"Delete failed: {(int)response.StatusCode} {response.ReasonPhrase}", Severity.Error);
_busy = false;
}
}
catch (Exception ex)
{
Snackbar.Add($"Delete failed: {ex.Message}", Severity.Error);
_busy = false;
}
}
private async Task AttachBearerAsync(HttpClient http)
{
var token = await TokenService.GetAccessTokenAsync();
if (!string.IsNullOrEmpty(token))
{
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
}
private sealed class TrackEditForm
{
public string TrackName { get; set; } = string.Empty;
public string Artist { get; set; } = string.Empty;
public string? Album { get; set; }
public string? Genre { get; set; }
public DateTime? ReleaseDate { get; set; }
public static TrackEditForm From(TrackEntity track) => new()
{
TrackName = track.TrackName,
Artist = track.Artist,
Album = track.Album,
Genre = track.Genre,
ReleaseDate = track.ReleaseDate is { } d
? d.ToDateTime(TimeOnly.MinValue)
: null
};
}
}