Skip to content

WI-036: Log a play, on screen

WI-036: Log a play, on screen

WI-032 and WI-035 built the routes. This is ADR-0007 as a screen.

The whole design is the first button

Played records a complete session with one tap and no form. That is the product decision: schema depth is not form depth, the API accepts an empty body, and the fast path sends one.

Everything else — rating, who played, who won, notes — is behind Add detail, closed by default, and none of it is required.

In scope

  • LogPlay on the game page: one-tap logging, and the expanded form.
  • Adding somebody to the roster inline, because “who was here” is remembered at the table and not before.
  • The shelf control re-reads after a play, since its rating is projected from sessions.

Out of scope

  • Editing or deleting a play from the UI. The delete route exists; editing arrived later in WI-037, and this sentence originally claimed an edit route that did not exist.
  • Scores. session_participants.score exists, but a scores UI is a different shape per game and inventing one now would be guessing.
  • Tags and teaching cost. Both are in the schema and neither is worth a control until somebody has logged enough plays to want them.

Two decisions worth naming

A failed participant write does not unwind the play. They are two calls, because participants need a session id. If the second fails the first has already succeeded, and the screen says so rather than pretending nothing happened or deleting a play somebody just recorded.

The winner is a long-press, not a second row of controls. Marking a winner is rarer than recording who was there, and giving it equal weight would make the common case slower. Somebody removed from the table stops being the winner automatically, because they cannot have won a game they were not at.

Definition of done

  • Played logs a session with an empty body — no form, no required fields.
  • The expanded form sends only what was filled in.
  • Players can be added inline and are selected on creation.
  • A winner can be marked, and is cleared if that person is deselected.
  • A failed participant write reports itself without losing the play.
  • The shelf’s rating updates after logging, without the client writing it.
  • Every call is authenticated and none is attempted without a token.
  • Each check proven able to fail.
  • Gate green.

Verification

Terminal window
pnpm --filter @tabletop/mobile test
pnpm gate

Then sign in, open a game, and press Played. The rating on the shelf moves when you log one with a rating — projected by the database, not written by the app.

Notes

The auth-gated parts of this screen do not appear in the pre-rendered HTML, because the static render has no session. Asserting against dist/game/[slug].html therefore proves nothing about them, and the check reads the emitted bundle instead — a distinction worth knowing before writing a test that passes for the wrong reason.