Skip to content

Refactor leaderboard fetching logic and improve error handling#3829

Merged
Baalmart merged 2 commits into
stagingfrom
chore/empty-state
Jul 14, 2026
Merged

Refactor leaderboard fetching logic and improve error handling#3829
Baalmart merged 2 commits into
stagingfrom
chore/empty-state

Conversation

@OchiengPaul442

@OchiengPaul442 OchiengPaul442 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Status of maturity (all need to be checked before merging):

  • I've tested this locally
  • I consider this code done

Screenshots (optional)

Summary by CodeRabbit

  • New Features

    • Leaderboard toggle controls now support direct slide navigation.
    • Leaderboard pages dynamically reflect the number of available entries.
  • Bug Fixes

    • Improved leaderboard loading, pagination, timeout, and cancellation handling.
    • Prevented updates after leaving the page.
    • Improved carousel behavior during loading and error states.
    • Refined polling recovery after errors.
  • Style

    • Updated card and placeholder shadow styling.

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds abort-aware leaderboard fetching, dynamic carousel pagination, direct toggle-to-page updates, revised stage animations and card shadows, and consolidates polling backoff state around the error counter.

Changes

Leaderboard UI and data flow

Layer / File(s) Summary
Leaderboard fetch contract and cancellation
src/website/src/features/clean-air-forum-2026/lib/learn-progress.ts
Leaderboard limits are optional, query parameters are conditional, and requests support a 30-second timeout plus external abort propagation while retaining response normalization.
Leaderboard toggle index callbacks
src/website/src/components/clean-air-forum-2026/LeaderboardToggles.tsx, src/website/src/features/clean-air-forum-2026/screens/LeaderboardScreen.tsx
Toggle buttons optionally report their index, and the leaderboard screen connects that callback to page state.
Dynamic faces and leaderboard carousel
src/website/src/features/faces-of-clean-air/FacesOfCleanAirPage.tsx, src/website/src/components/clean-air-forum-2026/selfie-components.tsx
The page tracks fetch and mount state, derives slides from available entries, slices rows per slide, updates stage animation structure, wires toggle changes, and adjusts card shadows.

Polling backoff state

Layer / File(s) Summary
Polling refresh backoff consolidation
src/website/src/hooks/usePollingWithVisibility.ts
Polling backoff now relies on the error counter, which refresh resets before invoking polling.

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

Sequence Diagram(s)

sequenceDiagram
  participant FacesOfCleanAirPage
  participant fetchCleanAirForum2026Leaderboard
  participant LeaderboardToggles
  FacesOfCleanAirPage->>fetchCleanAirForum2026Leaderboard: fetch leaderboard entries
  fetchCleanAirForum2026Leaderboard-->>FacesOfCleanAirPage: return normalized entries or error
  FacesOfCleanAirPage->>LeaderboardToggles: provide slide index callback
  LeaderboardToggles->>FacesOfCleanAirPage: report selected index
  FacesOfCleanAirPage->>FacesOfCleanAirPage: update leaderboard slide
Loading

Possibly related PRs

Suggested reviewers: baalmart, hassan-kreatestudio

Poem

Slides turn softly, entries align,
Abort clocks guard the fetching line.
Toggles point and pages flow,
Cards cast shadows, states now know.
Polling counts each error’s beat.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: leaderboard fetch refactoring and improved error handling.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ 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 chore/empty-state

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • JIRA integration encountered authorization issues. Please disconnect and reconnect the integration in the CodeRabbit UI.

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.

@github-actions

Copy link
Copy Markdown
Contributor

New azure website changes available for preview here

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/website/src/features/clean-air-forum-2026/screens/LeaderboardScreen.tsx (1)

386-397: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Toggle clicks skip setDirection, so slide animation direction can be wrong.

goToRelativePage always pairs setDirection with setPage, but onIndexChange={setPage} here calls setPage alone. Jumping via a toggle can therefore animate in the wrong direction relative to the actual page change (stale direction value carried over from the last auto-advance/swipe/arrow interaction).

🔧 Proposed fix
                     isPaused={isPaused}
                     reduceMotion={shouldReduceMotion}
-                    onIndexChange={setPage}
+                    onIndexChange={(index) => {
+                      setDirection(index > page ? 1 : -1);
+                      setPage(index);
+                    }}
                   />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/website/src/features/clean-air-forum-2026/screens/LeaderboardScreen.tsx`
around lines 386 - 397, Update the LeaderboardToggles onIndexChange handler in
LeaderboardScreen so toggle navigation updates direction consistently with page
changes, reusing the existing goToRelativePage logic or equivalent direction
calculation before calling setPage. Preserve the current activeIndex and toggle
behavior while ensuring animation direction reflects the selected page.
src/website/src/features/faces-of-clean-air/FacesOfCleanAirPage.tsx (1)

883-937: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Keep the auto-advance timer independent of live slide-count growth. leaderboardSlideCount now changes with leaderboardEntries.length, so whenever the list crosses a slide boundary this effect tears down and restarts the timeout. That can keep pushing the next carousel advance out while entries keep coming in.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/website/src/features/faces-of-clean-air/FacesOfCleanAirPage.tsx` around
lines 883 - 937, The auto-advance effect should not restart when
leaderboardSlideCount changes as leaderboardEntries grows. Update the effect
dependencies and callback logic around leaderboardSlideCount to use a stable or
current-value reference for the slide-count boundary while keeping the timer’s
lifecycle independent of live count growth; preserve the existing stage
transitions and slide advancement behavior.
🧹 Nitpick comments (1)
src/website/src/features/faces-of-clean-air/FacesOfCleanAirPage.tsx (1)

207-283: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Duplicate FaceCard/SkeletonCard implementations across two files — this PR's shadow tweak had to be applied twice. FacesOfCleanAirPage.tsx keeps its own local SkeletonCard/FaceCard, nearly identical to the exported versions in selfie-components.tsx; both needed the same shadow-token edit here, and they've already diverged elsewhere (fallback display name/location text), which is exactly the kind of drift this duplication invites.

  • src/website/src/features/faces-of-clean-air/FacesOfCleanAirPage.tsx#L207-L283: replace the local SkeletonCard with the exported one from selfie-components.tsx.
  • src/website/src/features/faces-of-clean-air/FacesOfCleanAirPage.tsx#L303-L400: replace the local FaceCard with the exported one from selfie-components.tsx (reconcile the displayName/location fallback differences first).
  • src/website/src/components/clean-air-forum-2026/selfie-components.tsx#L67-L147: keep as the canonical FaceCard once consolidated.
  • src/website/src/components/clean-air-forum-2026/selfie-components.tsx#L149-L208: keep as the canonical SkeletonCard once consolidated.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/website/src/features/faces-of-clean-air/FacesOfCleanAirPage.tsx` around
lines 207 - 283, Consolidate the duplicated card components by removing the
local SkeletonCard and FaceCard implementations from
src/website/src/features/faces-of-clean-air/FacesOfCleanAirPage.tsx at lines
207-283 and 303-400, importing and using the canonical exports from
src/website/src/components/clean-air-forum-2026/selfie-components.tsx instead;
reconcile displayName and location fallbacks before removal. Keep the canonical
FaceCard at lines 67-147 and SkeletonCard at lines 149-208 unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/website/src/features/clean-air-forum-2026/screens/LeaderboardScreen.tsx`:
- Around line 386-397: Update the LeaderboardToggles onIndexChange handler in
LeaderboardScreen so toggle navigation updates direction consistently with page
changes, reusing the existing goToRelativePage logic or equivalent direction
calculation before calling setPage. Preserve the current activeIndex and toggle
behavior while ensuring animation direction reflects the selected page.

In `@src/website/src/features/faces-of-clean-air/FacesOfCleanAirPage.tsx`:
- Around line 883-937: The auto-advance effect should not restart when
leaderboardSlideCount changes as leaderboardEntries grows. Update the effect
dependencies and callback logic around leaderboardSlideCount to use a stable or
current-value reference for the slide-count boundary while keeping the timer’s
lifecycle independent of live count growth; preserve the existing stage
transitions and slide advancement behavior.

---

Nitpick comments:
In `@src/website/src/features/faces-of-clean-air/FacesOfCleanAirPage.tsx`:
- Around line 207-283: Consolidate the duplicated card components by removing
the local SkeletonCard and FaceCard implementations from
src/website/src/features/faces-of-clean-air/FacesOfCleanAirPage.tsx at lines
207-283 and 303-400, importing and using the canonical exports from
src/website/src/components/clean-air-forum-2026/selfie-components.tsx instead;
reconcile displayName and location fallbacks before removal. Keep the canonical
FaceCard at lines 67-147 and SkeletonCard at lines 149-208 unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 77f07084-6038-430e-a2d7-b8866913beab

📥 Commits

Reviewing files that changed from the base of the PR and between a8fae44 and 2ac6ead.

📒 Files selected for processing (6)
  • src/website/src/components/clean-air-forum-2026/LeaderboardToggles.tsx
  • src/website/src/components/clean-air-forum-2026/selfie-components.tsx
  • src/website/src/features/clean-air-forum-2026/lib/learn-progress.ts
  • src/website/src/features/clean-air-forum-2026/screens/LeaderboardScreen.tsx
  • src/website/src/features/faces-of-clean-air/FacesOfCleanAirPage.tsx
  • src/website/src/hooks/usePollingWithVisibility.ts
💤 Files with no reviewable changes (1)
  • src/website/src/hooks/usePollingWithVisibility.ts

@Baalmart
Baalmart requested a review from Copilot July 14, 2026 10:29
@Baalmart
Baalmart merged commit 35d8218 into staging Jul 14, 2026
30 checks passed
@Baalmart
Baalmart deleted the chore/empty-state branch July 14, 2026 10:29
@Baalmart Baalmart mentioned this pull request Jul 14, 2026
1 task

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors the Clean Air Forum 2026 leaderboard/selfie-wall carousel behavior in the website, adding direct slide navigation via toggle controls and improving fetch robustness (timeouts/abort handling) while updating card/placeholder styling.

Changes:

  • Added toggle click support to jump directly to a leaderboard page/slide.
  • Updated leaderboard fetching to support optional limits and a 30s timeout with AbortSignal forwarding.
  • Refined Faces-of-Clean-Air carousel/leaderboard state handling and updated shadow styling for cards/placeholders.

Reviewed changes

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

Show a summary per file
File Description
src/website/src/hooks/usePollingWithVisibility.ts Refactors polling logic by removing backoffRef usage (but leaves backoff-related logic to be reconciled).
src/website/src/features/faces-of-clean-air/FacesOfCleanAirPage.tsx Updates carousel staging, leaderboard fetching state, dynamic slide counts, and styling; adds toggle-driven leaderboard navigation.
src/website/src/features/clean-air-forum-2026/screens/LeaderboardScreen.tsx Wires leaderboard toggle controls to update the current page.
src/website/src/features/clean-air-forum-2026/lib/learn-progress.ts Improves leaderboard fetch cancellation/timeout behavior and makes limit optional.
src/website/src/components/clean-air-forum-2026/selfie-components.tsx Updates FaceCard/SkeletonCard shadow styling to match the new design.
src/website/src/components/clean-air-forum-2026/LeaderboardToggles.tsx Adds onIndexChange and calls it on toggle click to enable direct navigation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 926 to +930
}, [
displayStage,
fetchState,
fetchLeaderboard,
goToRelativePage,
hasLoadedRef,
Comment on lines 1390 to 1394
<div className="w-full">
<LeaderboardRowsBlock
rows={leaderboardRows}
slideKey={leaderboardSlideIndex}
reduceMotion={shouldReduceMotion}
intervalMs={CAROUSEL_INTERVAL_MS}
isPaused={isPaused}
reduceMotion={shouldReduceMotion}
onIndexChange={setPage}
Comment on lines 55 to 59

const refresh = useCallback(() => {
errorCountRef.current = 0;
backoffRef.current = 1;
void invoke();
}, [invoke]);
Comment on lines +91 to +95
if (signal) {
signal.addEventListener('abort', () => controller.abort(signal.reason), {
once: true,
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants