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:
2026-07-13 12:11:12 +02:00
parent 6fc710d55a
commit d5419729e5
25 changed files with 1094 additions and 74 deletions
+37
View File
@@ -0,0 +1,37 @@
using MudBlazor;
namespace MeterVault.App.Theme;
/// <summary>The MeterVault MudBlazor theme — an energy-dashboard palette, dark by default.</summary>
public static class MeterVaultTheme
{
public const string PrimaryTeal = "#14B8A6";
public const string SecondaryAmber = "#F6C445";
public static readonly MudTheme Instance = new()
{
PaletteLight = new PaletteLight
{
Primary = PrimaryTeal,
Secondary = SecondaryAmber,
AppbarBackground = "#0E7C6B",
Background = "#F7F8FA",
Surface = "#FFFFFF",
},
PaletteDark = new PaletteDark
{
Primary = PrimaryTeal,
Secondary = SecondaryAmber,
Background = "#0D1117",
Surface = "#161B22",
AppbarBackground = "#10151C",
DrawerBackground = "#10151C",
TextPrimary = "#E6EDF3",
},
LayoutProperties = new LayoutProperties
{
DrawerWidthLeft = "250px",
DefaultBorderRadius = "8px",
},
};
}