Add play again button for rematch after game ends

When a game finishes (win or draw), players see a "Play again" button.
Clicking it creates a new game and the opponent sees a "Join Rematch"
link to join the same game.
This commit is contained in:
Ryan Hamamura
2026-01-14 18:02:26 -10:00
parent 5f452914f8
commit 2cd5b1d289
9 changed files with 138 additions and 37 deletions

View File

@@ -13,7 +13,7 @@ import (
const createGame = `-- name: CreateGame :one
INSERT INTO games (id, board, current_turn, status)
VALUES (?, ?, ?, ?)
RETURNING id, board, current_turn, status, winner_user_id, winning_cells, created_at, updated_at
RETURNING id, board, current_turn, status, winner_user_id, winning_cells, created_at, updated_at, rematch_game_id
`
type CreateGameParams struct {
@@ -40,6 +40,7 @@ func (q *Queries) CreateGame(ctx context.Context, arg CreateGameParams) (Game, e
&i.WinningCells,
&i.CreatedAt,
&i.UpdatedAt,
&i.RematchGameID,
)
return i, err
}
@@ -80,7 +81,7 @@ func (q *Queries) DeleteGame(ctx context.Context, id string) error {
}
const getActiveGames = `-- name: GetActiveGames :many
SELECT id, board, current_turn, status, winner_user_id, winning_cells, created_at, updated_at FROM games WHERE status < 2
SELECT id, board, current_turn, status, winner_user_id, winning_cells, created_at, updated_at, rematch_game_id FROM games WHERE status < 2
`
func (q *Queries) GetActiveGames(ctx context.Context) ([]Game, error) {
@@ -101,6 +102,7 @@ func (q *Queries) GetActiveGames(ctx context.Context) ([]Game, error) {
&i.WinningCells,
&i.CreatedAt,
&i.UpdatedAt,
&i.RematchGameID,
); err != nil {
return nil, err
}
@@ -116,7 +118,7 @@ func (q *Queries) GetActiveGames(ctx context.Context) ([]Game, error) {
}
const getGame = `-- name: GetGame :one
SELECT id, board, current_turn, status, winner_user_id, winning_cells, created_at, updated_at FROM games WHERE id = ?
SELECT id, board, current_turn, status, winner_user_id, winning_cells, created_at, updated_at, rematch_game_id FROM games WHERE id = ?
`
func (q *Queries) GetGame(ctx context.Context, id string) (Game, error) {
@@ -131,6 +133,7 @@ func (q *Queries) GetGame(ctx context.Context, id string) (Game, error) {
&i.WinningCells,
&i.CreatedAt,
&i.UpdatedAt,
&i.RematchGameID,
)
return i, err
}
@@ -171,7 +174,7 @@ func (q *Queries) GetGamePlayers(ctx context.Context, gameID string) ([]GamePlay
}
const getGamesByUserID = `-- name: GetGamesByUserID :many
SELECT g.id, g.board, g.current_turn, g.status, g.winner_user_id, g.winning_cells, g.created_at, g.updated_at FROM games g
SELECT g.id, g.board, g.current_turn, g.status, g.winner_user_id, g.winning_cells, g.created_at, g.updated_at, g.rematch_game_id FROM games g
JOIN game_players gp ON g.id = gp.game_id
WHERE gp.user_id = ?
ORDER BY g.updated_at DESC
@@ -195,6 +198,7 @@ func (q *Queries) GetGamesByUserID(ctx context.Context, userID sql.NullString) (
&i.WinningCells,
&i.CreatedAt,
&i.UpdatedAt,
&i.RematchGameID,
); err != nil {
return nil, err
}
@@ -265,17 +269,18 @@ func (q *Queries) GetUserActiveGames(ctx context.Context, userID sql.NullString)
const updateGame = `-- name: UpdateGame :exec
UPDATE games
SET board = ?, current_turn = ?, status = ?, winner_user_id = ?, winning_cells = ?, updated_at = CURRENT_TIMESTAMP
SET board = ?, current_turn = ?, status = ?, winner_user_id = ?, winning_cells = ?, rematch_game_id = ?, updated_at = CURRENT_TIMESTAMP
WHERE id = ?
`
type UpdateGameParams struct {
Board string
CurrentTurn int64
Status int64
WinnerUserID sql.NullString
WinningCells sql.NullString
ID string
Board string
CurrentTurn int64
Status int64
WinnerUserID sql.NullString
WinningCells sql.NullString
RematchGameID sql.NullString
ID string
}
func (q *Queries) UpdateGame(ctx context.Context, arg UpdateGameParams) error {
@@ -285,6 +290,7 @@ func (q *Queries) UpdateGame(ctx context.Context, arg UpdateGameParams) error {
arg.Status,
arg.WinnerUserID,
arg.WinningCells,
arg.RematchGameID,
arg.ID,
)
return err