109 lines
5.0 KiB
Markdown
109 lines
5.0 KiB
Markdown
# Phase 6: Event Browsing UI
|
|
|
|
**Status:** ⬜ Not Started
|
|
**Parent plan:** [PLAN.md](./PLAN.md)
|
|
**Domain:** frontend
|
|
**Implementer:** Opus + frontend-design skill
|
|
**Depends on:** Phase 4 (use cases) + Phase 5 (UI shell)
|
|
|
|
## Objective
|
|
|
|
Build the user-facing browsing experience: pre-match list, live list (auto-refreshing),
|
|
event-detail view with odds-over-time chart, plus an Excel export trigger. Visual
|
|
quality must match the design system established in Phase 5 — distinctive, accessible,
|
|
information-dense without being cluttered.
|
|
|
|
## Tasks
|
|
|
|
- [ ] Create `Marathon.UI/Pages/PreMatch/EventsList.razor`:
|
|
- Server-paginated table of upcoming `Event`s (use `IEventRepository` via injected
|
|
use case wrapper)
|
|
- Filters: sport (multi-select), country (multi-select), date range, free-text
|
|
search (league/team)
|
|
- Sort: scheduled time, sport, country, league
|
|
- Each row shows compact odds preview (Match Win-1 / Draw / Win-2)
|
|
- Click row → navigate to `Pages/Events/Detail.razor?id=...`
|
|
- [ ] Create `Marathon.UI/Pages/Live/LiveList.razor`:
|
|
- Same shell as PreMatch but data source is live snapshots
|
|
- Auto-refresh every `Scraping:PollingIntervalSeconds` (use a timer + state subscription
|
|
pattern; do NOT poll the scraper directly — read from snapshot repo)
|
|
- Visual indicator when odds change since last refresh (subtle pulse / arrow)
|
|
- [ ] Create `Marathon.UI/Pages/Events/Detail.razor`:
|
|
- Event header: sport icon, league, scheduled time, sides 1 & 2
|
|
- Tabs: "Match" | "Period 1" | "Period 2" | ...
|
|
- For each scope, show all bet types in a tabular layout
|
|
- Charts panel: odds-over-time using Plotly.Blazor — three traces for Win-1/Draw/Win-2,
|
|
secondary axis for handicap value
|
|
- Snapshot history table beneath the chart
|
|
- Excel export button (single event or full date range)
|
|
- [ ] Create `Marathon.UI/Components/SportIcon.razor` — small SVG-based component with
|
|
recognizable icons per sport (basketball, football, hockey, tennis, volleyball, etc.).
|
|
- [ ] Create `Marathon.UI/Components/OddsCell.razor` — formats `OddsRate` with delta
|
|
arrow (↑ green, ↓ red) when value changes from previous render.
|
|
- [ ] Create `Marathon.UI/Components/OddsTimeline.razor` — wraps Plotly.Blazor with
|
|
consistent theming and tooltip behavior.
|
|
- [ ] Create `Marathon.UI/Components/ExportDialog.razor` — modal: pick `DateRange`,
|
|
pick `ExportKind`, click Export → calls `ExportToExcelUseCase`. Show success toast
|
|
with output file path.
|
|
- [ ] State management: small `EventBrowsingState` service (singleton scoped to UI)
|
|
holding active filters per page. Inject via DI in pages. No Redux/Fluxor — keep
|
|
simple.
|
|
- [ ] Add packages to `Marathon.UI`:
|
|
- `Plotly.Blazor`
|
|
- [ ] Update `Marathon.UI/Resources/SharedResource.{ru,en}.resx` with all new strings.
|
|
Establish key naming convention from Phase 5 handoff notes.
|
|
- [ ] Performance:
|
|
- Virtualized rows for large event lists (`MudVirtualize` or `MudTable` virtual
|
|
pagination)
|
|
- Debounce filter inputs (300ms)
|
|
- Memoize chart data — recompute only when snapshot list changes
|
|
- [ ] Accessibility:
|
|
- Table semantics with proper headers + ARIA labels
|
|
- Keyboard navigation for row selection
|
|
- Focus visible on all interactive elements
|
|
- Charts include data table fallback for screen readers
|
|
|
|
## Files to Modify/Create
|
|
|
|
- `src/Marathon.UI/Pages/PreMatch/EventsList.razor`
|
|
- `src/Marathon.UI/Pages/Live/LiveList.razor`
|
|
- `src/Marathon.UI/Pages/Events/Detail.razor`
|
|
- `src/Marathon.UI/Components/SportIcon.razor`, `OddsCell.razor`,
|
|
`OddsTimeline.razor`, `ExportDialog.razor`
|
|
- `src/Marathon.UI/Services/EventBrowsingState.cs`
|
|
- `src/Marathon.UI/Resources/SharedResource.{ru,en}.resx` — append new keys
|
|
- `src/Marathon.UI/Components/_Imports.razor` — register Plotly.Blazor
|
|
- Tests: `tests/Marathon.UI.Tests/Pages/**`, `Components/**`
|
|
|
|
## Acceptance Criteria
|
|
|
|
- Compiles (Big Bang).
|
|
- Live list visually conveys odds changes between refreshes.
|
|
- Detail page chart renders 3 traces (Win-1/Draw/Win-2) with smooth interpolation
|
|
and clear tooltip showing exact rate at any point in time.
|
|
- Excel export from the dialog reaches `ExportToExcelUseCase` correctly.
|
|
- Both RU and EN render correctly across all new UI.
|
|
- Distinctive visual identity — implementer should follow frontend-design guidance.
|
|
|
|
## Notes
|
|
|
|
- The frontend-design skill content is provided to the agent in `FRONTEND_DESIGN_SKILL`.
|
|
Apply its principles — typography, color, motion, spatial composition.
|
|
- Use Plotly.Blazor for charts (smooth, themable, professional look).
|
|
- Keep components small (<200 lines) and composable.
|
|
- Big Bang: compile-only smoke check.
|
|
|
|
## Review Checklist
|
|
|
|
- [ ] Compiles
|
|
- [ ] No mutation of domain types in UI components
|
|
- [ ] Filters/sort persist within page session via `EventBrowsingState`
|
|
- [ ] Chart accessible (data table fallback)
|
|
- [ ] All new strings localized in RU + EN
|
|
- [ ] Visual consistency with Phase 5 theme tokens
|
|
|
|
## Handoff to Next Phase
|
|
|
|
<!-- Filled by Phase 6 implementer. Phase 7 (anomaly detection UI) needs to know
|
|
the table/card patterns established here so the anomaly feed is consistent. -->
|