M5: Blazor dashboard (MudBlazor + ApexCharts)
- MudBlazor theme (dark default) + responsive drawer/appbar layout + nav. - DashboardService read model: KPIs with period-over-period deltas, category breakdown, "what cost more/less" difference view, monthly trends. - Pages: Overview (KPI cards + DeltaChip + donut + difference table), Trends (range-select bar chart), Meters (list + source status), Import (load reference dataset + CSV dry-run preview), Admin (energy types, tariffs). Charts isolated into components to avoid the ApexCharts/MudBlazor Color/Format name clashes. - ReferenceDataImporter: one-click load of all four sheets as a starter dataset (meters, tank, tariff history, category memberships) — bundled sample CSVs copied to app output. - End-to-end render test: import creates meters + consumption; overview/meters/trends/ import/admin pages all return 200 with KPI cards rendered. 92 tests green (56 Core + 36 integration). Deferred to polish: dedicated PV & oil/consumable panels, meter-detail page, full admin CRUD, prev-year trend overlay. Claude-Session: https://claude.ai/code/session_01WujdMtMJPbxDpDnMeK22rr
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
@using ApexCharts
|
||||
@using System.Globalization
|
||||
|
||||
@if (Points is { Count: > 0 })
|
||||
{
|
||||
<ApexChart TItem="TrendPoint" Options="_options" Height="320">
|
||||
<ApexPointSeries TItem="TrendPoint"
|
||||
Items="Points"
|
||||
SeriesType="SeriesType.Bar"
|
||||
Name="Monthly cost"
|
||||
XValue="Label"
|
||||
YValue="p => (decimal)Math.Round(p.Cost, 2)" />
|
||||
</ApexChart>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2" Color="MudBlazor.Color.Secondary">No data in this range.</MudText>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter, EditorRequired]
|
||||
public IReadOnlyList<TrendPoint> Points { get; set; } = [];
|
||||
|
||||
private readonly ApexChartOptions<TrendPoint> _options = new()
|
||||
{
|
||||
Theme = new Theme { Mode = Mode.Dark },
|
||||
DataLabels = new DataLabels { Enabled = false },
|
||||
};
|
||||
|
||||
private static object Label(TrendPoint p) => p.Period.ToString("MMM yy", CultureInfo.InvariantCulture);
|
||||
}
|
||||
Reference in New Issue
Block a user