@page "/reports" @attribute [Microsoft.AspNetCore.Authorization.Authorize] @inject IUserSessionService Session @inject SharepointToolbox.Web.Infrastructure.Persistence.GeneratedReportRepository ReportIndex @inject Microsoft.Extensions.Options.IOptions Cfg @inject TranslationSource T @rendermode InteractiveServer @using SharepointToolbox.Web.Core.Models @using SharepointToolbox.Web.Services.Session

Reports

Generated reports for the selected client.

@if (!Session.HasProfile) { return; }
@Session.CurrentProfile!.Name @_reports.Count
@if (_reports.Count == 0) {
No reports generated yet for this client. Schedules run automatically; an admin can create them under Scheduled Reports.
} else {
@foreach (var r in _reports) { }
NameTypeGenerated (UTC)SizeStatus
@(string.IsNullOrEmpty(r.Name) ? "—" : r.Name) @r.Type @r.GeneratedUtc.ToString("yyyy-MM-dd HH:mm") @(r.Status == ReportRunStatus.Success ? $"{r.SizeBytes / 1024.0:F1} KB" : "—") @if (r.Status == ReportRunStatus.Success) { Success @if (r.Emailed) { Emailed } else if (!string.IsNullOrEmpty(r.EmailError)) { Email failed } } else { Failed }
@if (r.Status == ReportRunStatus.Success) { Download }
}
@code { private List _reports = new(); protected override async Task OnInitializedAsync() => await Reload(); private async Task Reload() { if (!Session.HasProfile) { _reports = new(); return; } _reports = (await ReportIndex.LoadForProfileAsync(Session.CurrentProfile!.Id)).ToList(); } private async Task DeleteAsync(GeneratedReport r) { // Remove the file (best-effort) then the index entry. if (r.Status == ReportRunStatus.Success && !string.IsNullOrEmpty(r.FileName)) { var path = System.IO.Path.Combine(Cfg.Value.ExportsFolder, r.ProfileId, System.IO.Path.GetFileName(r.FileName)); try { if (System.IO.File.Exists(path)) System.IO.File.Delete(path); } catch { /* ignore */ } } await ReportIndex.DeleteAsync(r.Id); await Reload(); } }