feat(phase-6): event browsing UI — pre-match/live lists, detail page, +26 bUnit tests
Replaces PreMatch/Live placeholder pages with a shared EventListShell
(filter chips, date range, sortable virtualized-friendly table, debounced
search, live auto-refresh with odds-movement indicators) and adds a new
/events/{eventCode} detail page (asymmetric header lockup, dynamic
Match/Period tabs, Plotly.Blazor odds-over-time chart with accessible
data-table fallback, snapshot history, Excel export modal).
New primitives matching Phase 5's editorial-quant system:
- SportIcon: inline SVGs per sport (basketball=6, football=11,
tennis=22723, hockey=43658, generic fallback)
- OddsCell: tabular mono with ▲/▼/— delta + flash on change
(prefers-reduced-motion honored)
- OddsTimeline: Plotly.Blazor wrapper with theme-aware colors and
<details>/<summary> data-table screen-reader fallback
- ExportDialog: From/To pickers + ExportKind radio + Esc/Enter
keyboard, surfaces use-case errors inline
- EventListShell: shared section shell for PreMatch/Live cadence
State + service split keeps the RCL host-agnostic:
- IEventBrowsingService / EventBrowsingService — wraps repos, returns
view-model records (EventListItem, EventDetail, EventScopeBoard,
BetRow, OddsTimelinePoint, SnapshotHistoryEntry); pages never see
EF or domain entities directly.
- EventBrowsingState — singleton (per-circuit in BlazorWebView) holding
immutable PageFilter records for PreMatch and Live.
Plotly.Blazor 5.4.1 added (latest .NET 8 line; 7.x has breaking changes).
+59 RU/EN localization keys following the Phase 5 dot-segmented convention.
Tests: +26 bUnit tests (PreMatch/Live/Detail pages, OddsCell/SportIcon/
ExportDialog components, EventBrowsingState). Total 228/228 passing
(Domain 96 + Application 15 + Infrastructure 80 + UI 37; baseline 202).
Build clean (0/0).
PLAN.md: P2/P3/P5 top-level checkboxes ticked; P6 row marked Done.
This commit is contained in:
@@ -109,6 +109,18 @@ Marathon_<YYYY-MM-DD>_to_<YYYY-MM-DD>.xlsx
|
||||
`System.Windows.Application` fully qualified in `App.xaml.cs`.
|
||||
- **`Directory.Build.props` must NOT set `TargetFramework`** when projects in the
|
||||
same solution use different TFMs (e.g., `net8.0` vs `net8.0-windows`).
|
||||
- **Razor source generator does NOT accept C# 11 raw string literals** (`"""…"""`)
|
||||
inside `@code` blocks — concatenate single-quoted attribute strings instead.
|
||||
- **Razor reserves the identifier `code`.** Loop variables must use any other
|
||||
name (`var sportCode in ...`) or the parser treats it as the `@code` directive.
|
||||
- **`MudBlazor.DateRange` shadows `Marathon.Application.Storage.DateRange`** in
|
||||
any Razor file that pulls both namespaces via `_Imports.razor`. Use a per-file
|
||||
alias: `using AppDateRange = Marathon.Application.Storage.DateRange;`.
|
||||
- **`Plotly.Blazor.LayoutLib.Margin` clashes with `MudBlazor.Margin`.** Fully
|
||||
qualify the Plotly side at the new-expression: `new Plotly.Blazor.LayoutLib.Margin {…}`.
|
||||
- **`Event.ScheduledAt` requires offset `+03:00`.** Test fixtures and any code
|
||||
that constructs Moscow datetimes must use `new DateTimeOffset(date, TimeSpan.FromHours(3))`,
|
||||
never pass a `DateTime.UtcNow` value to that constructor.
|
||||
|
||||
## Feature: Initial Implementation > Phase 4: Application + Workers — Learnings
|
||||
|
||||
|
||||
Reference in New Issue
Block a user