Files
deepdrft/DeepDrftPublic.Client/Controls/NowPlayingStats.razor
T

95 lines
3.5 KiB
Plaintext

@using DeepDrftModels.DTOs
@using DeepDrftModels.Enums
@using DeepDrftPublic.Client.Helpers
@using DeepDrftPublic.Client.Services
@implements IDisposable
<div class="hero-stat-row">
@* Studio Cuts — primary figure is the total Cut-medium track count; the secondary breakdown lists
per-ReleaseType Cut release counts, zero-count types already suppressed server-side. *@
<div class="hero-stat">
<div class="hero-stat-num">@_stats.CutTrackCount</div>
<div class="hero-stat-label">Studio Cuts</div>
@if (_stats.CutReleaseTypeCounts.Count > 0)
{
<div class="hero-stat-breakdown">
@foreach (var row in _stats.CutReleaseTypeCounts)
{
<span class="hero-stat-breakdown-item">@row.Count @PluralizeReleaseType(row.ReleaseType, row.Count)</span>
}
</div>
}
</div>
@* Mixes — primary figure is the Mix release count labelled "Sets"; the secondary figure is total
mix runtime as hh:mm. *@
<div class="hero-stat">
<div class="hero-stat-num">@_stats.MixReleaseCount</div>
<div class="hero-stat-label">Sets</div>
<div class="hero-stat-sub">@RuntimeFormat.ToHoursMinutes(_stats.MixRuntimeSeconds) runtime</div>
</div>
@* Plays — static placeholder (real play/share tracking is a future phase). Odometer treatment over
the existing card style; copy is placeholder pending sign-off. *@
<div class="hero-stat">
<div class="hero-stat-num hero-stat-odometer">XXX</div>
<div class="hero-stat-label">Plays (Coming Soon)</div>
</div>
</div>
@code {
[Inject] public required IStatsDataService StatsData { get; set; }
[Inject] public required PersistentComponentState PersistentState { get; set; }
private const string PersistKey = "home-stats";
private HomeStatsDto _stats = new();
private bool _loaded;
private PersistingComponentStateSubscription _persistingSubscription;
protected override async Task OnInitializedAsync()
{
_persistingSubscription = PersistentState.RegisterOnPersisting(Persist);
// Bridge the prerendered fetch across the prerender -> WASM seam so the WASM boot does not
// re-fetch and flicker the figures (the TracksView persistent-state seam, applied to stats).
if (PersistentState.TryTakeFromJson<HomeStatsDto>(PersistKey, out var restored) && restored is not null)
{
_stats = restored;
_loaded = true;
return;
}
var result = await StatsData.GetHomeStats();
if (result is { Success: true, Value: { } stats })
{
_stats = stats;
_loaded = true;
}
}
// Only bridge a successful fetch. If prerender failed, persist nothing so the WASM pass re-fetches
// rather than restoring zeros — mirrors the guard on the medium-browse persist path.
private Task Persist()
{
if (_loaded)
PersistentState.PersistAsJson(PersistKey, _stats);
return Task.CompletedTask;
}
private static string PluralizeReleaseType(ReleaseType type, int count)
{
var label = type switch
{
ReleaseType.Single => "Single",
ReleaseType.EP => "EP",
ReleaseType.Album => "Album",
_ => type.ToString()
};
// EP pluralizes as "EPs"; Single/Album take a plain trailing s.
return count == 1 ? label : label + "s";
}
public void Dispose() => _persistingSubscription.Dispose();
}