Files

3.1 KiB

Phase 8: Results Loader

Status: Not Started Parent plan: PLAN.md Domain: fullstack Implementer: Sonnet (backend) + Opus (UI) Depends on: Phase 6 (UI patterns)

Objective

Per customer TZ §4: scrape and persist results of completed events, with a UI that allows the user to load all results in a date range OR pick specific events to load selectively.

Tasks

Backend (Sonnet)

  • PullResultsUseCase was scaffolded in Phase 4 — extend it here:
    • When selection is null/empty, fetch results for ALL completed events in range that don't have a stored EventResult yet
    • When selection provided, fetch results only for those events
    • Idempotent — re-running for already-loaded results is a no-op
  • Add IResultsScraper-related parser methods (or extend IOddsScraper with ScrapeResultsAsync) — implementation may already exist from Phase 3.
  • After persisting results, infer WinnerSide and update the Event accordingly (or store derived WinnerSide on EventResult only — implementer's choice, document in handoff).
  • Tests in Marathon.Application.Tests:
    • PullResultsUseCase with selection list pulls only those events
    • With null selection, pulls all completed events missing results in range
    • Idempotency: running twice produces no duplicates

Frontend (Opus + frontend-design)

  • Create Marathon.UI/Pages/Results/ResultsLoader.razor:
    • Date range picker
    • Two modes: "All in range" (default) | "Selected events"
    • Selected events mode: searchable multi-select of completed events lacking results
    • "Load Results" button → invokes PullResultsUseCase
    • Progress indicator (number of events processed / total)
    • Result table on completion showing what was loaded (event identity, score, winner side)
  • Create Marathon.UI/Pages/Results/ResultsList.razor:
    • Browse already-loaded results
    • Filter by sport, date range, winner-side-1 / winner-side-2 / draw
    • Link back to event detail page (Phase 6)
  • Add Results entry to navigation drawer.
  • Localize all strings RU + EN.
  • Frontend tests:
    • bUnit: loader page invokes use case with correct parameters in both modes
    • bUnit: results list filter narrows correctly

Files to Modify/Create

  • src/Marathon.Application/UseCases/PullResultsUseCase.cs — extend
  • src/Marathon.UI/Pages/Results/ResultsLoader.razor
  • src/Marathon.UI/Pages/Results/ResultsList.razor
  • tests/Marathon.Application.Tests/UseCases/PullResultsUseCaseTests.cs
  • tests/Marathon.UI.Tests/Pages/Results/**

Acceptance Criteria

  • Compiles (Big Bang).
  • Selective loading respects user's selection.
  • Bulk loading skips events that already have results.
  • UI shows progress during a multi-event load.

Notes

  • Big Bang: compile-only smoke check.

Review Checklist

  • Idempotent — no duplicate EventResult rows
  • UI handles empty range gracefully (no events match)
  • All strings localized

Handoff to Next Phase