feat(schedule): scope vote-chip filters to Everyone/Me/Group - #310
feat(schedule): scope vote-chip filters to Everyone/Me/Group#310chiptus wants to merge 8 commits into
Conversation
Adds a Me ↔ Active Group toggle alongside the Schedule tab's vote-type filter chips, independent of the Artists tab's Vote Perspective. Reuses resolveVotesForScope on each set's full vote list (already fetched with sets) instead of the prior current-user-only votes query, and adds a voteScope URL param so shared filter links preserve the choice. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012xAfdayZzwNNJ8EGap3Rix
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
Adds a Me ↔ Active Group Vote Scope toggle for the Schedule tab’s vote filter chips, persisting the selection via a voteScope URL param and updating schedule filtering to respect the chosen scope.
Changes:
- Introduces Schedule-specific vote scope state (
voteScope=me|group) and UI toggles for both timeline and list toolbars / filter sheet. - Updates schedule filtering to evaluate votes from
set.votesbased on scope (me vs group members). - Extends URL search schema + url-state hook and updates unit tests for the new vote-scope behavior.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/routes/festivals/$festivalSlug/editions/$editionSlug/schedule/timeline.tsx | Uses schedule vote scope (me/group) when filtering timeline schedule days. |
| src/routes/festivals/$festivalSlug/editions/$editionSlug/schedule/list.tsx | Uses schedule vote scope (me/group) when filtering list schedule day groups. |
| src/pages/EditionView/tabs/ScheduleTab/VoteScopeToggle.tsx | Adds the underlying “Me / Group” toggle UI component. |
| src/pages/EditionView/tabs/ScheduleTab/ScheduleVoteScopeToggle.tsx | Wires auth + schedule vote scope hook into the toggle, hiding it when unavailable. |
| src/pages/EditionView/tabs/ScheduleTab/ScheduleFilterSheet.tsx | Adds the vote scope toggle next to vote filter chips in the mobile filter sheet. |
| src/pages/EditionView/tabs/ScheduleTab/list/ListDayGroup.tsx | Adds the vote scope toggle next to vote chips in the list header toolbar (md+). |
| src/pages/EditionView/tabs/ScheduleTab/horizontal/TimelineToolbar.tsx | Adds the vote scope toggle next to vote chips in the timeline toolbar (md+). |
| src/lib/voteScope.ts | Adds MeGroupVoteScope type (me/group subset). |
| src/lib/searchSchemas.ts | Adds optional voteScope search param to timeline/list schedule routes. |
| src/lib/scheduleFilter.ts | Updates vote filtering to use scoped votes derived from set.votes + scope rules. |
| src/lib/scheduleFilter.test.ts | Updates tests to use set.votes and adds coverage for group-scope filtering behavior. |
| src/hooks/useTimelineUrlState.ts | Adds url-state read/write helpers for voteScope. |
| src/hooks/useScheduleVoteScope.ts | New hook resolving effective schedule vote scope + group member ids for filtering. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Rename mobile "My vote" label to scope-neutral "Vote", reuse a shared empty Set instead of allocating one per filtered set, and skip the group-members query when the resolved scope isn't "group". Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012xAfdayZzwNNJ8EGap3Rix
Playwright test resultsDetails
|
chiptus
left a comment
There was a problem hiding this comment.
Addressed all three review comments in f2d754a: renamed the mobile "My vote" label to scope-neutral "Vote", reused a shared empty Set instead of allocating one per filtered set, and gated the group-members query on the resolved scope being "group".
Generated by Claude Code
Uh oh!
There was an error while loading. Please reload this page.
Removes the Schedule-tab-local Vote Scope toggle and voteScope URL param. The navbar's Active Scope switcher already offers Everyone / Me / Active Group globally, so the vote-type filter chips now read that scope directly instead of duplicating it with a narrower, Schedule-only Me/Group control that didn't respond to the navbar. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012xAfdayZzwNNJ8EGap3Rix
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.
Suppressed comments (1)
src/hooks/useScheduleVoteScope.ts:26
groupMemberIdsbecomes an emptySetwhenmembersis an empty array (which can happen on errors or if RLS returns no rows). UndervoteScope: "group"this makes vote filtering exclusionary (no member IDs match), so selecting a vote chip can hide all sets instead of staying inert while members are unavailable.
const groupMemberIds = useMemo(
() =>
members ? new Set(members.map((member) => member.user_id)) : undefined,
[members],
);
Two signed-in users join one group; the voter casts a Must Go vote, then the viewer confirms the Must Go chip surfaces that set under Group scope, hides it under Me scope, and shows it again under Everyone scope, all via the navbar Active Scope switcher. Adds a data-testid to the switcher trigger and an addMemberToGroup test helper for multi-member group setup. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012xAfdayZzwNNJ8EGap3Rix
The desktop/mobile branch in selectMustGoChip used a one-shot isVisible() check right after a dropdown-menu interaction, which lost the race against the closing dropdown's transition and picked the mobile filter-sheet path on desktop, where the chips group doesn't exist. Swap it for a retrying waitFor(). Also drop the fixed "voter"/"viewer" email suffixes, which collided with themselves on Playwright's automatic retry and masked the real failure behind a 422 from the admin user-creation API. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012xAfdayZzwNNJ8EGap3Rix
Playwright test resultsDetails
|
Three scope switches plus a chip selection and several assertions in one test exceeded Playwright's 30s CI default under firefox, which tore the page down mid-click and surfaced a misleading "context has been closed" error instead of a plain timeout. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012xAfdayZzwNNJ8EGap3Rix
selectScope clicked the trigger and menuitem back-to-back across three consecutive scope switches. Reopening the dropdown before the previous instance finished closing could detach the target menuitem mid-click, exhausting Playwright's action retries. Wait for the menu to actually open before clicking and close before moving on. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012xAfdayZzwNNJ8EGap3Rix
Uh oh!
There was an error while loading. Please reload this page.
Per review feedback, drop data-testid="active-scope-switcher" and locate the button by its accessible name instead. Makes the aria-label unconditional (previously mobile-only) so the name is stable and available on desktop too. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012xAfdayZzwNNJ8EGap3Rix
Schedule tab's vote-type filter chips now respect the navbar's Active Scope switcher (Everyone / Me / Active Group) instead of a separate, Schedule-only Me/Group toggle. This removed the earlier
voteScopeURL param and the extra selector — the chips just read whatever scope is already active globally.Verification
Generated by Claude Code