Skip to content

feat: add course detail pages aggregating all editions#259

Merged
rootulp merged 9 commits into
mainfrom
worktree-clever-mixing-stallman
Jul 16, 2026
Merged

feat: add course detail pages aggregating all editions#259
rootulp merged 9 commits into
mainfrom
worktree-clever-mixing-stallman

Conversation

@rootulp

@rootulp rootulp commented Jul 16, 2026

Copy link
Copy Markdown
Owner

Motivation

A user on Reddit asked to aggregate all years of a race into one page, then filter within it by year (e.g. open "IM Wisconsin", see combined stats, then drill into a single year). The repo already models this grouping as a course (base slug, /courses list, course-stats.json.gz), but a course card only linked to a filtered /races?q= list β€” there was no aggregated stats page. This adds one.

What's new

  • /courses/[course] β€” a course detail page aggregating all editions: summary cards, discipline table, time distributions (existing gender/age-group filters), demographics, a combined "fastest finishers ever" leaderboard (each row shows its year and links to that edition's result), and an All Editions table.
  • Year tags β€” single-select; default is all editions combined, ?year=YYYY drills into one edition (server-rendered per view, so payloads stay ~single-edition sized).
  • Repointed the /courses list + chart links from /races?q= to /courses/[course], and added a "View all N editions β†’" link on /race/[slug] (shown only when >1 edition).
  • Extracted a pure computeRaceStats from getRaceStats (behavior-preserving) so the race and course pages share one code path.
  • Nonexistent courses / out-of-range ?year= return a real 404 (route group scopes the overview's loading.tsx so it no longer soft-404s the detail page β€” same SEO fix as fix: return a real 404 for nonexistent athlete pagesΒ #257 for athletes), guarded by e2e/course-404.spec.ts.

Testing

  • Unit: 210 vitest tests pass (new coverage for course grouping, pooling, combined leaderboard, per-edition summary, computeRaceStats parity).
  • E2E: course-404.spec.ts (3/3) β€” real 404s + valid-course 200.
  • Ran the app: verified combined + single-edition views, year tags, per-edition leaderboard links, and 404 behavior on a live dev server.

πŸ€– Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added course overview pages with charts, summaries, leaderboards, demographics, and edition history.
    • Added navigation from course charts and race pages to course details and all available editions.
    • Added loading placeholders for the courses overview.
    • Added dynamic course metadata and improved page-not-found handling for invalid courses or editions.
  • Bug Fixes

    • Corrected course links to use the appropriate course detail pages.
  • Tests

    • Added regression coverage for course routing, statistics, summaries, rankings, and course metadata.

rootulp added 9 commits July 16, 2026 12:36
src/app/courses/loading.tsx created a Suspense boundary wrapping the
[course] child segment, so Next streamed the shell with HTTP 200 before
notFound() resolved (soft 404 for /courses/<bad-slug> and out-of-range
?year=). Moves the overview-only files (page.tsx, loading.tsx, and its
chart components) into a (overview) route group so the loading boundary
no longer wraps [course]. Same class of bug as /athlete/[slug], fixed in
PR #257.

Adds e2e/course-404.spec.ts mirroring athlete-404.spec.ts.
@rootulp rootulp self-assigned this Jul 16, 2026
@vercel

vercel Bot commented Jul 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
tritimes Ready Ready Preview, Comment Jul 16, 2026 8:33pm

@rootulp
rootulp enabled auto-merge (squash) July 16, 2026 20:30
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a1aabc0a-8bdd-4ab0-8d49-ae2a0d9b9fcb

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 7b68c70 and f20e4cd.

πŸ“’ Files selected for processing (17)
  • app/e2e/course-404.spec.ts
  • app/src/app/courses/(overview)/course-charts.tsx
  • app/src/app/courses/(overview)/course-list.tsx
  • app/src/app/courses/(overview)/loading.tsx
  • app/src/app/courses/(overview)/page.tsx
  • app/src/app/courses/[course]/page.tsx
  • app/src/app/race/[slug]/page.tsx
  • app/src/components/CourseBarChart.tsx
  • app/src/lib/__tests__/course-results.test.ts
  • app/src/lib/__tests__/course-summary.test.ts
  • app/src/lib/__tests__/courses.test.ts
  • app/src/lib/__tests__/race-stats.test.ts
  • app/src/lib/__tests__/races-url.test.ts
  • app/src/lib/data.ts
  • app/src/lib/races-url.ts
  • app/src/lib/races.ts
  • app/src/lib/types.ts

πŸ“ Walkthrough

Walkthrough

Adds course-level metadata and aggregation utilities, new overview and detail pages for courses, navigation from race and course views, loading UI, and tests covering routing, statistics, URLs, and course manifest behavior.

Changes

Course detail experience

Layer / File(s) Summary
Course metadata and URL contracts
app/src/lib/types.ts, app/src/lib/races.ts, app/src/lib/races-url.ts, app/src/lib/__tests__/*
Adds course and edition types, derives course information from race manifests, and changes course links to /courses/:slug paths with corresponding tests.
Pooled course statistics
app/src/lib/data.ts, app/src/lib/__tests__/*
Extracts pure race-statistics computation and adds pooled results, cross-edition leaderboards, and per-year summaries with unit coverage.
Course pages and navigation
app/src/app/courses/..., app/src/components/CourseBarChart.tsx, app/src/app/race/[slug]/page.tsx, app/e2e/course-404.spec.ts
Adds course overview and detail routes with metadata, loading states, edition views, aggregate statistics, tables, charts, and 404 regression coverage; race and course navigation now point to course details.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CoursePage
  participant CourseInfo
  participant CourseResults
  participant RaceStats
  CoursePage->>CourseInfo: Resolve course editions
  CoursePage->>CourseResults: Pool edition results
  CourseResults-->>CoursePage: Return CourseResult[]
  CoursePage->>RaceStats: Compute combined statistics
  RaceStats-->>CoursePage: Return RaceStats
  CoursePage-->>CoursePage: Render course details and edition summaries
Loading

Possibly related PRs

  • rootulp/tritimes#250: Also modifies RacePage and adds related metadata and structured page output.
✨ Finishing Touches
πŸ“ Generate docstrings
  • Create stacked PR
  • Commit on current branch
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-clever-mixing-stallman

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands.

@rootulp
rootulp merged commit e86de5a into main Jul 16, 2026
6 of 7 checks passed
@rootulp
rootulp deleted the worktree-clever-mixing-stallman branch July 16, 2026 20:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant