Skip to content

refactor: solid leaderboards (@fehmer, @miodec)#7485

Merged
Miodec merged 117 commits intomasterfrom
feature/solid-leaderboards
Mar 7, 2026
Merged

refactor: solid leaderboards (@fehmer, @miodec)#7485
Miodec merged 117 commits intomasterfrom
feature/solid-leaderboards

Conversation

@fehmer
Copy link
Member

@fehmer fehmer commented Feb 9, 2026

No description provided.

@monkeytypegeorge monkeytypegeorge added the frontend User interface or web stuff label Feb 9, 2026
@fehmer fehmer added the force-ci Force CI to run on draft PRs label Feb 9, 2026
@fehmer fehmer force-pushed the feature/solid-leaderboards branch from 1498b5e to 2faf95b Compare February 10, 2026 12:22
@fehmer fehmer force-pushed the feature/solid-leaderboards branch from 532da70 to 471ed1a Compare February 10, 2026 22:29
@monkeytypegeorge monkeytypegeorge removed the backend Server stuff label Mar 6, 2026
@Miodec Miodec requested a review from Copilot March 6, 2026 16:21
@github-actions github-actions bot added the waiting for review Pull requests that require a review before continuing label Mar 6, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 43 out of 44 changed files in this pull request and generated 8 comments.

Comment on lines +59 to +61
if (params.page !== undefined) {
setPage(params.page - 1);
}
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setPage(params.page - 1) can still produce negative / non-integer pages from user-edited URLs (schema allows any number). Clamp to >= 0 and preferably coerce+validate in LeaderboardUrlParamsSchema (e.g., .int().min(1)) so invalid URLs don’t trigger invalid API requests.

Copilot uses AI. Check for mistakes.
Comment on lines +33 to +44
export const LeaderboardUrlParamsSchema = z
.object({
type: z.enum(["allTime", "daily", "weekly"]),
mode: ModeSchema.optional(),
mode2: z.string().optional(),
language: LanguageSchema.optional(),
yesterday: z.boolean().optional(),
lastWeek: z.boolean().optional(),
friendsOnly: z.boolean().optional(),
page: z.number().optional(),
goToUserPage: z.boolean().optional(),
})
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LeaderboardUrlParamsSchema.page is z.number().optional(), which accepts negatives/decimals. Since this is parsed directly from the URL, constrain it (e.g., .int().min(1)) and consider coercion if needed so readGetParameters can safely convert it to a 0-based index.

Copilot uses AI. Check for mistakes.
Comment on lines +84 to +86
if (response.body.data.entries.length === 0 && options.page !== 0) {
setPage(Math.floor(response.body.data.count / pageSize));
}
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When requesting a page beyond the end, entries.length === 0 triggers setPage(Math.floor(count / pageSize)). This is off-by-one when count is an exact multiple of pageSize (e.g. 100/50 => 2 but last valid page index is 1). Compute the last valid 0-based page with Math.max(0, Math.ceil(count / pageSize) - 1) (or Math.floor((count - 1) / pageSize) when count>0).

Copilot uses AI. Check for mistakes.
mode: undefined,
mode2: undefined,
language: undefined,
previous: false,
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

normalizeSelection() always forces previous: false for weekly. This means changing any weekly option via the sidebar (e.g. toggling friends-only) will silently reset the user back to “this week” even if they selected “last week”. Preserve draft.previous (or default it) instead of hard-resetting it.

Suggested change
previous: false,
previous: draft.previous ?? false,

Copilot uses AI. Check for mistakes.
Comment on lines +55 to +58
}
});

setSelection({ ...getSelection(), ...newSelection } as Selection);

Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getSelection() is used but not imported from ../stores/leaderboard-selection, causing a compile error. Import it (or avoid needing it) before calling setSelection({...getSelection(), ...}).

Copilot uses AI. Check for mistakes.
Comment on lines +42 to +58
let newSelection: Partial<Selection> = {
type: params.type,
friendsOnly: params.friendsOnly ?? false,
};

if (params.type === "weekly") {
newSelection.previous = params.lastWeek ?? false;
} else {
newSelection.mode = params.mode ?? "time";
newSelection.mode2 = params.mode2 ?? "15";
newSelection.language = params.language ?? "english";
newSelection.previous =
(params.type === "daily" && params.yesterday) ?? false;
}
});

setSelection({ ...getSelection(), ...newSelection } as Selection);

Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When params.type === "weekly", newSelection is merged with getSelection(). If the current selection is a speed leaderboard, this merge keeps mode/mode2/language as strings, which fails SelectionSchema for weekly (z.never().optional()), so setSelection will reject the update. Build a valid weekly selection by explicitly clearing those fields (set to undefined or omit) before calling setSelection (or avoid merging for weekly).

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 44 out of 45 changed files in this pull request and generated 5 comments.

@Miodec Miodec merged commit c786538 into master Mar 7, 2026
14 checks passed
@Miodec Miodec deleted the feature/solid-leaderboards branch March 7, 2026 16:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

force-ci Force CI to run on draft PRs frontend User interface or web stuff waiting for review Pull requests that require a review before continuing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants