fix spec review issues: add missing files, clarify DB migration, use Zod schemas
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,21 +8,23 @@
|
|||||||
|
|
||||||
## 1. Entry Data Model
|
## 1. Entry Data Model
|
||||||
|
|
||||||
Replace the current country-only lineup with full ESC entries:
|
Replace the current country-only lineup with full ESC entries (shown as Zod schemas, matching codebase conventions):
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
type Entry = {
|
const entrySchema = z.object({
|
||||||
country: { code: string; name: string; flag: string }
|
country: z.object({ code: z.string(), name: z.string(), flag: z.string() }),
|
||||||
artist: string
|
artist: z.string(),
|
||||||
song: string
|
song: z.string(),
|
||||||
}
|
})
|
||||||
|
|
||||||
type Lineup = {
|
const lineupSchema = z.object({
|
||||||
year: number
|
year: z.number(),
|
||||||
entries: Entry[]
|
entries: z.array(entrySchema),
|
||||||
}
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note: The existing `countrySchema` gains a `flag` field — this is a breaking change to the country object shape throughout the codebase.
|
||||||
|
|
||||||
The data file changes from `esc-2026.json` to `esc-2025.json` using real ESC 2025 entries for testing. Each entry includes the flag emoji in the data file.
|
The data file changes from `esc-2026.json` to `esc-2025.json` using real ESC 2025 entries for testing. Each entry includes the flag emoji in the data file.
|
||||||
|
|
||||||
Display format everywhere: `🇩🇪 Abor — Süden`
|
Display format everywhere: `🇩🇪 Abor — Süden`
|
||||||
@@ -58,8 +60,8 @@ type Prediction = {
|
|||||||
**Bottom section — scrollable entry list:**
|
**Bottom section — scrollable entry list:**
|
||||||
- All entries from the lineup
|
- All entries from the lineup
|
||||||
- Already-assigned entries are dimmed/disabled
|
- Already-assigned entries are dimmed/disabled
|
||||||
- Tapping an unassigned entry shows a small picker with only unfilled slots (1st/2nd/3rd/Last)
|
- Tapping an unassigned entry shows a popover with only unfilled slot options (1st/2nd/3rd/Last)
|
||||||
- After selecting a slot, the entry fills that slot and dims in the list
|
- After selecting a slot, the entry fills that slot, the popover closes, and the entry dims in the list
|
||||||
|
|
||||||
**Submit button:** Appears when all 4 slots are filled. After submission or when predictions are locked, the UI becomes read-only showing assigned entries in their slots.
|
**Submit button:** Appears when all 4 slots are filled. After submission or when predictions are locked, the UI becomes read-only showing assigned entries in their slots.
|
||||||
|
|
||||||
@@ -87,11 +89,12 @@ Strip the entire Dish of the Nation feature:
|
|||||||
|
|
||||||
## 5. Player List — Prediction Checkmark
|
## 5. Player List — Prediction Checkmark
|
||||||
|
|
||||||
Add prediction submission status to the player state broadcast:
|
Add prediction submission status to the game state broadcast:
|
||||||
|
|
||||||
- Server: When building room state or game state, include `hasSubmittedPrediction: boolean` per player by checking if a prediction exists in the GameManager
|
- Shared: Add `predictionSubmitted: Map<playerId, boolean>` (or equivalent) to `gameStateSchema` in `game-types.ts`. This lives on the game state, not the player schema, since it's game-specific data.
|
||||||
- Client: Player list component renders a checkmark icon (✓) next to player names that have submitted predictions
|
- Server: When building game state in `GameManager.getGameStateForPlayer()` / `getGameStateForDisplay()`, include which players have submitted predictions.
|
||||||
- Visible on all views (play, host, display)
|
- Client: `player-list.tsx` reads from game state and renders a checkmark icon (✓) next to player names that have submitted predictions.
|
||||||
|
- Visible on all views (play, host, display).
|
||||||
|
|
||||||
## 6. Acts Naming
|
## 6. Acts Naming
|
||||||
|
|
||||||
@@ -113,6 +116,8 @@ Host control buttons: "Start Pre-Show", "Start Live Event", "Start Scoring", "En
|
|||||||
|
|
||||||
Predictions lock when advancing from Pre-Show to Live Event (previously act1 → act2).
|
Predictions lock when advancing from Pre-Show to Live Event (previously act1 → act2).
|
||||||
|
|
||||||
|
**DB migration:** The Postgres `actEnum` must be updated from `["lobby", "act1", "act2", "act3", "ended"]` to `["lobby", "pre-show", "live-event", "scoring", "ended"]`. Since there is no production data to preserve, drop and recreate the enum (via Drizzle `push` or a migration). The `predictions` table columns also change from `predictedWinner/top3/nulPointsPick` to `first/second/third/last` — same approach, drop and recreate.
|
||||||
|
|
||||||
## 7. Lobby Code — Copy to Clipboard
|
## 7. Lobby Code — Copy to Clipboard
|
||||||
|
|
||||||
On the display view (and anywhere the room code is shown prominently):
|
On the display view (and anywhere the room code is shown prominently):
|
||||||
@@ -141,7 +146,7 @@ Predictions lock on `pre-show → live-event` transition.
|
|||||||
## Files Affected
|
## Files Affected
|
||||||
|
|
||||||
### Modified
|
### Modified
|
||||||
- `packages/shared/src/game-types.ts` — entry type, prediction model
|
- `packages/shared/src/game-types.ts` — entry/lineup schemas, prediction model, add predictionSubmitted to game state
|
||||||
- `packages/shared/src/ws-messages.ts` — remove dish messages, update prediction message
|
- `packages/shared/src/ws-messages.ts` — remove dish messages, update prediction message
|
||||||
- `packages/shared/src/constants.ts` — act names
|
- `packages/shared/src/constants.ts` — act names
|
||||||
- `packages/server/data/` — replace `esc-2026.json` with `esc-2025.json`
|
- `packages/server/data/` — replace `esc-2026.json` with `esc-2025.json`
|
||||||
@@ -149,12 +154,13 @@ Predictions lock on `pre-show → live-event` transition.
|
|||||||
- `packages/server/src/games/game-service.ts` — remove dish persistence, update prediction columns
|
- `packages/server/src/games/game-service.ts` — remove dish persistence, update prediction columns
|
||||||
- `packages/server/src/rooms/room-manager.ts` — act name references
|
- `packages/server/src/rooms/room-manager.ts` — act name references
|
||||||
- `packages/server/src/ws/handler.ts` — remove dish handlers, update prediction handler
|
- `packages/server/src/ws/handler.ts` — remove dish handlers, update prediction handler
|
||||||
- `packages/server/src/db/schema.ts` — remove dish tables, update prediction columns
|
- `packages/server/src/db/schema.ts` — remove dish tables, update prediction columns, update actEnum values
|
||||||
- `packages/server/tests/game-manager.test.ts` — rewrite for new model
|
- `packages/server/tests/game-manager.test.ts` — rewrite for new model
|
||||||
- `packages/server/tests/ws-handler.test.ts` — update for changed messages
|
- `packages/server/tests/ws-handler.test.ts` — update for changed messages
|
||||||
- `packages/client/src/stores/room-store.ts` — remove dish state, update game state shape
|
- `packages/client/src/stores/room-store.ts` — remove dish state, update game state shape
|
||||||
- `packages/client/src/hooks/use-websocket.ts` — remove dish handlers
|
- `packages/client/src/hooks/use-websocket.ts` — remove dish handlers
|
||||||
- `packages/client/src/components/predictions-form.tsx` — rewrite as tap-to-assign
|
- `packages/client/src/components/predictions-form.tsx` — rewrite as tap-to-assign
|
||||||
|
- `packages/client/src/components/player-list.tsx` — add prediction checkmark
|
||||||
- `packages/client/src/routes/play.$roomCode.tsx` — remove dish UI
|
- `packages/client/src/routes/play.$roomCode.tsx` — remove dish UI
|
||||||
- `packages/client/src/routes/host.$roomCode.tsx` — remove dish UI
|
- `packages/client/src/routes/host.$roomCode.tsx` — remove dish UI
|
||||||
- `packages/client/src/routes/display.$roomCode.tsx` — remove dish UI, add copy-to-clipboard
|
- `packages/client/src/routes/display.$roomCode.tsx` — remove dish UI, add copy-to-clipboard
|
||||||
|
|||||||
Reference in New Issue
Block a user