@page "/" @inject IStringLocalizer L @inject IDashboardSummaryService Dashboard @inject ILogger Logger @L["App.Title"] · @L["Nav.Dashboard"]
@L["Home.Kicker"]

@L["Home.Title"]

@L["Home.Lede"]


@L["Home.Section.Latest"]

@L["Anomaly.Kind.SuspensionFlip"]

@if (!_summary.HasAnyData) { @* First-run: nothing captured yet. Make the next step unmissable. *@
@L["Home.Empty.Heading"]

@L["Home.Empty"]

} else if (_summary.LatestSignals.Count == 0) { @* Capturing, but the detector hasn't flagged anything yet. *@

@L["Home.NoSignals"]

@L["Home.ViewAll"] →
} else { }
@code { private DashboardSummary _summary = DashboardSummary.Empty; private string? AnomaliesDelta => _summary.AnomaliesToday > 0 ? string.Format(CultureInfo.CurrentCulture, L["Home.Stat.NewToday"], _summary.AnomaliesToday) : null; protected override async Task OnInitializedAsync() { try { _summary = await Dashboard.GetAsync(CancellationToken.None); } catch (Exception ex) { // Dashboard is read-only chrome; on failure keep the empty summary and log. Logger.LogError(ex, "Home: failed to load dashboard summary."); } } private string FormatSignalTime(DateTimeOffset at) { var moscow = at.ToOffset(MoscowTime.Offset); return moscow.Date == MoscowTime.Now.Date ? moscow.ToString("HH:mm", CultureInfo.InvariantCulture) : moscow.ToString("dd MMM", CultureInfo.InvariantCulture); } private string SportLabel(int code) => SportLabels.Resolve(L, code); private string SeverityLabel(AnomalySeverity severity) => severity switch { AnomalySeverity.High => L["Anomaly.Severity.High"], AnomalySeverity.Medium => L["Anomaly.Severity.Medium"], _ => L["Anomaly.Severity.Low"], }; }