Skip to content

szn buttons#2099

Merged
ragnep merged 8 commits intomainfrom
szn-buttons
Mar 12, 2026
Merged

szn buttons#2099
ragnep merged 8 commits intomainfrom
szn-buttons

Conversation

@ragnep
Copy link
Copy Markdown
Contributor

@ragnep ragnep commented Mar 11, 2026

Summary by CodeRabbit

  • New Features

    • Collection shortcuts for quick toggling and clearer metric selection highlighting.
    • Season shortcuts for rapid season selection; hover continues to show subtle previews.
    • Visible selected states and improved hover/keyboard interactions for metrics and season tiles.
  • Tests

    • Expanded coverage for shortcut flows, hover vs click behavior, visual selection states, desktop visibility, and pagination/URL interactions.
  • Style

    • Small UI text adjustment in season dropdown for tighter layout.

Signed-off-by: ragnep <ragneinfo@gmail.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 11, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds collection and season shortcut interactions plus preview-vs-select semantics across collected-stats components; extends DisplaySeason and header metric types with seasonNumber and collection; refactors UserPageCollected query/update logic to compute multi-field updates and expose shortcut callbacks; updates tests for hover preview, click selection, and shortcut flows.

Changes

Cohort / File(s) Summary
Types & Helpers
components/user/collected/stats/types.ts, components/user/collected/stats/helpers.ts
Added seasonNumber: number to DisplaySeason and optional collection: CollectedCollectionType to header metrics; helpers emit these fields.
Top-level Filters & Shortcuts
components/user/collected/UserPageCollected.tsx
Expanded ProfileCollectedFilters shape; added converters, getFilters, createQueryString, getCollectionUpdate and new shortcut setters (setCollectionShortcut, setSeasonShortcut); rewired query/update construction and effective season derivation.
Stats Container & Visibility
components/user/collected/UserPageCollectedStats.tsx
Added props activeCollection, activeSeasonNumber, onCollectionShortcut, onSeasonShortcut; introduced preferred-season preview state, getCollapsedStartedSeasons, and fallback visibility/selection resolution.
Header Interactivity
components/user/collected/stats/subcomponents/CollectedStatsHeader.tsx
Per-metric interactive rendering using activeCollection + onCollectionShortcut; metrics can render as buttons and compute isSelected/tone, invoking shortcut on click.
Seasons & Tiles
components/user/collected/stats/subcomponents/CollectedStatsSeasons.tsx, components/user/collected/stats/subcomponents/CollectedStatsSeasonTile.tsx
Tile props renamed: isActiveisSelected, onActivateonPreview; added optional onSelect; hover/focus call preview, click triggers select/shortcut; styling and aria updated to use isSelected.
Public API Updates
components/user/collected/UserPageCollectedStats.tsx, components/user/collected/UserPageCollected.tsx
Public props/interfaces expanded: UserPageCollectedStatsProps gains activeCollection?, activeSeasonNumber?, onCollectionShortcut?, onSeasonShortcut?; ProfileCollectedFilters extended with collection/subcollection/seized/szn/initialSznId/page/pageSize/sortBy/sortDirection.
Tests: collected & stats
__tests__/components/user/collected/*.test.tsx
Tests updated to include seasonNumber, rename tile props, assert hover-preview vs click-selection behavior, add shortcut mocks/buttons, and cover desktop visibility/see-more cases and router/query expectations.
Activity & Helpers Cleanup
components/user/stats/activity/activity.helpers.ts, components/user/stats/activity/UserPageActivityWrapper.tsx, __tests__/components/user/stats/activity/*
Removed page-filter reducer/hooks and related exports; removed re-export of USER_PAGE_ACTIVITY_TAB; updated tests to import from activity.types.
Small UI tweak
components/utils/select/dropdown/SeasonsGridDropdown.tsx
Adjusted button text size class from tw-text-sm to tw-text-xs (presentation-only).

Sequence Diagram

sequenceDiagram
    participant User
    participant Header as CollectedStatsHeader
    participant Season as CollectedStatsSeasonTile
    participant Stats as UserPageCollectedStats
    participant Parent as UserPageCollected
    participant Router as Router

    User->>Header: hover metric
    Header->>Stats: onPreview(collection?)
    Stats->>Parent: set preferredSeasonPreview / preview state

    User->>Header: click metric
    Header->>Parent: onCollectionShortcut(collection)
    Parent->>Parent: getCollectionUpdate(...)
    Parent->>Router: router.replace / updateFields

    User->>Season: hover tile
    Season->>Stats: onPreview()
    Stats->>Parent: preview season

    User->>Season: click tile
    Season->>Stats: onPreview()
    Season->>Stats: onSelect()
    Stats->>Parent: onSeasonShortcut(seasonNumber)
    Parent->>Parent: getCollectionUpdate(...)
    Parent->>Router: router.replace / updateFields
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • prxt6529
  • GelatoGenesis

Poem

🐰
I peek on hover, I choose on click,
Seasons shuffle gently, neat and quick.
Shortcuts hum and filters flow,
A bunny cheers as states all glow.

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'szn buttons' is too vague and abbreviated, failing to convey meaningful information about the changeset despite referring to a real part of the changes. Use a more descriptive title such as 'Add season shortcut buttons and collection shortcuts' or 'Implement interactive season and collection selection via shortcut callbacks'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch szn-buttons

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.

Signed-off-by: ragnep <ragneinfo@gmail.com>
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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/user/collected/stats/subcomponents/CollectedStatsSeasonTile.tsx`:
- Around line 122-125: The click handler handleClick should not call onPreview
because previewing happens on hover/focus; change handleClick to only invoke
onSelect (i.e., remove the onPreview() call) so clicks only trigger selection.
Apply the same change to the other similar click handler in this component (the
second occurrence around the other tile handler) so no click path invokes
onPreview; keep onPreview only on hover/focus handlers.

In `@components/user/collected/UserPageCollected.tsx`:
- Around line 590-591: The active tile should use the optimistic season state so
UI updates immediately when setSzn() changes filters.szn; change the prop usage
in UserPageCollected so activeSeasonNumber reads the optimistic value
(filters.szn) falling back to filters.initialSznId if empty/undefined — update
the activeSeasonNumber prop passed to the tile/component to use filters.szn ||
filters.initialSznId and ensure the receiving component (activeSeasonNumber)
still accepts the same type.

In `@components/user/collected/UserPageCollectedStats.tsx`:
- Around line 109-139: The component needs to reset its local
tile-preview/detail state whenever the active season filter changes so a
previously-expanded tile (kept by preferredActiveSeasonId) doesn't remain open
for a newly selected season; add a useEffect that watches activeSeasonFilterId
and selectedActiveSeasonId (or activeSeasonNumber) and calls the existing local
preview reset setter (e.g., clearPreview, setExpandedTileId, or equivalent state
used to track the detail/preview UI) to null/false; ensure you import useEffect
(and useState/useId if you add state) at top if not already present so the
preview state is cleared whenever active season filter or selectedActiveSeasonId
changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 97a269f4-4a90-422d-88a7-e984a603c669

📥 Commits

Reviewing files that changed from the base of the PR and between af8221b and 152d91f.

📒 Files selected for processing (10)
  • __tests__/components/user/collected/CollectedStatsSeasonTile.test.tsx
  • __tests__/components/user/collected/UserPageCollected.test.tsx
  • __tests__/components/user/collected/UserPageCollectedStats.test.tsx
  • components/user/collected/UserPageCollected.tsx
  • components/user/collected/UserPageCollectedStats.tsx
  • components/user/collected/stats/helpers.ts
  • components/user/collected/stats/subcomponents/CollectedStatsHeader.tsx
  • components/user/collected/stats/subcomponents/CollectedStatsSeasonTile.tsx
  • components/user/collected/stats/subcomponents/CollectedStatsSeasons.tsx
  • components/user/collected/stats/types.ts

Comment thread components/user/collected/stats/subcomponents/CollectedStatsSeasonTile.tsx Outdated
Comment thread components/user/collected/UserPageCollected.tsx Outdated
Comment thread components/user/collected/UserPageCollectedStats.tsx
Signed-off-by: ragnep <ragneinfo@gmail.com>
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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/user/collected/UserPageCollected.tsx`:
- Around line 304-325: setCollection and setCollectionShortcut only update
URL/search params, causing local filters (used by UserPageCollectedStats) to
remain stale; before calling updateFields(...) call the local state setter
(setFilters) to mirror the new collection and also clear filters.szn when the
collection is being reset (i.e., collection === null), then proceed to call
updateFields(getCollectionUpdateItems({ collection, allowToggle: true })); apply
this change in both setCollection and setCollectionShortcut so UI reads the
updated filters immediately.
- Around line 327-343: The season shortcut currently checks only
filters.initialSznId so it ignores any locally staged selection; in
setSeasonShortcut replace the comparison with the optimistic id (filters.szn?.id
?? filters.initialSznId) to decide isActiveSeasonShortcut, and when applying the
shortcut also stage the chosen season into the optimistic filters state so the
UI updates immediately (i.e., update the same filters.szn or equivalent staged
filter alongside calling updateFields); reference setSeasonShortcut and
filters.szn to locate where to change the comparison and where to stage the
optimistic value.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0ac6cc4c-68b0-4b4c-89e6-883fa82df25d

📥 Commits

Reviewing files that changed from the base of the PR and between d1b9f54 and ed4fe97.

📒 Files selected for processing (6)
  • __tests__/components/user/collected/CollectedStatsSeasonTile.test.tsx
  • __tests__/components/user/collected/UserPageCollected.test.tsx
  • __tests__/components/user/collected/UserPageCollectedStats.test.tsx
  • components/user/collected/UserPageCollected.tsx
  • components/user/collected/UserPageCollectedStats.tsx
  • components/user/collected/stats/subcomponents/CollectedStatsSeasonTile.tsx

Comment thread components/user/collected/UserPageCollected.tsx
Comment thread components/user/collected/UserPageCollected.tsx
Signed-off-by: ragnep <ragneinfo@gmail.com>
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.

Actionable comments posted: 1

♻️ Duplicate comments (3)
components/user/collected/UserPageCollected.tsx (2)

403-442: ⚠️ Potential issue | 🟠 Major

Shortcut handlers still skip the optimistic filters state.

UserPageCollectedStats now renders pressed state from local filters, but setCollection*() and setSeasonShortcut() only mutate the URL. Until the search-param round trip completes, the header state and cards query still read stale local values, and setSeasonShortcut() still decides “already active” from URL state instead of the staged local season. Mirror the collection/szn changes into setFilters() first, including clearing any staged season when the collection is reset, then call updateFields(...).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/user/collected/UserPageCollected.tsx` around lines 403 - 442,
setCollection, setCollectionShortcut and setSeasonShortcut currently only call
updateFields and leave the local filters state stale; before calling
updateFields, call setFilters(...) to mirror the intended changes into the local
filters so UI/press states read the staged values. Specifically, in
setCollection and setCollectionShortcut update filters.collection to the new
collection (and clear filters.initialSznId when collection is set to null), and
in setSeasonShortcut compute the intended collection and season using the
existing filters plus the new season, update filters.collection and
filters.initialSznId accordingly (clearing staged season when collection is
reset), then call updateFields(getCollectionUpdateItems(...)) as before. Make
sure to use the same allowToggle/value logic used to build
getCollectionUpdateItems so the optimistic UI matches the URL update.

689-690: ⚠️ Potential issue | 🟡 Minor

?? masks an optimistic clear.

After setSzn(null), filters.szn is intentionally cleared, but this expression immediately falls back to the old initialSznId until the router update lands. The cards query clears right away while the stats shortcut stays pressed. This needs a staged season id/sentinel in local state instead of deriving the active value with ??.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/user/collected/UserPageCollected.tsx` around lines 689 - 690, The
activeSeasonNumber prop currently uses "filters.szn?.id ??
filters.initialSznId", which masks the intended optimistic clear; introduce a
local staged season sentinel in UserPageCollected (e.g., stagedSznId via
useState) and use that to drive activeSeasonNumber
(activeSeasonNumber={stagedSznId ?? filters.initialSznId}). Update the handlers
that call setSzn so that when clearing you set stagedSznId to null immediately
(so the UI reflects the cleared state) and when selecting a season you set
stagedSznId to the selected id (and let the router update filters.szn
asynchronously); keep filters.szn only as the canonical source from the router
and remove the "?? filters.szn" pattern.
components/user/collected/stats/subcomponents/CollectedStatsSeasonTile.tsx (1)

128-130: ⚠️ Potential issue | 🟡 Minor

Pointer clicks still preview before selecting.

When onSelect is present, a normal mouse click focuses the button before onClick, so onFocus={onPreview} still fires on the select path. That breaks the new preview-on-hover / select-on-click split in real browsers. Gate preview to keyboard focus, or only fall back to preview on click when onSelect is absent. Please verify with a real browser or userEvent.click, since fireEvent.click() will miss this sequence here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/user/collected/stats/subcomponents/CollectedStatsSeasonTile.tsx`
around lines 128 - 130, The preview is still triggered on mouse click because
onFocus={onPreview} runs before onClick when onSelect is present; change the
focus logic so preview only runs for keyboard focus or when no onSelect exists:
implement a short-lived pointer interaction flag (set onPointerDown/onTouchStart
and cleared after focus) and update the onFocus handler in
CollectedStatsSeasonTile to call onPreview only if onSelect is undefined OR the
focus was not preceded by a pointer interaction (i.e., keyboard-initiated
focus). Keep existing onMouseEnter/hasTouchScreen behavior unchanged and ensure
onClick/onSelect behavior remains the select path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/user/collected/UserPageCollected.tsx`:
- Line 212: getFilters() currently sets page using raw
Number.parseInt(pageParam, 10) which can produce NaN or non-positive values;
update getFilters() to normalize the parsed page: parse pageParam into a number,
if it's NaN or less than 1 set page to 1, otherwise use the parsed value. Ensure
this normalization mirrors the clamping logic in createQueryString() so the
initial query key/API request never uses NaN or 0; refer to getFilters(),
createQueryString(), and the pageParam variable when making the change.

---

Duplicate comments:
In `@components/user/collected/stats/subcomponents/CollectedStatsSeasonTile.tsx`:
- Around line 128-130: The preview is still triggered on mouse click because
onFocus={onPreview} runs before onClick when onSelect is present; change the
focus logic so preview only runs for keyboard focus or when no onSelect exists:
implement a short-lived pointer interaction flag (set onPointerDown/onTouchStart
and cleared after focus) and update the onFocus handler in
CollectedStatsSeasonTile to call onPreview only if onSelect is undefined OR the
focus was not preceded by a pointer interaction (i.e., keyboard-initiated
focus). Keep existing onMouseEnter/hasTouchScreen behavior unchanged and ensure
onClick/onSelect behavior remains the select path.

In `@components/user/collected/UserPageCollected.tsx`:
- Around line 403-442: setCollection, setCollectionShortcut and
setSeasonShortcut currently only call updateFields and leave the local filters
state stale; before calling updateFields, call setFilters(...) to mirror the
intended changes into the local filters so UI/press states read the staged
values. Specifically, in setCollection and setCollectionShortcut update
filters.collection to the new collection (and clear filters.initialSznId when
collection is set to null), and in setSeasonShortcut compute the intended
collection and season using the existing filters plus the new season, update
filters.collection and filters.initialSznId accordingly (clearing staged season
when collection is reset), then call updateFields(getCollectionUpdateItems(...))
as before. Make sure to use the same allowToggle/value logic used to build
getCollectionUpdateItems so the optimistic UI matches the URL update.
- Around line 689-690: The activeSeasonNumber prop currently uses
"filters.szn?.id ?? filters.initialSznId", which masks the intended optimistic
clear; introduce a local staged season sentinel in UserPageCollected (e.g.,
stagedSznId via useState) and use that to drive activeSeasonNumber
(activeSeasonNumber={stagedSznId ?? filters.initialSznId}). Update the handlers
that call setSzn so that when clearing you set stagedSznId to null immediately
(so the UI reflects the cleared state) and when selecting a season you set
stagedSznId to the selected id (and let the router update filters.szn
asynchronously); keep filters.szn only as the canonical source from the router
and remove the "?? filters.szn" pattern.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cf72e2c0-6718-4c9a-8614-a62fa12e9d5c

📥 Commits

Reviewing files that changed from the base of the PR and between ed4fe97 and c879144.

📒 Files selected for processing (7)
  • __tests__/components/user/collected/CollectedStatsSeasonTile.test.tsx
  • __tests__/components/user/collected/UserPageCollected.test.tsx
  • __tests__/components/user/collected/UserPageCollectedStats.test.tsx
  • components/user/collected/UserPageCollected.tsx
  • components/user/collected/stats/subcomponents/CollectedStatsSeasonTile.tsx
  • components/user/collected/stats/subcomponents/CollectedStatsSeasons.tsx
  • components/utils/select/dropdown/SeasonsGridDropdown.tsx

Comment thread components/user/collected/UserPageCollected.tsx Outdated
Signed-off-by: ragnep <ragneinfo@gmail.com>
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.

Actionable comments posted: 1

♻️ Duplicate comments (1)
components/user/collected/UserPageCollected.tsx (1)

212-212: ⚠️ Potential issue | 🟡 Minor

Normalize non-positive page values in getFilters().

This line still allows non-positive page values through. A URL like ?page=0 or ?page=-1 would store these values in filters, potentially causing invalid API requests before the URL rewrite occurs.

🛡️ Proposed fix
-      page: pageParam ? Number.parseInt(pageParam, 10) : 1,
+      page: Math.max(1, pageParam ? Number.parseInt(pageParam, 10) || 1 : 1),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/user/collected/UserPageCollected.tsx` at line 212, The
getFilters() function currently sets page using pageParam ?
Number.parseInt(pageParam, 10) : 1 which allows 0 or negative pages; change the
logic to parse pageParam into an integer (use Number.parseInt or
Number.parseInt(pageParam, 10)), then normalize by checking isNaN(parsed) ||
parsed < 1 and defaulting to 1; assign the normalized value to the page field so
page is always a positive integer before being stored in filters or used in API
calls.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/user/collected/UserPageCollected.tsx`:
- Around line 252-254: The page value is normalized for NaN but not clamped to a
minimum of 1 in createQueryString(); update createQueryString() so any parsed
page (from pageParam / parsedPage) is coerced to at least 1 (e.g., use
Math.max(1, parsedPage) or equivalent) before serializing, mirroring the
normalization used in getFilters(); reference the pageParam, parsedPage and page
variables and ensure the final page written into the query string is >= 1.

---

Duplicate comments:
In `@components/user/collected/UserPageCollected.tsx`:
- Line 212: The getFilters() function currently sets page using pageParam ?
Number.parseInt(pageParam, 10) : 1 which allows 0 or negative pages; change the
logic to parse pageParam into an integer (use Number.parseInt or
Number.parseInt(pageParam, 10)), then normalize by checking isNaN(parsed) ||
parsed < 1 and defaulting to 1; assign the normalized value to the page field so
page is always a positive integer before being stored in filters or used in API
calls.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bdb8a708-a329-4c56-b614-3c268237b8a0

📥 Commits

Reviewing files that changed from the base of the PR and between c879144 and 1979c28.

📒 Files selected for processing (2)
  • __tests__/components/user/collected/UserPageCollected.test.tsx
  • components/user/collected/UserPageCollected.tsx

Comment thread components/user/collected/UserPageCollected.tsx Outdated
ragnep added 3 commits March 11, 2026 14:34
Signed-off-by: ragnep <ragneinfo@gmail.com>
Signed-off-by: ragnep <ragneinfo@gmail.com>
Signed-off-by: ragnep <ragneinfo@gmail.com>
@sonarqubecloud
Copy link
Copy Markdown

@ragnep ragnep merged commit 298e9b8 into main Mar 12, 2026
7 checks passed
@ragnep ragnep deleted the szn-buttons branch March 12, 2026 06:13
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.

2 participants