Skip to content

refactor: clean frontend routing flow and remove redundant UI/test noise#689

Open
CMI-James wants to merge 5 commits into
mainfrom
codex/local-pr-guardrails
Open

refactor: clean frontend routing flow and remove redundant UI/test noise#689
CMI-James wants to merge 5 commits into
mainfrom
codex/local-pr-guardrails

Conversation

@CMI-James
Copy link
Copy Markdown
Contributor

@CMI-James CMI-James commented May 12, 2026

Description

Implemented a full frontend cleanup pass to remove routing/state noise, reduce redundant UI behavior, and stabilize brittle tests while preserving user-facing behavior.

Closes #688

Changes proposed

What were you told to do?

Perform a full cleanup of the website codebase by pulling latest changes, removing redundant/noisy frontend patterns, and restoring stable behavior.

What did I do?

Routing and app-shell cleanup

  • Replaced mixed in-memory route state with URL-driven route resolution in the app shell.
  • Aligned sidebar navigation and command actions with consistent path-based navigation.
  • Removed unused state/parameters that were contributing to type and maintenance noise.

UI and component cleanup

  • Fixed invalid nested interactive markup in account switching UI.
  • Improved collapsible validation rendering to only surface inline messages when actually visible.
  • Reduced duplicate holdings display behavior in single-item scenarios.
  • Resolved ambiguous CTA labeling in portfolio empty-state actions.
  • Added defensive compatibility fallback logic for wallet session hook integration points.

Test and quality stabilization

  • Migrated legacy jest-style test usage to vitest-compatible patterns.
  • Updated brittle text assertions to resilient content checks.
  • Fixed command palette test keyboard event handling and close assertions.
  • Kept approved snapshot updates and retained repository-consistent test behavior.

Check List (Check all the applicable boxes)

  • My code follows the code style of this project.
  • This PR does not contain plagiarized content.
  • The title and description of the PR is clear and explains the approach.
  • I am making a pull request against the main branch (left side).
  • My commit messages styles matches our requested structure.
  • My code additions will fail neither code linting checks nor unit test.
  • I am only making changes to files I was requested to.

Screenshots / Testing Evidence

  • npm run --prefix frontend typecheck passed.
  • npm run --prefix frontend lint passed.
  • npm run --prefix frontend test passed (107 files, 1722 tests).
  • npm run --prefix frontend build passed.

Summary by CodeRabbit

  • Bug Fixes

    • Validation messages in collapsible sections now appear only under the intended conditions.
    • Holdings breakdown header total badge visibility corrected to match footer behavior.
    • Account switcher keyboard activation improved for Enter/Space.
  • Improvements

    • App navigation now follows the URL path for consistent routing and command-palette/sidebar actions.
    • Collectibles button label changed to “Explore collectibles.”
  • Tests

    • Test suites migrated from Jest to Vitest.
  • Chores

    • CI/toolchain Rust version updated.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

Warning

Rate limit exceeded

@CMI-James has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 39 minutes and 31 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f3161f11-9a0d-48a4-9c2b-ae7bc3b5f030

📥 Commits

Reviewing files that changed from the base of the PR and between bfdfced and b13ad93.

📒 Files selected for processing (5)
  • .github/workflows/test-contracts.yml
  • contracts/attendance-pass/src/storage.rs
  • contracts/escrow-ledger/src/storage.rs
  • contracts/fanout-distributor/src/storage.rs
  • contracts/vote-escrow/src/storage.rs
📝 Walkthrough

Walkthrough

This PR consolidates frontend navigation from internal route state to URL-derived routing, refines component visibility conditions, removes redundant state management, adds service robustness, and migrates test infrastructure from Jest to Vitest while updating test assertions.

Changes

Frontend cleanup and stabilization

Layer / File(s) Summary
App routing refactor: URL-derived navigation
frontend/src/App.tsx
AppContent derives active route from location.pathname via ROUTE_PATHS mapping and resolveRouteFromPath helper instead of internal state. Command palette and sidebar use navigate() with mapped paths. Main content and Portfolio callbacks use currentRoute and ROUTE_PATHS.
Component UI refinements: visibility and accessibility
frontend/src/components/CollapsibleSection.tsx, frontend/src/components/HoldingsBreakDowncard.tsx, frontend/src/components/v1/AccountSwitcher.tsx, frontend/tests/unit/AccountSwitcher.test.tsx
CollapsibleSection gates inline validation by showInlineValidation state. HoldingsBreakDowncard total badge requires holdings.length > 1. AccountSwitcher refactors recent items from buttons to menuitem divs with explicit Enter/Space keyboard handling. Unused import removed from AccountSwitcher test.
QueueHealthWidget: remove redundant refresh state
frontend/src/components/v1/QueueHealthWidget.tsx, frontend/tests/components/QueueHealthWidget.test.tsx
Component removes lastRefresh state and setLastRefresh() calls; relies on timeUntilRefresh countdown. Test suite migrates Jest to Vitest with mock setup updates and timer advancements wrapped in act().
useWalletStatus: add fallback for optional service methods
frontend/src/hooks/v1/useWalletStatus.ts
Introduces DEFAULT_REFRESH_STATE constant and uses optional chaining with fallbacks for getRefreshState() and getSessionDropped() methods.
Test cleanup: Jest-to-Vitest migration and assertion updates
frontend/tests/components/AnalyticsRangeSwitcher.test.tsx, frontend/tests/components/AuditSnapshotCard.test.tsx, frontend/tests/components/Portfolio.test.tsx, frontend/tests/components/QuickPivotLinks.test.tsx, frontend/tests/components/v1/CampaignRewardsSpotlightCard.test.tsx, frontend/tests/components/v1/CommandPalette.test.tsx
Migrates test setup from jest.fn()/jest.useFakeTimers()/jest.clearAllMocks() to vi equivalents. Updates assertions: AnalyticsRangeSwitcher expects "90 Days" instead of "1 Year"; Portfolio/CampaignRewardsSpotlightCard update query selectors; CommandPalette switches to window.dispatchEvent with async assertions. Removes unused React imports.
Minor code cleanup: unused parameters and exports
frontend/src/pages/AnalyticsDashboard.tsx, frontend/src/pages/Portfolio.tsx, frontend/src/utils/v1/index.ts
AnalyticsDashboard marks unused range parameter as _range and removes unused index from map. Portfolio changes collectibles button text to "Explore collectibles". utils/v1/index.ts removes useAsyncAction and usePaginatedQuery re-exports; repositions useNetworkGuard.
CI: Rust toolchain bump
.github/workflows/lint.yml, .github/workflows/test-contracts.yml, rust-toolchain.toml
GitHub Actions and rust-toolchain.toml updated to pin Rust toolchain to 1.91.0 instead of 1.85.0 for contract linting and contract tests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • theblockcade/stellarcade#674: Overlapping changes to CollapsibleSection and HoldingsBreakDowncard visibility logic, inline validation rendering, and total-badge conditions.
  • theblockcade/stellarcade#491: Related App.tsx route/navigation handling refactor and AppSidebar wiring (this PR consolidates route resolution to URL-derived state; earlier PR introduced AppSidebar and route state/onNavigate callbacks).
  • theblockcade/stellarcade#428: Related useWalletStatus hook modifications (this PR adds DEFAULT_REFRESH_STATE fallback; earlier PR extended hook to expose lastUpdatedAt/isRefreshing).

Poem

🐰 Routes now live in paths so true,
State cleaned, tests blue, Vitest too.
Components shine with proper guards,
Simplicity won—less code, more cards!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Rust toolchain updates in workflows and rust-toolchain.toml (1.85.0→1.91.0) are out of scope relative to the frontend cleanup objective, though they represent valid maintenance work unrelated to issue #688. Consider separating Rust toolchain version bumps into a dedicated CI-focused pull request to maintain clear separation of concerns between frontend cleanup and infrastructure updates.
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main objective: a frontend cleanup focused on routing flow improvements and removal of redundant UI/test patterns, which aligns with the primary changes throughout the changeset.
Linked Issues check ✅ Passed All coding objectives from issue #688 are met: routing consolidated to URL-driven resolution (App.tsx), invalid UI patterns removed (AccountSwitcher, CollapsibleSection), redundant exports cleaned (v1/index.ts), and tests migrated to vitest with improved assertions.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/local-pr-guardrails

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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 (1)
frontend/tests/components/AnalyticsRangeSwitcher.test.tsx (1)

134-147: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fallback test no longer validates fallback behavior.

On Line 137, passing ranges={mockRanges} means the test "uses default ranges when none provided" does not cover the "none provided" path anymore. Either remove the prop in this test or rename/split the case.

Suggested minimal fix
-    it('uses default ranges when none provided', () => {
+    it('renders provided ranges', () => {
🤖 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 `@frontend/tests/components/AnalyticsRangeSwitcher.test.tsx` around lines 134 -
147, The test "uses default ranges when none provided" is passing
ranges={mockRanges} so it doesn't exercise the fallback path; update the test
for AnalyticsRangeSwitcher by removing the ranges prop (leave selectedId="24h"
and onChange={mockOnChange}) so the component uses its default ranges, or
alternatively rename the test to reflect that it uses provided ranges and add a
separate test that omits ranges to assert default labels ("24 Hours", "7 Days",
"90 Days"); adjust references to mockRanges and mockOnChange accordingly.
🧹 Nitpick comments (2)
frontend/src/App.tsx (1)

53-53: ⚡ Quick win

Use ROUTE_PATHS constants for consistency.

Commands "go-lobby" and "go-profile" use hardcoded paths "/" and "/profile" instead of the centralized ROUTE_PATHS constants. This creates inconsistency with other commands and could cause maintenance issues if paths change.

♻️ Proposed fix to use ROUTE_PATHS constants
     {
       id: "go-lobby",
       label: "Go to Lobby",
       description: "Open the game lobby",
-      action: () => navigate("/"),
+      action: () => navigate(ROUTE_PATHS.lobby),
     },
     {
       id: "go-profile",
       label: "Go to Profile Settings",
       description: "Open the profile settings page",
-      action: () => navigate("/profile"),
+      action: () => navigate(ROUTE_PATHS.profile),
     },

Also applies to: 65-65

🤖 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 `@frontend/src/App.tsx` at line 53, Replace the hardcoded route strings used in
the command actions with the centralized ROUTE_PATHS constants: update the
"go-lobby" action (currently calling navigate("/") ) to call
navigate(ROUTE_PATHS.LOBBY) and update the "go-profile" action (currently
calling navigate("/profile")) to call navigate(ROUTE_PATHS.PROFILE); also ensure
ROUTE_PATHS is imported into the App component if it's not already.
frontend/src/hooks/v1/useWalletStatus.ts (1)

62-68: ⚡ Quick win

Consider adding lastSucceededAt to the default state for explicitness.

The constant omits lastSucceededAt, which is accessed on line 151. While this works (the property is optional in WalletSessionRefreshState), explicitly including it improves clarity and documents the full shape.

♻️ Proposed enhancement for explicitness
 const DEFAULT_REFRESH_STATE: WalletSessionRefreshState = {
   phase: WalletSessionRefreshPhase.IDLE,
   trigger: "manual",
   attempt: 0,
   maxAttempts: 1,
   terminal: false,
+  lastSucceededAt: undefined,
 };
🤖 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 `@frontend/src/hooks/v1/useWalletStatus.ts` around lines 62 - 68,
DEFAULT_REFRESH_STATE omits the optional lastSucceededAt property which is later
accessed; update the DEFAULT_REFRESH_STATE object in useWalletStatus.ts (the
WalletSessionRefreshState default) to include lastSucceededAt: null (or an
appropriate initial Date | null) so the full shape is explicit and consumers
referencing lastSucceededAt won't rely on its absence.
🤖 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 `@frontend/tests/components/AnalyticsRangeSwitcher.test.tsx`:
- Around line 134-147: The test "uses default ranges when none provided" is
passing ranges={mockRanges} so it doesn't exercise the fallback path; update the
test for AnalyticsRangeSwitcher by removing the ranges prop (leave
selectedId="24h" and onChange={mockOnChange}) so the component uses its default
ranges, or alternatively rename the test to reflect that it uses provided ranges
and add a separate test that omits ranges to assert default labels ("24 Hours",
"7 Days", "90 Days"); adjust references to mockRanges and mockOnChange
accordingly.

---

Nitpick comments:
In `@frontend/src/App.tsx`:
- Line 53: Replace the hardcoded route strings used in the command actions with
the centralized ROUTE_PATHS constants: update the "go-lobby" action (currently
calling navigate("/") ) to call navigate(ROUTE_PATHS.LOBBY) and update the
"go-profile" action (currently calling navigate("/profile")) to call
navigate(ROUTE_PATHS.PROFILE); also ensure ROUTE_PATHS is imported into the App
component if it's not already.

In `@frontend/src/hooks/v1/useWalletStatus.ts`:
- Around line 62-68: DEFAULT_REFRESH_STATE omits the optional lastSucceededAt
property which is later accessed; update the DEFAULT_REFRESH_STATE object in
useWalletStatus.ts (the WalletSessionRefreshState default) to include
lastSucceededAt: null (or an appropriate initial Date | null) so the full shape
is explicit and consumers referencing lastSucceededAt won't rely on its absence.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: efa10e5b-52fd-4758-8e5d-bf3a751b877e

📥 Commits

Reviewing files that changed from the base of the PR and between 3ca67b8 and a521320.

📒 Files selected for processing (17)
  • frontend/src/App.tsx
  • frontend/src/components/CollapsibleSection.tsx
  • frontend/src/components/HoldingsBreakDowncard.tsx
  • frontend/src/components/v1/AccountSwitcher.tsx
  • frontend/src/components/v1/QueueHealthWidget.tsx
  • frontend/src/hooks/v1/useWalletStatus.ts
  • frontend/src/pages/AnalyticsDashboard.tsx
  • frontend/src/pages/Portfolio.tsx
  • frontend/src/utils/v1/index.ts
  • frontend/tests/components/AnalyticsRangeSwitcher.test.tsx
  • frontend/tests/components/AuditSnapshotCard.test.tsx
  • frontend/tests/components/Portfolio.test.tsx
  • frontend/tests/components/QueueHealthWidget.test.tsx
  • frontend/tests/components/QuickPivotLinks.test.tsx
  • frontend/tests/components/v1/CampaignRewardsSpotlightCard.test.tsx
  • frontend/tests/components/v1/CommandPalette.test.tsx
  • frontend/tests/unit/AccountSwitcher.test.tsx
💤 Files with no reviewable changes (2)
  • frontend/src/utils/v1/index.ts
  • frontend/tests/unit/AccountSwitcher.test.tsx

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.

Frontend cleanup: remove routing/state noise and stabilize UI/test behavior

1 participant