Rebuild user game list pages in Laravel #348

Closed
opened 2026-06-01 21:53:19 -05:00 by Codex · 1 comment
Member

The user game list experience needs to be rebuilt in Laravel so users can view and manage the video games they are tracking by status.

This is core MyVideoGameList functionality: users need to see the games on their list, organized by status, and signed-in users need owner-only access to edit and remove their own list entries. The current Laravel checkout has game_lists persistence, status values, add/edit/delete controller logic, and profile/header links pointing to /list/{username}, but the public list routes and list page are not wired up. The Notion report says: "The game list link doesn't work to view the games in our list."

This issue incorporates #59, which covered lazy-loading user game list status tabs.

Source: https://www.notion.so/3702f7baaae48002b51addc1700d86ca

Scope

  • Public user list pages at /list/{username}.
  • Current signed-in user list shortcut at /list.
  • Status-tabbed list rendering for Playing, Replaying, Continuously Playing, Completed, On Hold, Dropped, and Plan to Play.
  • Active, non-deleted game_lists rows only.
  • Game and platform metadata needed for each visible row.
  • List row links to canonical game profile pages.
  • Owner-only edit/delete controls for the signed-in user's own list.
  • Guest and non-owner read-only list views.
  • Empty states for users or statuses with no games.
  • Status counts without hydrating every list entry on the initial request.
  • Lazy/status-scoped loading for large lists, including jimmyb-scale lists with hundreds of completed games.
  • Accessible no-JavaScript fallback and shareable status-tab URLs.
  • Existing Laravel/Tailwind site layout, including light/dark mode styling.

Acceptance Criteria

  • Visiting /list/{username} renders that user's public game list instead of a missing route or broken page.
  • Visiting /list as a guest redirects to login.
  • Visiting /list as an authenticated user renders the signed-in user's own list.
  • The default page render shows the Playing status first.
  • Users can switch to Replaying, Continuously Playing, Completed, On Hold, Dropped, and Plan to Play.
  • Status URLs or query parameters are shareable and can render a selected status directly.
  • JavaScript-enhanced tab switching loads status contents without a full page reload where practical.
  • Users without JavaScript can navigate between statuses through normal links.
  • Status counts are shown and exclude soft-deleted list rows.
  • List rows show useful compact metadata: game title, platform, ownership/status, rating, priority/difficulty/hours where present, started/finished dates where present, and game profile link.
  • Missing, disabled, deleted, or soft-deleted games do not break rendering and are excluded or handled with a clear safe fallback.
  • Owner views show edit/delete controls for the signed-in user's own entries.
  • Guest and non-owner views do not show edit/delete controls.
  • Existing add/edit/delete list entry behavior remains intact.
  • Large lists do not load every status group on the initial request.
  • The page avoids N+1 queries and performs acceptably for lists with 1,600+ entries.
  • Public profile and header "View List" links route to the rebuilt list page.
  • User-facing UI supports light/dark mode and follows existing Laravel/Tailwind patterns.

Test Coverage Required

  • Feature test that /list/{username} renders a public user list.
  • Feature test that /list redirects guests to login.
  • Feature test that /list renders the authenticated user's own list.
  • Feature tests for each supported status tab/query value.
  • Regression test that default list rendering shows Playing entries and does not render entries from other statuses in the initial content.
  • Regression test that status counts are correct and exclude soft-deleted rows.
  • Regression test that soft-deleted list rows are not rendered.
  • Regression test for missing/deleted/disabled game or platform data.
  • Feature test that list rows include canonical game links and compact metadata.
  • Feature test that empty statuses show a clear empty state.
  • Authorization tests proving edit/delete controls appear only for the owner.
  • Regression tests confirming owner-only update/delete policies still protect list mutations.
  • Performance-oriented test or query-count regression proving list rendering avoids N+1 queries and does not hydrate all statuses.
  • Run focused list tests with php artisan test --compact.
  • Run vendor/bin/pint --dirty --format agent before closing the issue if PHP files are changed.

Progress Checklist

  • game_lists table exists
  • GameList model exists
  • Game-list status values exist for Playing, Completed, On Hold, Dropped, Plan to Play, and Continuously Playing
  • Game-list rows store game, platform, rating, ownership, dates, hours, priority, difficulty, replay, and notes metadata
  • Game-list create/update/delete controller logic exists
  • Owner-only update/delete policy exists
  • Profile/header links reserve user list URLs
  • Add public /list/{username} route
  • Add authenticated /list current-user route
  • Build public list page shell and status-tab UI
  • Render Playing as the default status
  • Add Replaying status support from is_replaying = Y
  • Add status-scoped rendering/loading for Continuously Playing, Completed, On Hold, Dropped, and Plan to Play
  • Add shareable status URLs or query parameters
  • Add no-JavaScript fallback navigation
  • Add grouped status counts
  • Exclude soft-deleted list rows
  • Handle missing or unavailable related game/platform data safely
  • Show compact row metadata and canonical game links
  • Show owner-only edit/delete controls
  • Preserve existing list add/edit/delete behavior
  • Add tests for routes, status filtering, counts, empty states, authorization, metadata, and query efficiency
  • Confirm large lists render efficiently without sacrificing tab usability
The user game list experience needs to be rebuilt in Laravel so users can view and manage the video games they are tracking by status. This is core MyVideoGameList functionality: users need to see the games on their list, organized by status, and signed-in users need owner-only access to edit and remove their own list entries. The current Laravel checkout has `game_lists` persistence, status values, add/edit/delete controller logic, and profile/header links pointing to `/list/{username}`, but the public list routes and list page are not wired up. The Notion report says: "The game list link doesn't work to view the games in our list." This issue incorporates #59, which covered lazy-loading user game list status tabs. Source: https://www.notion.so/3702f7baaae48002b51addc1700d86ca ## Scope - Public user list pages at `/list/{username}`. - Current signed-in user list shortcut at `/list`. - Status-tabbed list rendering for Playing, Replaying, Continuously Playing, Completed, On Hold, Dropped, and Plan to Play. - Active, non-deleted `game_lists` rows only. - Game and platform metadata needed for each visible row. - List row links to canonical game profile pages. - Owner-only edit/delete controls for the signed-in user's own list. - Guest and non-owner read-only list views. - Empty states for users or statuses with no games. - Status counts without hydrating every list entry on the initial request. - Lazy/status-scoped loading for large lists, including `jimmyb`-scale lists with hundreds of completed games. - Accessible no-JavaScript fallback and shareable status-tab URLs. - Existing Laravel/Tailwind site layout, including light/dark mode styling. ## Acceptance Criteria - Visiting `/list/{username}` renders that user's public game list instead of a missing route or broken page. - Visiting `/list` as a guest redirects to login. - Visiting `/list` as an authenticated user renders the signed-in user's own list. - The default page render shows the Playing status first. - Users can switch to Replaying, Continuously Playing, Completed, On Hold, Dropped, and Plan to Play. - Status URLs or query parameters are shareable and can render a selected status directly. - JavaScript-enhanced tab switching loads status contents without a full page reload where practical. - Users without JavaScript can navigate between statuses through normal links. - Status counts are shown and exclude soft-deleted list rows. - List rows show useful compact metadata: game title, platform, ownership/status, rating, priority/difficulty/hours where present, started/finished dates where present, and game profile link. - Missing, disabled, deleted, or soft-deleted games do not break rendering and are excluded or handled with a clear safe fallback. - Owner views show edit/delete controls for the signed-in user's own entries. - Guest and non-owner views do not show edit/delete controls. - Existing add/edit/delete list entry behavior remains intact. - Large lists do not load every status group on the initial request. - The page avoids N+1 queries and performs acceptably for lists with 1,600+ entries. - Public profile and header "View List" links route to the rebuilt list page. - User-facing UI supports light/dark mode and follows existing Laravel/Tailwind patterns. ## Test Coverage Required - Feature test that `/list/{username}` renders a public user list. - Feature test that `/list` redirects guests to login. - Feature test that `/list` renders the authenticated user's own list. - Feature tests for each supported status tab/query value. - Regression test that default list rendering shows Playing entries and does not render entries from other statuses in the initial content. - Regression test that status counts are correct and exclude soft-deleted rows. - Regression test that soft-deleted list rows are not rendered. - Regression test for missing/deleted/disabled game or platform data. - Feature test that list rows include canonical game links and compact metadata. - Feature test that empty statuses show a clear empty state. - Authorization tests proving edit/delete controls appear only for the owner. - Regression tests confirming owner-only update/delete policies still protect list mutations. - Performance-oriented test or query-count regression proving list rendering avoids N+1 queries and does not hydrate all statuses. - Run focused list tests with `php artisan test --compact`. - Run `vendor/bin/pint --dirty --format agent` before closing the issue if PHP files are changed. ## Progress Checklist - [x] `game_lists` table exists - [x] `GameList` model exists - [x] Game-list status values exist for Playing, Completed, On Hold, Dropped, Plan to Play, and Continuously Playing - [x] Game-list rows store game, platform, rating, ownership, dates, hours, priority, difficulty, replay, and notes metadata - [x] Game-list create/update/delete controller logic exists - [x] Owner-only update/delete policy exists - [x] Profile/header links reserve user list URLs - [x] Add public `/list/{username}` route - [x] Add authenticated `/list` current-user route - [x] Build public list page shell and status-tab UI - [x] Render Playing as the default status - [x] Add Replaying status support from `is_replaying = Y` - [x] Add status-scoped rendering/loading for Continuously Playing, Completed, On Hold, Dropped, and Plan to Play - [x] Add shareable status URLs or query parameters - [x] Add no-JavaScript fallback navigation - [x] Add grouped status counts - [x] Exclude soft-deleted list rows - [x] Handle missing or unavailable related game/platform data safely - [x] Show compact row metadata and canonical game links - [x] Show owner-only edit/delete controls - [x] Preserve existing list add/edit/delete behavior - [x] Add tests for routes, status filtering, counts, empty states, authorization, metadata, and query efficiency - [x] Confirm large lists render efficiently without sacrificing tab usability
jimmyb self-assigned this 2026-06-01 23:56:53 -05:00
Author
Member

Completed and pushed the user game list rebuild on dev.

Implementation notes:

  • Added /list and /list/{username} routes with owner-aware rendering and read-only public/non-owner views.
  • Built the status-tab list UI for Playing, Replaying, Continuously Playing, Completed, On Hold, Dropped, Plan to Play, and All.
  • Playing renders on the initial response; non-playing tabs lazy-load and cache per page load.
  • Tab anchors use query-string URLs for no-JS fallback, while JS-enhanced navigation uses hash URLs and partial fetches.
  • All renders grouped sections and now caps each section at 100 rows with cursor-based Load More controls, so large statuses do not dump the whole list into one response.
  • Added list-performance indexes, including game_lists_user_status_deleted_name_index and game_lists_user_deleted_name_id_index; both were run against .env.local.
  • Preserved and tightened add/edit/delete behavior: duplicate active list entries are blocked, owner spoofing on add is ignored, and update/delete remain owner-policy protected.
  • Added the reusable Game Information card to add/edit list-entry pages.

Verification:

  • vendor/bin/pint --dirty --format agent
  • php artisan test --compact tests/Feature/GameListPageTest.php passed with 30 tests / 294 assertions
  • npm run build

Schema note: the current Laravel schema does not appear to have a separate disabled-games flag, so unavailable game handling is covered through soft-deleted games plus safe platform fallback.

Completed and pushed the user game list rebuild on `dev`. Implementation notes: - Added `/list` and `/list/{username}` routes with owner-aware rendering and read-only public/non-owner views. - Built the status-tab list UI for Playing, Replaying, Continuously Playing, Completed, On Hold, Dropped, Plan to Play, and All. - Playing renders on the initial response; non-playing tabs lazy-load and cache per page load. - Tab anchors use query-string URLs for no-JS fallback, while JS-enhanced navigation uses hash URLs and partial fetches. - All renders grouped sections and now caps each section at 100 rows with cursor-based Load More controls, so large statuses do not dump the whole list into one response. - Added list-performance indexes, including `game_lists_user_status_deleted_name_index` and `game_lists_user_deleted_name_id_index`; both were run against `.env.local`. - Preserved and tightened add/edit/delete behavior: duplicate active list entries are blocked, owner spoofing on add is ignored, and update/delete remain owner-policy protected. - Added the reusable Game Information card to add/edit list-entry pages. Verification: - `vendor/bin/pint --dirty --format agent` - `php artisan test --compact tests/Feature/GameListPageTest.php` passed with 30 tests / 294 assertions - `npm run build` Schema note: the current Laravel schema does not appear to have a separate disabled-games flag, so unavailable game handling is covered through soft-deleted games plus safe platform fallback.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
MyVideoGameList/myvideogamelist.com#348
No description provided.