feat(front): put the dead ends on a DeadEndPage with a board to play on #559

Merged
root merged 1 commit from claude/eager-wilbur-560d0a into main 2026-10-19 16:05:08 +00:00
root commented 2026-10-19 15:39:09 +00:00 (Migrated from gitlab.core-project.space)

Summary

Game not found, Player not found, the unknown address and the router's error screen move onto a new page template, DeadEndPage. Each one shows a heading, the reason, the address asked for when it helps, and the ways onward, beside a board where the Player can play a whole game alone. The two password-recovery notices become a notice state of AuthPage.

 design-system/
+├── dead-end-page.tsx      # DeadEndPage
+├── page-action.tsx        # PageAction (link | reload) and its button, shared with AuthPage's notice
 game/components/
+├── playable-board.tsx     # Board + click/drag/promotion + marks, driven by the caller's Game
+├── free-board.tsx         # both colours from the start, ending line, Play again; useState only
 auth/components/
-├── auth-notice.tsx
 ├── auth-page.tsx          # + notice state: heading (focused), status, primary action
 ├── morphy-finish.tsx      # now a scripted use of PlayableBoard
 games/components/
-├── not-found.tsx
<DeadEndPage heading reason asked? primary secondary? isFailure? board>
  text column (first on a phone)      board panel (bg-primary, left from lg)
  ├─ [role=alert if failure] h2, reason   <FreeBoard>
  ├─ "You asked for <code>"                 <PlayableBoard game movableBy=turn>
  └─ primary button, secondary button       status line + Play again
Screen Address asked for Ways onward
Game not found /games/<id> My games, Home
Player not found /players/<username> Home
Unknown address none Home
Error screen none (an alert) Try again (full reload), Home

The test harness's own PlayableBoard (in board.harness.tsx) is now BoardInPlay, a thin wrapper over the real PlayableBoard, so one name means one thing.

Evidence

  • Before: each dead end showed a short line on an empty page (the layout audit in spec #450). The recovery notices replaced AuthPage with a narrow column.
    After: in the dev stack, each screen was checked at 1280 and 390 px, and Game not found at 1920 px too:
Screen 1280 px 390 px
Game not found 1280 390
Game not found, 1920 px 1920
Board ended (Fool's mate, French) ended
Error screen, API down (French) error
Player not found player
Unknown address unknown unknown 390
Reset link sent (heading focused) sent sent 390
Reset link invalid invalid
  • View tests: app/dead-ends.test.tsx (new: the unknown address, the error screen, the free board's checkmate, threefold draw, promotion, Play again and French copy), plus additions to game-page-route, profile-route, forgot-password and reset-password. Morphy's finish tests in sign-in.test.tsx pass unchanged.
  • e2e: apps/e2e/tests/dead-ends.spec.ts. It opens an unknown Game link, plays e4 and follows My games. It also covers Try again's full reload: the Game read is aborted, then the route is removed and Try again pressed. A full reload cannot be clicked inside Vitest's browser iframe, so this check lives in e2e.
  • Gate: pnpm lint, typecheck, test, build, format:check all green.

Merge Danger

Door: two-way

Blast Radius: layout

These four screens and the two recovery notices change. Two tests that asserted "no board" on a not-found or error page now check for no Game page or Room layout instead.

Proposed rule change (not committed)

Rule 8 of apps/front/CODING_STANDARDS.md, add a fifth template:

    - `AuthPage`: a sign-in, sign-up or password form, with its pitch and board.
    - The home's doors, each under a `LandingHeading`: an entry into an activity.
+   - `DeadEndPage`: an address that leads nowhere, or a failure: a heading, why, the way onward, and a board to play on.

Changing the rule is the owner's call, in a dedicated MR (CLAUDE.md).

Review notes

  • game_play_again ("Play again" / "Rejouer") has the same text as room_play_again. It is a separate key because it names a different action: the free board starting over, not a Room's rematch.
  • Only the heading and the reason sit inside the error screen's alert. The address asked for and the actions stay outside it, as the old screen alerted its one line.

Follow-ups noticed

  • games/components/ now holds one file (game-row.tsx), below rule 2's two-file threshold for a role folder. Moving it to the vertical's root would collide with games/game-row.ts, so it is left as is.

Closes #458

## Summary Game not found, Player not found, the unknown address and the router's error screen move onto a new page template, `DeadEndPage`. Each one shows a heading, the reason, the address asked for when it helps, and the ways onward, beside a board where the Player can play a whole game alone. The two password-recovery notices become a notice state of `AuthPage`. ```diff design-system/ +├── dead-end-page.tsx # DeadEndPage +├── page-action.tsx # PageAction (link | reload) and its button, shared with AuthPage's notice game/components/ +├── playable-board.tsx # Board + click/drag/promotion + marks, driven by the caller's Game +├── free-board.tsx # both colours from the start, ending line, Play again; useState only auth/components/ -├── auth-notice.tsx ├── auth-page.tsx # + notice state: heading (focused), status, primary action ├── morphy-finish.tsx # now a scripted use of PlayableBoard games/components/ -├── not-found.tsx ``` ```text <DeadEndPage heading reason asked? primary secondary? isFailure? board> text column (first on a phone) board panel (bg-primary, left from lg) ├─ [role=alert if failure] h2, reason <FreeBoard> ├─ "You asked for <code>" <PlayableBoard game movableBy=turn> └─ primary button, secondary button status line + Play again ``` | Screen | Address asked for | Ways onward | | ---------------- | ---------------------- | ------------------------- | | Game not found | `/games/<id>` | **My games**, Home | | Player not found | `/players/<username>` | **Home** | | Unknown address | none | **Home** | | Error screen | none (an alert) | **Try again** (full reload), Home | The test harness's own `PlayableBoard` (in `board.harness.tsx`) is now `BoardInPlay`, a thin wrapper over the real `PlayableBoard`, so one name means one thing. ## Evidence - **Before:** each dead end showed a short line on an empty page (the layout audit in spec #450). The recovery notices replaced `AuthPage` with a narrow column. **After:** in the dev stack, each screen was checked at 1280 and 390 px, and Game not found at 1920 px too: | Screen | 1280 px | 390 px | | --- | --- | --- | | Game not found | ![1280](/uploads/4ebc01e0b5bbfeefc8e0bbca33055d15/mcp-Claude_Browser-blob-1792423831120-ztxa0j.jpg) | ![390](/uploads/c735e596d2628642eb0afc3b32168f90/mcp-Claude_Browser-blob-1792423831120-nwuqmn.jpg) | | Game not found, 1920 px | ![1920](/uploads/ffec6f87661db227dde0073400d258cd/mcp-Claude_Browser-blob-1792423831120-63qy85.jpg) | | | Board ended (Fool's mate, French) | ![ended](/uploads/6316129c755b71bbb85c39d0bdcf69ea/mcp-Claude_Browser-blob-1792423809112-ka8uhw.jpg) | | | Error screen, API down (French) | ![error](/uploads/f105c578fb7c75ffbc0f132a0706adf8/mcp-Claude_Browser-blob-1792423769917-fqiep6.jpg) | | | Player not found | ![player](/uploads/5af7dfc605676579f28c0f47d1cf8cde/mcp-Claude_Browser-blob-1792423842997-rqhs6q.jpg) | | | Unknown address | ![unknown](/uploads/7d82d3b52c6c726a7a6dbbff36c65ae5/mcp-Claude_Browser-blob-1792423842997-k418v7.jpg) | ![unknown 390](/uploads/e2b2d077b20cd7e67bf2cbd05b334740/mcp-Claude_Browser-blob-1792423856932-wamaat.jpg) | | Reset link sent (heading focused) | ![sent](/uploads/b463ff1e7c26698763134ce6bf949912/mcp-Claude_Browser-blob-1792423856932-vr1vtx.jpg) | ![sent 390](/uploads/ba72dc5ea327ae7c9c6b7b476dbc0aed/mcp-Claude_Browser-blob-1792423856932-rwdt5t.jpg) | | Reset link invalid | ![invalid](/uploads/31dd7c7d3e6002e0103b88e08c5eed75/mcp-Claude_Browser-blob-1792423842997-49qq3w.jpg) | | - View tests: `app/dead-ends.test.tsx` (new: the unknown address, the error screen, the free board's checkmate, threefold draw, promotion, Play again and French copy), plus additions to `game-page-route`, `profile-route`, `forgot-password` and `reset-password`. Morphy's finish tests in `sign-in.test.tsx` pass unchanged. - e2e: `apps/e2e/tests/dead-ends.spec.ts`. It opens an unknown Game link, plays e4 and follows My games. It also covers Try again's full reload: the Game read is aborted, then the route is removed and Try again pressed. A full reload cannot be clicked inside Vitest's browser iframe, so this check lives in e2e. - Gate: `pnpm lint`, `typecheck`, `test`, `build`, `format:check` all green. ## Merge Danger **Door:** two-way **Blast Radius:** layout These four screens and the two recovery notices change. Two tests that asserted "no board" on a not-found or error page now check for no Game page or Room layout instead. ## Proposed rule change (not committed) Rule 8 of `apps/front/CODING_STANDARDS.md`, add a fifth template: ```diff - `AuthPage`: a sign-in, sign-up or password form, with its pitch and board. - The home's doors, each under a `LandingHeading`: an entry into an activity. + - `DeadEndPage`: an address that leads nowhere, or a failure: a heading, why, the way onward, and a board to play on. ``` Changing the rule is the owner's call, in a dedicated MR (CLAUDE.md). ## Review notes - `game_play_again` ("Play again" / "Rejouer") has the same text as `room_play_again`. It is a separate key because it names a different action: the free board starting over, not a Room's rematch. - Only the heading and the reason sit inside the error screen's alert. The address asked for and the actions stay outside it, as the old screen alerted its one line. ## Follow-ups noticed - `games/components/` now holds one file (`game-row.tsx`), below rule 2's two-file threshold for a role folder. Moving it to the vertical's root would collide with `games/game-row.ts`, so it is left as is. Closes #458
project_1_bot_a8dd9262857d850eef8dca5206e61de5 commented 2026-10-19 15:48:24 +00:00 (Migrated from gitlab.core-project.space)

Screenshots

Before is production, after is this merge request's review app at 9e6fc7d.

Desktop

Page Before After
Home
Local game
Room

Mobile

Page Before After
Home
Local game
Room
<!-- chess-screenshots --> ### Screenshots Before is production, after is this merge request's review app at 9e6fc7d. #### Desktop | Page | Before | After | | --- | --- | --- | | Home | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/2127/artifacts/raw/review-screenshots/before/home-desktop.png" width="400"> | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/2127/artifacts/raw/review-screenshots/after/home-desktop.png" width="400"> | | Local game | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/2127/artifacts/raw/review-screenshots/before/local-desktop.png" width="400"> | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/2127/artifacts/raw/review-screenshots/after/local-desktop.png" width="400"> | | Room | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/2127/artifacts/raw/review-screenshots/before/room-desktop.png" width="400"> | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/2127/artifacts/raw/review-screenshots/after/room-desktop.png" width="400"> | #### Mobile | Page | Before | After | | --- | --- | --- | | Home | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/2127/artifacts/raw/review-screenshots/before/home-mobile.png" width="200"> | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/2127/artifacts/raw/review-screenshots/after/home-mobile.png" width="200"> | | Local game | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/2127/artifacts/raw/review-screenshots/before/local-mobile.png" width="200"> | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/2127/artifacts/raw/review-screenshots/after/local-mobile.png" width="200"> | | Room | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/2127/artifacts/raw/review-screenshots/before/room-mobile.png" width="200"> | <img src="https://gitlab.core-project.space/amaurycoudr/chess-project/-/jobs/2127/artifacts/raw/review-screenshots/after/room-mobile.png" width="200"> |
root (Migrated from gitlab.core-project.space) merged commit into main 2026-10-19 16:05:09 +00:00
Sign in to join this conversation.
No description provided.