@* The accessible alternative to the chart (brief §7.2): one row per bucket with the period label, each series' value
with its unit, the status in words (availability, reason, provenance), the optional cost and price coverage, the
optional comparison (with the bucket it is compared with) and the change, a total row, and a drill-down per row.
A wide table scrolls inside its own container, never the page.
The rows read newest first with the total above them (A-42); the chart beside it stays chronological. *@
@if (_model is not null && _model.Rows.Count > 0)
{
@if (Series.Any(s => !s.IsAdditive))
{
@S.AnalysisTable_NotAdditive
}
}
@code {
/// The buckets of the plan, oldest first; the table turns them round itself (A-42).
[Parameter, EditorRequired]
public IReadOnlyList Buckets { get; set; } = [];
/// The series (, , …).
[Parameter, EditorRequired]
public IReadOnlyList Series { get; set; } = [];
/// The comparison buckets paired with : each row names the bucket it is compared with.
[Parameter]
public IReadOnlyList? ComparisonPairs { get; set; }
[Parameter]
public bool IncludeTotal { get; set; } = true;
/// The drill-down address of a row ( written as a URL); null for none.
[Parameter]
public Func? DrillHref { get; set; }
/// A row's drill-down as an action, when no address is given.
[Parameter]
public EventCallback OnDrill { get; set; }
/// The table's accessible name (also its caption for screen readers).
[Parameter]
public string? Caption { get; set; }
private AnalysisTableModel? _model;
private object? _builtFrom;
private bool HasDrill => DrillHref is not null || OnDrill.HasDelegate;
protected override void OnParametersSet()
{
var source = (Buckets, Series, ComparisonPairs, IncludeTotal, System.Globalization.CultureInfo.CurrentCulture.Name);
if (!Equals(_builtFrom, source))
{
_builtFrom = source;
_model = AnalysisTableModel.Build(Buckets, Series, ComparisonPairs, IncludeTotal);
}
}
private static string? RowClass(AnalysisTableRow row) =>
row.IsTotal ? "mv-row-total" : row.IsQualified ? "mv-row-qualified" : null;
private static string? CellClass(AnalysisTableCell cell, bool numeric)
{
var classes = string.Join(' ', new[] { numeric ? "mv-num" : null, cell.CssClass, cell.IsUnknown ? "mv-unknown" : null }.Where(c => c is not null));
return classes.Length > 0 ? classes : null;
}
}