Skip to content

Commit

Permalink
feat: support editing and deleting game rounds
Browse files Browse the repository at this point in the history
  • Loading branch information
Tarow committed Dec 27, 2023
1 parent b2c01a8 commit 193961c
Show file tree
Hide file tree
Showing 12 changed files with 597 additions and 70 deletions.
118 changes: 103 additions & 15 deletions internal/api/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func (h Handler) EditGame(c echo.Context) error {
return slices.Index(form.Players, i.Name) - slices.Index(form.Players, j.Name)
})

updatedGame, err := h.service.Edit(*game)
updatedGame, err := h.service.EditGame(*game)
if err != nil {
return err
}
Expand All @@ -144,7 +144,7 @@ func (h Handler) DeleteGame(c echo.Context) error {
return err
}

err = h.service.Delete(int32(parsedId))
err = h.service.DeleteGame(int32(parsedId))
if err != nil {
c.Logger().Error(err)
return err
Expand All @@ -167,12 +167,107 @@ func (h Handler) AddRound(c echo.Context) error {
return err
}

round, err := parseRound(*game, c)
round.CreatedAt = time.Now()
if err != nil {
return err
}

round, err = h.service.AddRound(round)
if err != nil {
return err
}

game.Rounds = append(game.Rounds, round)
gameDetails := template.GameDetails(*game)
return render(c, http.StatusCreated, gameDetails)
}

func (h Handler) GetEditRoundForm(c echo.Context) error {
game, err := h.findGame(c.Param("gameid"))
if err != nil {
return err
}

roundId, err := strconv.Atoi(c.Param("roundid"))
if err != nil {
return err
}

var round skat.Round
var roundIdx int
for i, r := range game.Rounds {
if r.ID == int32(roundId) {
round = r
roundIdx = i
}
}

form := components.EditRoundForm(*game, round, roundIdx)
return render(c, http.StatusOK, form)
}

func (h Handler) EditRound(c echo.Context) error {
game, err := h.findGame(c.Param("gameid"))
if err != nil {
c.Logger().Error(err)
return err
}

parsedRoundId, err := strconv.Atoi(c.Param("roundid"))
if err != nil {
c.Logger().Error(err)
return err
}

round, err := parseRound(*game, c)
if err != nil {
c.Logger().Error(err)
return err
}
round.ID = int32(parsedRoundId)

updatedRound, err := h.service.EditRound(round)
if err != nil {
c.Logger().Error(err)
return err
}

for i, round := range game.Rounds {
if updatedRound.ID == round.ID {
game.Rounds[i] = updatedRound
break
}
}

gameDetails := template.GameDetails(*game)
return render(c, http.StatusCreated, gameDetails)
}

func (h Handler) DeleteRound(c echo.Context) error {
parsedRoundId, err := strconv.Atoi(c.Param("roundid"))
if err != nil {
c.Logger().Error(err)
return err
}

h.service.DeleteRound(int32(parsedRoundId))

game, err := h.findGame(c.Param("gameid"))
if err != nil {
return err
}

gameDetails := template.GameDetails(*game)
return render(c, http.StatusCreated, gameDetails)
}

func parseRound(game skat.Game, c echo.Context) (skat.Round, error) {
var params map[string]string = make(map[string]string)
c.Bind(&params)

round := skat.Round{}
round.GameID = game.ID
round.CreatedAt = time.Now()
for _, player := range game.Players {
role, exists := params[player.Name]
if !exists {
Expand All @@ -185,16 +280,16 @@ func (h Handler) AddRound(c echo.Context) error {
case "opponent":
round.Opponents = append(round.Opponents, player.ID)
case "dealer":
round.Dealer = &player.ID
dealer := player.ID
round.Dealer = &dealer
}
}

wonStr, exists := params["won"]
if exists {
won, err := strconv.ParseBool(wonStr)
if err != nil {
c.Logger().Error(err)
return err
return skat.Round{}, err
}
round.Won = won
}
Expand All @@ -204,19 +299,12 @@ func (h Handler) AddRound(c echo.Context) error {
gameValue, err := strconv.Atoi(gameValueStr)
if err != nil {
c.Logger().Error(err)
return err
return skat.Round{}, err
}
round.Value = int32(gameValue)
}

round, err = h.service.AddRound(game.ID, round)
if err != nil {
return err
}

game.Rounds = append(game.Rounds, round)
gameDetails := template.GameDetails(*game)
return render(c, http.StatusCreated, gameDetails)
return round, nil
}

func render(ctx echo.Context, status int, t templ.Component) error {
Expand Down
82 changes: 79 additions & 3 deletions internal/skat/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ func (s Service) Create(g Game) (Game, error) {
return g, nil
}

func (s Service) Edit(g Game) (Game, error) {
func (s Service) EditGame(g Game) (Game, error) {
tx, err := s.db.Begin()
if err != nil {
return Game{}, err
Expand Down Expand Up @@ -184,7 +184,7 @@ func (s Service) Edit(g Game) (Game, error) {
return g, nil
}

func (s Service) AddRound(gameId int32, round Round) (Round, error) {
func (s Service) AddRound(round Round) (Round, error) {
opponents := round.Opponents

tx, err := s.db.Begin()
Expand Down Expand Up @@ -228,7 +228,83 @@ func (s Service) AddRound(gameId int32, round Round) (Round, error) {
return round, nil
}

func (s Service) Delete(gameId int32) error {
func (s Service) EditRound(round Round) (Round, error) {
tx, err := s.db.Begin()
if err != nil {
return Round{}, err
}
defer tx.Rollback()

// Delete old opponents
deleteOpponents := table.RoundOpponent.DELETE().
WHERE(table.RoundOpponent.RoundID.EQ(sqlite.Int32(round.ID)))
_, err = deleteOpponents.Exec(tx)
if err != nil {
return Round{}, err
}

// Update round
updateRound := table.Round.UPDATE(
table.Round.AllColumns.Except(table.Round.ID),
).WHERE(table.Round.ID.EQ(sqlite.Int32(round.ID))).
MODEL(round)
_, err = updateRound.Exec(tx)
if err != nil {
return Round{}, err
}

// Insert new round opponents
roundOpponents := make([]model.RoundOpponent, 0)
for _, opponentId := range round.Opponents {
roundOpponents = append(roundOpponents, model.RoundOpponent{
RoundID: round.ID,
PlayerID: opponentId,
})
}
insertOpponents := table.RoundOpponent.INSERT(
table.RoundOpponent.AllColumns,
).MODELS(roundOpponents)

_, err = insertOpponents.Exec(tx)
if err != nil {
return Round{}, err
}

err = tx.Commit()
if err != nil {
return Round{}, err
}

return round, nil
}

func (s Service) DeleteRound(roundId int32) error {
tx, err := s.db.Begin()
if err != nil {
return err
}
defer tx.Rollback()

// Delete opponents
deleteOpponents := table.RoundOpponent.DELETE().
WHERE(table.RoundOpponent.RoundID.EQ(sqlite.Int32(roundId)))
_, err = deleteOpponents.Exec(tx)
if err != nil {
return err
}

// Delete round
deleteRound := table.Round.DELETE().
WHERE(table.Round.ID.EQ(sqlite.Int32(roundId)))
_, err = deleteRound.Exec(tx)
if err != nil {
return err
}

return tx.Commit()
}

func (s Service) DeleteGame(gameId int32) error {
tx, err := s.db.Begin()
if err != nil {
return err
Expand Down
5 changes: 4 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,11 @@ func registerRoutes(e *echo.Echo, handler api.Handler) {
e.PUT("/games/:id/edit", handler.EditGame)

e.DELETE("/games/:id", handler.DeleteGame)
e.POST("/games/:id/rounds", handler.AddRound)

e.POST("/games/:id/rounds", handler.AddRound)
e.GET("/games/:gameid/rounds/:roundid", handler.GetEditRoundForm)
e.PUT("/games/:gameid/rounds/:roundid", handler.EditRound)
e.DELETE("/games/:gameid/rounds/:roundid", handler.DeleteRound)
}
func createTables(db *sql.DB) error {
_, err := db.Exec(`
Expand Down
2 changes: 1 addition & 1 deletion templates/components/create_game_form.templ
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package components

templ CreateGameForm() {
<form id="create_game_form" method="dialog">
<form method="dialog">
<div class="flex flex-col gap-8">
<h3 class="font-bold text-lg">Create Game</h3>
<div class="flex flex-row items-center flex-wrap justify-between">
Expand Down
2 changes: 1 addition & 1 deletion templates/components/create_game_form_templ.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions templates/components/edit_game_form.templ
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import "github.com/tarow/skat-counter/internal/skat"
import "fmt"

templ EditGameForm(g skat.Game) {
<form id="create_game_form" method="dialog">
<form method="dialog">
<div class="flex flex-col gap-8">
<h3 class="font-bold text-lg">Create Game</h3>
<h3 class="font-bold text-lg">Edit Game</h3>
<div class="flex flex-row items-center flex-wrap justify-between">
<div class="flex-1">
<div class="flex flex-row pb-2">
Expand All @@ -25,7 +25,7 @@ templ EditGameForm(g skat.Game) {
<span>3</span>
</div>
</div>
<div class="divider divider-horizontal "></div>
<div class="divider divider-horizontal"></div>
<div class="flex-shrink">
<div class="form-control">
<label class="cursor-pointer flex items-center gap-2">
Expand Down
6 changes: 3 additions & 3 deletions templates/components/edit_game_form_templ.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 193961c

Please sign in to comment.