Commit graph

7 commits

Author SHA1 Message Date
12423cec1d feat(frontend): add quit button and matchmaking ban UX
- index.html/style.css: destructive-styled #match-quit-btn in the in-match
  HUD row, two-click arm/confirm (no heavyweight modal).
- multiplayerMatch.ts: wires the button (send player:quit, tear down
  timer/listeners/opponent pane immediately, no server reply awaited),
  adds an optional onQuit constructor callback for a future host
  (#14/#15) to route back to the main menu -- nothing mounts
  MultiplayerMatch yet, so this ticket's own quit-button wiring is what
  exercises it.
- ui/banBanner.ts (new): standalone renderBanBanner(container,
  bannedUntil) countdown, ready for #14 to mount into #menu-matchmaking.
  Not wired anywhere yet: per session.js/queue.js, quitting a
  matchmaking match pushes nothing to the quitter directly -- the only
  wire message carrying ban info is queue:banned, sent in reply to a
  later queue:join while banned.

Verified against a real backend + real browser tab driving
MultiplayerMatch through an actual matchmaking match (paired against a
raw ws opponent): quit sends player:quit, opponent gets
room:playerLeft + room:closed(reason:quit) with no ban message; a
follow-up queue:join from the quitter correctly receives queue:banned
(bannedUntil ~120s out) and renderBanBanner counts it down live.
Repeated via room:create/room:join (private room): identical
teardown/onQuit behavior, opponent gets zero ban-related messages, and
the quitter's earlier matchmaking ban is left completely unchanged.
2026-09-10 12:40:50 -03:00
5190ec19a3 feat(frontend): add in-match orchestrator and multiplayer scoreboard
New multiplayerMatch.ts (MultiplayerMatch class) drives one round: syncs
ThemeGuessGame/OpponentView to a round:start payload, relays local
category assignments as round:progress, forwards opponent round:progress
to OpponentView, drives timerHud's countdown (submitting the local color
map as round:submit at expiry), and renders a two-column scoreboard on
round:reveal via computeMatchResult.

ThemeGuessGame gains an optional onCategoryAssigned?(id, hex) constructor
callback, invoked as the last step of applyColor.

timerHud's TimerHudOptions gains an optional onExpire?() callback on the
countdown variant, fired once when endsAt passes.

resultView.ts gains renderMultiplayerResult() for the two-column
you/opponent scoreboard + winner banner (equal overall -> explicit draw).

index.html/style.css: additive #mp-scoreboard/#mp-winner-banner/#mp-you-*/
#mp-opponent-* markup and .mp-* styles; existing single-player result
markup untouched aside from adding id="solo-score-meter-wrap" so it can
be toggled off during a multiplayer reveal.
2026-09-10 12:16:15 -03:00
30a2d9f3dd feat(frontend): add in-match timer HUD with countdown and time warning 2026-09-10 12:03:42 -03:00
4b8c402e43 feat(frontend): add in-match split-view opponent progress pane 2026-09-10 12:03:42 -03:00
5162f090cb feat(frontend): add solo mode config flow (time/theme/opponent) 2026-09-10 11:54:48 -03:00
18cf6a00ca feat(frontend): restructure main menu into Solo/Private/Matchmaking
Replace the single pick-a-theme-and-start intro modal with a three-section
menu (Solo/Private/Matchmaking). Solo keeps the existing gameplay reachable
via a direct Play button; Private (Enter Code/Create Room) and Matchmaking
(Find Match) are stubbed with console.log no-ops pending tickets #17/#15/#14.

main.ts gains a small showView(name) helper that toggles .hidden across the
menu/result overlay screens, keeping it a thin composition root.
2026-09-10 11:45:28 -03:00
6f9a298aef refactor(frontend): move to frontend/, port to Vite + TypeScript
Splits the single game.js god-class into layered modules (types, data,
engine, game, preview, ui, main) and converts every source file to
TypeScript, built and served by Vite instead of a plain static server.
No behavior change: verified against the previous JS version via a full
play-through (theme select, preview countdown, coloring, reveal) in a
real browser.
2026-09-10 10:37:44 -03:00
Renamed from style.css (Browse further)