feat(leaderboard): season-driven data loading with URL synchronization#583
Open
petahade wants to merge 3 commits into
Open
feat(leaderboard): season-driven data loading with URL synchronization#583petahade wants to merge 3 commits into
petahade wants to merge 3 commits into
Conversation
- Extend `useLeaderboard` with an optional `season` param; appends
`?season=<id>` to every API request and includes it in the React Query
key so season changes trigger fresh fetches rather than reusing cached
data for the wrong season.
- `/leaderboard` page: add a Season filter (alongside category/search/sort),
initialize it from the `?season=` query param on page load, and update
the URL via `router.push(..., { scroll: false })` on each change — no
full reload, back/forward navigation preserved.
- `/leaderboards` page: wire existing `SeasonSelector` to the same URL-sync
handler instead of isolated local state; season is now passed through to
`useLeaderboard` so the API call reflects the selection.
- Both pages use `isFetching` (not just `isLoading`) to show skeleton rows
and a `Loader2` spinner in the table heading while a season-specific
request is in flight, preventing stale rankings from lingering on screen.
- Wrap both page components in a `<Suspense>` boundary required by Next.js
14 for `useSearchParams` in client components.
|
@petahade is attempting to deploy a commit to the paul joseph's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
@petahade Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #554
Summary
This PR completes the leaderboard season flow so that selecting a season actually changes what data is fetched — rather than only toggling local UI state — and keeps the browser URL in sync with the active selection.
Problem
SeasonSelectorpreviously called a localsetSeasonthat had no effect on data fetching.useLeaderboardnever received or forwarded the season, so every API call always returned the same season-agnostic results regardless of what the user selected. The URL was also never updated, so refreshing the page or sharing a link always reset the view to the default season.Changes
frontend/src/hooks/useLeaderboard.tsseason?: stringas a fourth parameter.seasonis included in the React QueryqueryKey— a season change produces a new cache entry and a fresh fetch, while re-selecting the same season is a no-op (no duplicate request).URLSearchParamsto append?season=<id>to every API call when a season is provided. When omitted, the query string is unchanged (backwards-compatible with existing callers).frontend/src/app/leaderboard/page.tsxSEASONSconstant (matchingSeasonSelector's list) and a new Season<Select>filter in the Filters card — filter grid expanded from 3 to 4 columns (lg:grid-cols-4).?season=on page load viauseSearchParams(), falling back to"current".handleSeasonChangeupdates local state, resets pagination to page 1, and pushes the updated query string withrouter.push(..., { scroll: false })— no full reload, native browser back/forward preserved. Selecting"current"removes the param to keep URLs clean.useLeaderboardnow receivesseasonand returnsisFetchingin addition toisLoading.isFetching(not justisLoading) so stale data is replaced immediately when a season-specific request starts, even when a stale cache entry exists.Loader2spinner appears next to the "Rankings" heading whenisFetching && !isLoading(background refetch in progress).isLoadingprop are also gated onisFetching.<Suspense>as required by Next.js 14 foruseSearchParamsin client components.frontend/src/app/leaderboards/page.tsxonChange={setSeason}onSeasonSelectorwithonChange={handleSeasonChange}, which uses the same URL-sync logic described above.?season=query param on page load.useLeaderboardnow receivesseasonso API requests include the correct season parameter.isFetchingdrives theLeaderboardTableisLoadingprop and aLoader2spinner in the table heading, showing feedback during season switches.<Suspense>for the sameuseSearchParamsrequirement.Behaviour
?season=season-3, new rankings rendered?season=season-2in URL?season=season-4?season=param removed, URL stays cleanTest plan
/leaderboard— default season ("Current Season") is selected, no?season=in URL.?season=season-3without a full page reload; skeleton rows appear briefly; results refresh.?season=param is removed from URL.?season=season-2— Season 2 is pre-selected and the correct data loads.?season=param is preserved in URL./leaderboardswith theSeasonSelectordropdown.useLeaderboardwithout aseasonargument are unaffected (no?season=appended, same query key behaviour as before).