Rename game/ -> connect4/ to avoid c4/game stutter. Drop redundant
Game prefix from exported types (GameStore -> Store, GameInstance ->
Instance, GameStatus -> Status). Rename NATS subjects from game.{id}
to connect4.{id}. URL routes unchanged.
152 lines
3.5 KiB
Plaintext
152 lines
3.5 KiB
Plaintext
package components
|
|
|
|
import (
|
|
"github.com/ryanhamamura/c4/config"
|
|
"github.com/ryanhamamura/c4/connect4"
|
|
"github.com/starfederation/datastar-go/datastar"
|
|
)
|
|
|
|
templ StatusBanner(g *connect4.Game, myColor int) {
|
|
<div id="c4-status" class={ statusClass(g, myColor) }>
|
|
{ statusMessage(g, myColor) }
|
|
if g.IsFinished() {
|
|
if g.RematchGameID != nil {
|
|
<a
|
|
class="btn btn-sm bg-white text-gray-800 border-none ml-4"
|
|
href={ templ.SafeURL("/games/" + *g.RematchGameID) }
|
|
>
|
|
Join Rematch
|
|
</a>
|
|
} else {
|
|
<button
|
|
class="btn btn-sm bg-white text-gray-800 border-none ml-4"
|
|
type="button"
|
|
data-on:click={ datastar.PostSSE("/games/%s/rematch", g.ID) }
|
|
>
|
|
Play again
|
|
</button>
|
|
}
|
|
}
|
|
</div>
|
|
}
|
|
|
|
templ PlayerInfo(g *connect4.Game, myColor int) {
|
|
<div id="c4-players" class="flex gap-8 mb-2">
|
|
for _, info := range playerInfoPairs(g, myColor) {
|
|
<div class="flex items-center gap-2">
|
|
<span class={ "player-chip " + info.ColorClass }></span>
|
|
<span>{ info.Label }</span>
|
|
</div>
|
|
}
|
|
</div>
|
|
}
|
|
|
|
templ InviteLink(gameID string) {
|
|
<div class="mt-4 text-center">
|
|
<p>Share this link with your opponent:</p>
|
|
<div class="bg-base-200 p-4 rounded-lg font-mono break-all my-2">
|
|
{ config.Global.AppURL + "/games/" + gameID }
|
|
</div>
|
|
<button
|
|
class="btn btn-sm mt-2"
|
|
type="button"
|
|
onclick={ copyToClipboard(config.Global.AppURL + "/games/" + gameID) }
|
|
>
|
|
Copy Link
|
|
</button>
|
|
</div>
|
|
}
|
|
|
|
script copyToClipboard(url string) {
|
|
navigator.clipboard.writeText(url)
|
|
}
|
|
|
|
func statusClass(g *connect4.Game, myColor int) string {
|
|
switch g.Status {
|
|
case connect4.StatusWaitingForPlayer:
|
|
return "alert bg-base-200 text-xl font-bold"
|
|
case connect4.StatusInProgress:
|
|
if g.CurrentTurn == myColor {
|
|
return "alert alert-success text-xl font-bold"
|
|
}
|
|
return "alert bg-base-200 text-xl font-bold"
|
|
case connect4.StatusWon:
|
|
if g.Winner != nil && g.Winner.Color == myColor {
|
|
return "alert alert-success text-xl font-bold"
|
|
}
|
|
return "alert alert-error text-xl font-bold"
|
|
case connect4.StatusDraw:
|
|
return "alert alert-warning text-xl font-bold"
|
|
}
|
|
return "alert bg-base-200 text-xl font-bold"
|
|
}
|
|
|
|
func statusMessage(g *connect4.Game, myColor int) string {
|
|
switch g.Status {
|
|
case connect4.StatusWaitingForPlayer:
|
|
return "Waiting for opponent..."
|
|
case connect4.StatusInProgress:
|
|
if g.CurrentTurn == myColor {
|
|
return "Your turn!"
|
|
}
|
|
return opponentName(g, myColor) + "'s turn"
|
|
case connect4.StatusWon:
|
|
if g.Winner != nil && g.Winner.Color == myColor {
|
|
return "You win!"
|
|
}
|
|
if g.Winner != nil {
|
|
return g.Winner.Nickname + " wins!"
|
|
}
|
|
return "Game over"
|
|
case connect4.StatusDraw:
|
|
return "It's a draw!"
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func opponentName(g *connect4.Game, myColor int) string {
|
|
for _, p := range g.Players {
|
|
if p != nil && p.Color != myColor {
|
|
return p.Nickname
|
|
}
|
|
}
|
|
return "Opponent"
|
|
}
|
|
|
|
type playerInfoData struct {
|
|
ColorClass string
|
|
Label string
|
|
}
|
|
|
|
func playerInfoPairs(g *connect4.Game, myColor int) []playerInfoData {
|
|
var result []playerInfoData
|
|
|
|
var myName, oppName string
|
|
var myClass, oppClass string
|
|
|
|
for _, p := range g.Players {
|
|
if p == nil {
|
|
continue
|
|
}
|
|
colorClass := "yellow"
|
|
if p.Color == 1 {
|
|
colorClass = "red"
|
|
}
|
|
if p.Color == myColor {
|
|
myName = p.Nickname
|
|
myClass = colorClass
|
|
} else {
|
|
oppName = p.Nickname
|
|
oppClass = colorClass
|
|
}
|
|
}
|
|
|
|
if oppName == "" {
|
|
oppName = "Waiting..."
|
|
}
|
|
|
|
result = append(result, playerInfoData{ColorClass: myClass, Label: myName + " (You)"})
|
|
result = append(result, playerInfoData{ColorClass: oppClass, Label: oppName})
|
|
return result
|
|
}
|