Skip to content

feat: fix playlist cross-board climbs, shared MultiboardClimbList, playlist follows#879

Merged
marcodejongh merged 3 commits intomainfrom
claude/fix-playlist-cross-board-climbs-9hNKo
Mar 1, 2026
Merged

feat: fix playlist cross-board climbs, shared MultiboardClimbList, playlist follows#879
marcodejongh merged 3 commits intomainfrom
claude/fix-playlist-cross-board-climbs-9hNKo

Conversation

@marcodejongh
Copy link
Owner

Playlists containing climbs from multiple board types now render correctly
instead of showing "Not showing X climbs from other layouts". This brings
playlists to feature parity with the setter page's multi-board support.

Key changes:

  • Backend: Add all-boards mode to playlistClimbs resolver (omit boardName
    to query across all board types); fix board filter in setterClimbsFull
    to also filter by layoutId and size edges, not just boardType
  • Database: Add playlist_follows table for playlist follow feature
  • Frontend: Extract shared useBoardDetailsMap hook and MultiboardClimbList
    component used by both setter and playlist pages
  • Frontend: Refactor SetterClimbList to delegate rendering to shared component
  • Frontend: Rewrite PlaylistDetailContent for multi-board rendering with
    board filter, follow button, and no cross-layout filtering
  • Frontend: Refactor SessionDetailContent to use shared hook
  • Tests: Add playlist follow mutation tests and useBoardDetailsMap hook tests

https://claude.ai/code/session_01YGdgG2kDYVJhhg4yHfLUYH

…aylist follows

Playlists containing climbs from multiple board types now render correctly
instead of showing "Not showing X climbs from other layouts". This brings
playlists to feature parity with the setter page's multi-board support.

Key changes:
- Backend: Add all-boards mode to playlistClimbs resolver (omit boardName
  to query across all board types); fix board filter in setterClimbsFull
  to also filter by layoutId and size edges, not just boardType
- Database: Add playlist_follows table for playlist follow feature
- Frontend: Extract shared useBoardDetailsMap hook and MultiboardClimbList
  component used by both setter and playlist pages
- Frontend: Refactor SetterClimbList to delegate rendering to shared component
- Frontend: Rewrite PlaylistDetailContent for multi-board rendering with
  board filter, follow button, and no cross-layout filtering
- Frontend: Refactor SessionDetailContent to use shared hook
- Tests: Add playlist follow mutation tests and useBoardDetailsMap hook tests

https://claude.ai/code/session_01YGdgG2kDYVJhhg4yHfLUYH
@vercel
Copy link

vercel bot commented Mar 1, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
boardsesh Building Building Preview, Comment Mar 1, 2026 0:35am

Request Review

@chatgpt-codex-connector
Copy link

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@claude
Copy link

claude bot commented Mar 1, 2026

Claude Review

Ready to merge - No significant issues found. This is a well-structured PR with good test coverage for the new playlist follow feature.

Minor Notes

  1. Missing foreign key reference in migration - packages/db/drizzle/0061_silky_cassandra_nova.sql:3-4: The playlist_uuid column references playlist UUIDs but has no foreign key constraint to playlists.uuid. This is intentional for soft-delete compatibility (playlist can be deleted while follow records remain), but worth noting this allows orphaned follows.

  2. Test coverage is good - Tests cover authentication, authorization (private playlist), and idempotency for follow/unfollow mutations. The useBoardDetailsMap hook tests are comprehensive.

  3. Documentation unchanged - No documentation updates needed; the changes do not affect any documented systems in docs/.

…ype input properly

- Add missing followerCount and isFollowedByMe fields to noopCreatePlaylist
  fallback in use-playlists.ts
- Update use-playlists.test.ts test fixtures to include the new required fields
- Type playlistClimbs query input as GetPlaylistClimbsInput instead of
  Record<string, unknown> in playlist-detail-content.tsx

https://claude.ai/code/session_01YGdgG2kDYVJhhg4yHfLUYH
@claude
Copy link

claude bot commented Mar 1, 2026

Claude Review

Ready to merge - Minor issues noted below, but nothing blocking.

Issues

  1. Missing FK on playlist_uuid (packages/db/drizzle/0061_silky_cassandra_nova.sql:4)

    • The playlist_follows table has FK from follower_id to users.id, but no FK from playlist_uuid to playlists.uuid. Orphaned follow records will persist if a playlist is deleted.
  2. Stale followerCount in list queries (packages/backend/src/graphql/resolvers/playlists/queries.ts:100,182)

    • myPlaylists and sharedPlaylists always return hardcoded followerCount: 0 and isFollowedByMe: false instead of querying actual values. Only the single playlist query fetches real counts.
  3. Stale followerCount on updatePlaylist (packages/backend/src/graphql/resolvers/playlists/mutations.ts:147-148)

    • Returns followerCount: 0 after update instead of actual count. Could cause UI flicker showing 0 followers briefly.

Test Coverage

  • Tests added for followPlaylist/unfollowPlaylist mutations
  • Tests added for useBoardDetailsMap hook
  • No test coverage for the new playlistClimbs all-boards mode (the boardName: undefined path)

Documentation

  • No documentation updates required; this feature isn't covered in existing docs

…add query tests

- Add FK constraint from playlist_follows.playlist_uuid → playlists.uuid
  with CASCADE delete to prevent orphaned follow records
- Extract shared getPlaylistFollowStats() helper for batch-fetching
  followerCount and isFollowedByMe across playlist lists
- Fix userPlaylists, allUserPlaylists, and single playlist query to use
  real follow stats instead of hardcoded followerCount: 0
- Fix updatePlaylist mutation to return actual followerCount after update
- Add tests: getPlaylistFollowStats helper, playlistClimbs all-boards mode,
  specific-board mode, pagination, access control

https://claude.ai/code/session_01YGdgG2kDYVJhhg4yHfLUYH
@claude
Copy link

claude bot commented Mar 1, 2026

Claude Review

Ready to merge - Well-structured implementation with good test coverage. Minor performance consideration noted below.

Performance Note

  • packages/backend/src/graphql/resolvers/playlists/queries.ts:598-604 - The all-boards mode uses a correlated subquery to find the most popular angle for each climb, which runs once per row. This matches the existing pattern in setterClimbsFull but could be slow for very large playlists. Consider caching or batch optimization if performance issues arise with playlists containing 100+ climbs.

What looks good

  • Clean extraction of useBoardDetailsMap hook with comprehensive tests
  • Proper database schema with indexes and foreign key constraints
  • Follow/unfollow mutations are idempotent (onConflictDoNothing)
  • GraphQL schema properly extended with followerCount/isFollowedByMe fields
  • Test coverage for mutations and hooks

@marcodejongh marcodejongh merged commit 5bd035f into main Mar 1, 2026
10 of 11 checks passed
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