Skip to content

Add pickup game lobbies#272

Draft
mwickett wants to merge 4 commits into
mainfrom
mwickett/pickup-game-lobby
Draft

Add pickup game lobbies#272
mwickett wants to merge 4 commits into
mainfrom
mwickett/pickup-game-lobby

Conversation

@mwickett

Copy link
Copy Markdown
Owner

What this enables

A signed-in host can create a pickup game without a Circle, show a QR code or lobby code, and let other signed-in Blitzer users confirm that they want to join. The host can also add accountless guests at setup. Once the host starts, every registered participant lands in the existing scoring experience and can enter scores together.

Flow

  1. New Game now asks whether this is a Pickup or Circle game.
  2. Pickup setup creates a pre-start Game with the host and optional guests.
  3. The lobby exposes a high-entropy QR link plus a short manual code.
  4. Scanners sign in or sign up, explicitly confirm joining, and appear in the live lobby roster.
  5. The host starts after at least two players are present. The join credential is revoked and everyone moves to the normal scorer.
  6. Open lobbies and started pickup games remain discoverable in Games.

Data and authorization

  • Adds GameKind, startedAt, host, join token, and join code fields through an additive Prisma migration. Existing no-Circle games are marked LEGACY; existing Circle games retain current behavior.
  • QR possession permits an authenticated user to join only while the lobby is open.
  • Pickup scoring is authorized by registered GamePlayers; Circle scoring remains authorized by active Circle membership.
  • Host-only start and join/start operations use a row lock to avoid race conditions.
  • Score writes now require an exact match with the game roster, and round edits verify that the round belongs to the game.

Validation

  • npm run typecheck
  • npm run lint
  • npm test -- --runInBand (167 tests)
  • npx next build with the local development environment

Copilot AI review requested due to automatic review settings July 10, 2026 21:12
@vercel

vercel Bot commented Jul 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
blitzer Ready Ready Preview, Comment Jul 11, 2026 2:02am

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds “pickup game” lobbies that allow a signed-in host to create a game without a Circle, share a QR/link or short code, have other signed-in users join, then start into the existing scoring flow with roster-based scoring authorization.

Changes:

  • Introduces pickup-lobby server actions + queries (create/join/start + lobby reads) with DB row locking and join token/code.
  • Extends game authorization to support pickup scoring via exact roster membership (and keeps Circle semantics).
  • Adds UI routes for creating pickup games, joining by code/token, and a lobby page with QR + roster.

Reviewed changes

Copilot reviewed 25 out of 26 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/server/queries/lobbies.ts New query helpers to fetch pickup lobby by token / for a participant.
src/server/queries/games.ts Expands games list queries to include pickup games and redefines legacy filtering via kind.
src/server/mutations/rounds.ts Switches scoring auth to requireGameScoringAccess and enforces roster-match on score writes.
src/server/mutations/lobbies.ts New server actions for creating/joining/starting pickup lobbies with locks + join credentials.
src/server/mutations/index.ts Re-exports new lobby server actions.
src/server/mutations/games.ts Updates finish/finalization auth to allow pickup players to finalize via scorer access.
src/server/mutations/common.ts Adds local-user provisioning helper and shared pickup/circle scoring authorization + roster assertion.
src/server/db/schema.prisma Adds GameKind, lobby fields, host relation, and supporting indexes.
src/server/db/migrations/20260710120000_add_pickup_games/migration.sql Prisma migration to add enum + new game columns + indexes and backfill legacy kind.
src/server/tests/queries.test.ts Updates getGames tests for OR logic and pickup-without-circle behavior.
src/server/tests/mutations.test.ts Updates scoring mutation tests for round ownership checks and roster enforcement.
src/proxy.ts Allows /games, /games/new, and /games/[id]/lobby without an active Circle while still requiring auth.
src/lib/tests/gameLogic.test.ts Updates game fixtures to include new game fields (kind, startedAt, etc.).
src/components/GamesList.tsx Adjusts UI copy and status badges to include pickup/lobby states.
src/app/join/page.tsx New join-by-code entry page with sign-in gate.
src/app/join/JoinByCodeForm.tsx Client form to join a pickup lobby via short code.
src/app/join/[token]/page.tsx Token-based join confirmation page (with sign-in/sign-up redirects).
src/app/join/[token]/JoinLobbyButton.tsx Client button to execute join action and route to lobby.
src/app/games/new/PickupGameSetup.tsx Client UI to create a pickup lobby with threshold + optional guests.
src/app/games/new/page.tsx Adds game-type chooser routing (circle vs pickup) for New Game.
src/app/games/new/GameTypeChooser.tsx UI for selecting pickup vs circle game creation.
src/app/games/[id]/page.tsx Redirects pickup players to lobby pre-start; allows pickup players to edit after start.
src/app/games/[id]/lobby/page.tsx New lobby page rendering QR/link, lobby code, roster, and controls.
src/app/games/[id]/lobby/LobbyControls.tsx Client controls for polling/refresh, copy link, and host start action.
package.json Adds qrcode runtime dependency and @types/qrcode dev dependency.
package-lock.json Lockfile updates for added dependencies.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/server/queries/lobbies.ts Outdated
Comment thread src/server/mutations/common.ts
Comment thread src/server/mutations/common.ts
Comment thread src/app/games/[id]/lobby/page.tsx Outdated
Comment thread src/app/games/[id]/lobby/LobbyControls.tsx Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 31 out of 32 changed files in this pull request and generated 4 comments.

Comment thread src/server/mutations/common.ts
Comment thread src/app/games/[id]/lobby/LobbyControls.tsx
Comment thread src/app/join/JoinByCodeForm.tsx
Comment thread src/app/join/JoinByCodeForm.tsx Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 32 out of 33 changed files in this pull request and generated 4 comments.

Comment on lines +22 to +30
};

export async function getPickupLobbyByToken(joinToken: string) {
return prisma.game.findUnique({
where: { joinToken },
include: lobbyInclude,
});
}

Comment on lines +153 to +167
} catch (error) {
if (
error &&
typeof error === "object" &&
"code" in error &&
error.code === "P2002"
) {
const racedUser = await prisma.user.findUnique({
where: { clerk_user_id: userId },
});
if (racedUser) return racedUser;
}
throw error;
}
}
Comment on lines +165 to +177
export async function joinPickupGameByCode(rawCode: string) {
await requireAuthContext("user");
const code = rawCode
.trim()
.toUpperCase()
.replace(/[^A-Z0-9]/g, "");
const game = await prisma.game.findUnique({
where: { joinCode: code },
select: { joinToken: true },
});
if (!game?.joinToken) throw new Error("We couldn't find that lobby code");
return joinPickupGame(game.joinToken);
}
Comment on lines +40 to +44
const copy = async () => {
await navigator.clipboard.writeText(joinUrl);
setCopied(true);
window.setTimeout(() => setCopied(false), 1_800);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants