Real-time two-player Connect 4 using Via framework with: - Game creation and invite links - SSE-based live updates for both players - Win detection with animated highlighting - Session-based nickname persistence
111 lines
2.3 KiB
Go
111 lines
2.3 KiB
Go
package ui
|
|
|
|
import (
|
|
"github.com/ryanhamamura/c4/game"
|
|
"github.com/ryanhamamura/via/h"
|
|
)
|
|
|
|
func StatusBanner(g *game.Game, myColor int) h.H {
|
|
var message string
|
|
var class string
|
|
|
|
switch g.Status {
|
|
case game.StatusWaitingForPlayer:
|
|
message = "Waiting for opponent..."
|
|
class = "status waiting"
|
|
case game.StatusInProgress:
|
|
if g.CurrentTurn == myColor {
|
|
message = "Your turn!"
|
|
class = "status your-turn"
|
|
} else {
|
|
opponentName := getOpponentName(g, myColor)
|
|
message = opponentName + "'s turn"
|
|
class = "status opponent-turn"
|
|
}
|
|
case game.StatusWon:
|
|
if g.Winner != nil && g.Winner.Color == myColor {
|
|
message = "You win!"
|
|
class = "status winner"
|
|
} else if g.Winner != nil {
|
|
message = g.Winner.Nickname + " wins!"
|
|
class = "status loser"
|
|
}
|
|
case game.StatusDraw:
|
|
message = "It's a draw!"
|
|
class = "status draw"
|
|
}
|
|
|
|
return h.Div(
|
|
h.Class(class),
|
|
h.Text(message),
|
|
)
|
|
}
|
|
|
|
func getOpponentName(g *game.Game, myColor int) string {
|
|
for _, p := range g.Players {
|
|
if p != nil && p.Color != myColor {
|
|
return p.Nickname
|
|
}
|
|
}
|
|
return "Opponent"
|
|
}
|
|
|
|
func PlayerInfo(g *game.Game, myColor int) h.H {
|
|
var myName, opponentName string
|
|
var myColorClass, opponentColorClass string
|
|
|
|
for _, p := range g.Players {
|
|
if p == nil {
|
|
continue
|
|
}
|
|
if p.Color == myColor {
|
|
myName = p.Nickname
|
|
if p.Color == 1 {
|
|
myColorClass = "red"
|
|
} else {
|
|
myColorClass = "yellow"
|
|
}
|
|
} else {
|
|
opponentName = p.Nickname
|
|
if p.Color == 1 {
|
|
opponentColorClass = "red"
|
|
} else {
|
|
opponentColorClass = "yellow"
|
|
}
|
|
}
|
|
}
|
|
|
|
if opponentName == "" {
|
|
opponentName = "Waiting..."
|
|
}
|
|
|
|
return h.Div(h.Class("player-info"),
|
|
h.Div(h.Class("player you"),
|
|
h.Span(h.Class("player-chip "+myColorClass)),
|
|
h.Span(h.Text(myName+" (You)")),
|
|
),
|
|
h.Div(h.Class("player opponent"),
|
|
h.Span(h.Class("player-chip "+opponentColorClass)),
|
|
h.Span(h.Text(opponentName)),
|
|
),
|
|
)
|
|
}
|
|
|
|
const baseURL = "https://demo.adriatica.io"
|
|
|
|
func InviteLink(gameID string) h.H {
|
|
fullURL := baseURL + "/game/" + gameID
|
|
return h.Div(h.Class("invite-section"),
|
|
h.P(h.Text("Share this link with your opponent:")),
|
|
h.Div(h.Class("invite-link"),
|
|
h.Text(fullURL),
|
|
),
|
|
h.Button(
|
|
h.Class("copy-btn"),
|
|
h.Type("button"),
|
|
h.Text("Copy Link"),
|
|
h.Attr("onclick", "navigator.clipboard.writeText('"+fullURL+"')"),
|
|
),
|
|
)
|
|
}
|