Commit graph

19 commits

Author SHA1 Message Date
AyoubBenziza
1e5ef2be90 feat(web): i18n (FR/EN) — homemade typed dictionary
- lightweight, dependency-free i18n: typed fr/en dictionaries (fr is the source
  of truth, en must match its shape → compile error on drift), I18nProvider +
  useI18n hook, browser detection + localStorage persistence
- FR/EN language switcher (home + room header)
- translated the whole player-facing flow: home, join, pseudo, room shell,
  lobby (incl. settings, categories, bots, track submission, history),
  quiz, blindtest, player-cards, round transitions, end screen (podium, awards,
  tracks, rounds recap), and server-error messages (mapped by code)
- history dates localized to the active language

Content (questions/categories) intentionally left as-is. Back-office (admin)
not translated yet — internal, token-gated tool.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 19:03:28 +02:00
AyoubBenziza
47e5c2854e fix(web): center end-screen recap + shadcn tooltips
- results page: when there are no tracks (quiz-only game), the recap was sitting
  in the left column of a 2-col grid; now a single section is centered (2 columns
  only when both tracks and recap exist)
- add a shadcn Tooltip component (@workspace/ui, via radix-ui) and replace native
  browser title= tooltips: connection dot, back-office active toggle, and the
  locked blindtest tiles (now aria-disabled so the tooltip still triggers)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 18:17:47 +02:00
AyoubBenziza
f0c327617b feat: leave-room button
- room:leave event: removes the player from the room (not just disconnected),
  reassigns host if the host leaves, deletes the room when empty
- store leaveRoom() emits it and clears the session (reset)
- room header gets a "Quitter" button (always available); end-screen "Quitter"
  now also leaves cleanly

Verified e2e: leaver removed from snapshot, host reassigned to the next player.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 17:33:10 +02:00
AyoubBenziza
fa7c97c402 feat(web): richer desktop layout for end screen and back-office
- end screen: wider container (max-w-4xl), podium/awards stay centered, and the
  two long sections (musiques + récap des manches) sit side-by-side on desktop
- back-office: 2-column layout (form | questions list) on desktop, wider

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 15:24:34 +02:00
AyoubBenziza
879bc5b388 feat: per-submode mixed settings, fastest award, wider desktop layout
Mixed settings fix:
- RoundConfig carries a `pool` hint (quiz | image) per quiz round; lobby shows
  a separate count for each selected sub-mode (Quiz, Images) and the blindtest
  config — not just the quiz one
- server pool composes the queue per round's pool (quiz formats vs image_reveal),
  in order; verified e2e (2 quiz + 2 images honored)

Awards:
- " Le plus rapide" — derived client-side from the speed bonus baked into
  quiz/image points (points above the 100 base on correct answers)

Desktop restyle:
- room page gets an ambient halo background and a responsive container
  (lobby max-w-3xl with a 2-column players|settings grid, game/end max-w-lg)
- game/end views widened to max-w-lg

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 15:10:09 +02:00
AyoubBenziza
976ebf0799 feat(web): end-game awards, copy results, avatars in recap
- FunStats: award badges from the recap data — 🎯 Sans-faute, 🧠 Le cerveau
  (most correct), 🦹 Roi de la tromperie (blindtest decoy points), 🪨 Le boulet
  (0 correct). Shown with player avatars.
- "Copier les résultats" button: copies ranking + per-round answers to clipboard
- avatars next to each player in the round-by-round recap

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 01:11:06 +02:00
AyoubBenziza
331d375349 feat(web): recap polish — sort answers by points, highlight you, found count
- per round, answers sorted by points (then correct first)
- the local player's line is bolded with "(toi)"
- per-round "✓ X" badge showing how many got it right

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 01:05:14 +02:00
AyoubBenziza
f7ee2204d1 feat: round recap shows each player's answer
- shared: RoundRecap gains answers[] (RoundPlayerAnswer: text + correct)
- server: quiz/blindtest recap() build per-player answers (choice text / free
  text / blindtest guess formatted by mode), with correctness
- client: recap lists each player's answer per round, green/red by correctness,
  with their points when they scored

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 01:00:50 +02:00
AyoubBenziza
03a0dfa998 feat: end-of-game round recap (all rounds with answers + scorers)
- shared: RoundRecap (+ scorers); game:end carries recap[]
- server: GameRound.recap(ctx) per mode (quiz: prompt + correct answer +
  image; blindtest: "title — artist" + addedBy + links); engine accumulates a
  history per round (with that round's scorers from the score deltas) and sends
  it at game:end
- client: GameEndView shows a collapsible "Récapitulatif des manches" — each
  round's label, answer, media thumbnail (image/youtube) and who scored
- engine test dummy round implements recap

Verified e2e: game:end recap lists every round with answer + scorers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 00:54:40 +02:00
AyoubBenziza
db0100e272 feat(web): victory sound on the end screen (drop-in)
- lib/sound: plays src/assets/sounds/victory.{mp3,ogg,wav} if present,
  auto-detected via import.meta.glob; no-op when absent
- played alongside the confetti when the end screen appears
- README documenting where to drop the file

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 21:17:25 +02:00
AyoubBenziza
7093ce8cd9 feat(web): victory confetti on the end screen
canvas-confetti burst (center pop + side jets) fired once when the game-end
screen appears.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 17:54:23 +02:00
AyoubBenziza
3f36798207 feat(web): brand icons (Spotify/YouTube) via react-simple-icons
Add @icons-pack/react-simple-icons for brand logos lucide doesn't provide.
End-screen track recap now uses official SiSpotify (green) and SiYoutube (red)
icons instead of generic ones. Lucide stays for UI icons.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 17:35:20 +02:00
AyoubBenziza
c0a4340bae feat(web): Spotify export on the end screen (roadmap V1 step 8)
From the blindtest tracks revealed at game end:
- per-track Spotify search link (green button) built from "title artist"
- "Playlist" button copies the whole tracklist ("title — artist" per line)
  to the clipboard for pasting into Spotify
- YouTube open link kept alongside

Pure client-side, derived from the tracks already sent in game:end.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 17:31:38 +02:00
AyoubBenziza
3f0cab8f5f feat: end-of-game track recap, no self-vote in who_added, festive home + icons
- game:end now carries the played blindtest tracks (title/artist/youtubeId/
  url/submittedByName); the end screen lists them as cards with a YouTube
  open link so players can recover/export the songs
- who_added vote no longer lets you pick yourself (filtered out)
- home page: animated halo, floating geek emojis, springy gradient title,
  hover/tap on buttons (Framer Motion) + Lucide icons
- lobby settings get Lucide icons (game type, quiz, blindtest mode, tracks,
  start)

Verified e2e: game:end includes the track list with links.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 16:04:14 +02:00
AyoubBenziza
6251146c19 feat: replay from lobby, contributor mislead card, editable track cards
Return to lobby (replay without recreating the room):
- lobby:return (host): reset to lobby, scores to 0, keep players + tracks
- client: end screen has "Rejouer" (host) + "Quitter"; store clears transient
  game state whenever the room goes back to lobby

Contributor has nothing to input:
- round:start carries a private `mine: true` to the contributor only (via
  RoundStart.secretPlayerId targeted emit); they're excluded from eligible
  voters. Client shows a "fais-les se tromper" card instead of the vote form.

Editable track submission:
- submitTrack ack returns trackId + youtubeId; new blindtest:removeTrack
- lobby shows submitted tracks as cards (YouTube thumbnail + title) with delete

Verified e2e (3 players): add/remove, private mine flag, return-to-lobby reset.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 15:13:54 +02:00
AyoubBenziza
0c2534f3a4 feat(web): podium on the end screen + larger avatars
- GameEndView: top-3 podium — 2nd left, champion center (taller), 3rd right,
  with gold/silver/bronze pedestals, staggered rise-in (climax on the champion),
  crown + pulsing gold glow kept on #1; ranks 4+ listed below
- bigger avatars where they read too small: lobby (size-7→11) and in-game
  player cards (size-9→14, slightly wider cards)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 11:05:54 +02:00
AyoubBenziza
4f10d86fb0 feat(web): DiceBear lorelei avatars for players
- Avatar component using DiceBear 9.x lorelei, seeded by the player name
  (stable, recognizable across screens)
- shown in the lobby list, the in-game player cards (gold ring on leader),
  and the final leaderboard (large on the winner, small on runners-up)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 10:50:17 +02:00
AyoubBenziza
0c9eaca312 feat(web): glorify the winner on the final leaderboard
- dedicated winner card: gold border, gold gradient, pulsing gold glow,
  spring scale-in, and a Crown that drops & bounces in (Framer Motion)
- champion label + big gold score; runners-up listed below from rank 2
- drop the generic Scoreboard component (now unused)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 10:25:28 +02:00
AyoubBenziza
5cc9113b8c feat(quiz): quiz game mode end-to-end (server mode + playable client UI)
Server:
- quiz mode (GameRound): in-memory FR question bank (mcq + truefalse),
  per-room anti-repeat, first-vote lock, score = base + speed bonus ∝ time
  left; registered via registerRound, loaded at startup
- shared: typed quiz payloads (QuizQuestionPayload / reveal truth / result)
- tests: quiz scoring, vote lock, bounds, reveal (bun test)

Client:
- room store handles round:start / voteAck / reveal / game:end
- RoomPage dispatches by status: lobby (host start controls) → quiz view
  (question, countdown, vote, reveal + scoreboard) → game-end view
- replaces standalone lobby page

Roadmap V1 step 4. Verified end-to-end over the wire (start→vote→reveal→
score→next round→game:end, no answer leaked, anti-repeat works).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 15:43:17 +02:00