The SSE patching refactor (0808c4d) wrapped game elements in a bare
<div id="game-content"> without propagating the flex classes from
<main>. This broke center-alignment and vertical spacing for both
Connect 4 and Snake game pages.
85 lines
2.9 KiB
Plaintext
85 lines
2.9 KiB
Plaintext
package pages
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/ryanhamamura/games/chat"
|
|
chatcomponents "github.com/ryanhamamura/games/chat/components"
|
|
"github.com/ryanhamamura/games/features/common/components"
|
|
"github.com/ryanhamamura/games/features/common/layouts"
|
|
snakecomponents "github.com/ryanhamamura/games/features/snakegame/components"
|
|
"github.com/ryanhamamura/games/snake"
|
|
"github.com/starfederation/datastar-go/datastar"
|
|
)
|
|
|
|
// keydownScript builds the inline JS for a single data-on:keydown handler
|
|
// that dispatches WASD/arrow keys to direction POST endpoints.
|
|
func keydownScript(gameID string) string {
|
|
return fmt.Sprintf(
|
|
"const k=evt.key;"+
|
|
"if(k==='w'||k==='ArrowUp'){evt.preventDefault();%s}"+
|
|
"else if(k==='s'||k==='ArrowDown'){evt.preventDefault();%s}"+
|
|
"else if(k==='a'||k==='ArrowLeft'){evt.preventDefault();%s}"+
|
|
"else if(k==='d'||k==='ArrowRight'){evt.preventDefault();%s}",
|
|
datastar.PostSSE("/snake/%s/dir?d=0", gameID),
|
|
datastar.PostSSE("/snake/%s/dir?d=1", gameID),
|
|
datastar.PostSSE("/snake/%s/dir?d=2", gameID),
|
|
datastar.PostSSE("/snake/%s/dir?d=3", gameID),
|
|
)
|
|
}
|
|
|
|
templ GamePage(sg *snake.SnakeGame, mySlot int, messages []chat.Message, chatCfg chatcomponents.Config, gameID string) {
|
|
@layouts.Base("Snake") {
|
|
<main
|
|
class="snake-wrapper flex flex-col items-center gap-4 p-4"
|
|
data-signals={ `{"chatMsg":""}` }
|
|
data-init={ fmt.Sprintf("@get('/snake/%s/events',{requestCancellation:'disabled'})", gameID) }
|
|
data-on:keydown__throttle.100ms={ keydownScript(gameID) }
|
|
tabindex="0"
|
|
>
|
|
@GameContent(sg, mySlot, messages, chatCfg, gameID)
|
|
</main>
|
|
}
|
|
}
|
|
|
|
templ GameContent(sg *snake.SnakeGame, mySlot int, messages []chat.Message, chatCfg chatcomponents.Config, gameID string) {
|
|
<div id="game-content" class="flex flex-col items-center gap-4">
|
|
@components.LiveClock()
|
|
@components.BackToLobby()
|
|
<h1 class="text-3xl font-bold">~~~~</h1>
|
|
@snakecomponents.PlayerList(sg, mySlot)
|
|
@snakecomponents.StatusBanner(sg, mySlot, gameID)
|
|
if sg.Status == snake.StatusInProgress || sg.Status == snake.StatusFinished {
|
|
if sg.Mode == snake.ModeMultiplayer {
|
|
<div class="snake-game-area">
|
|
@snakecomponents.Board(sg)
|
|
@chatcomponents.Chat(messages, chatCfg)
|
|
</div>
|
|
} else {
|
|
@snakecomponents.Board(sg)
|
|
}
|
|
} else if sg.Mode == snake.ModeMultiplayer {
|
|
@chatcomponents.Chat(messages, chatCfg)
|
|
}
|
|
if sg.Mode == snake.ModeMultiplayer && (sg.Status == snake.StatusWaitingForPlayers || sg.Status == snake.StatusCountdown) {
|
|
@snakecomponents.InviteLink(gameID)
|
|
}
|
|
</div>
|
|
}
|
|
|
|
templ JoinPage(gameID string) {
|
|
@layouts.Base("Snake - Join") {
|
|
@components.GameJoinPrompt(
|
|
fmt.Sprintf("/login?return_url=/snake/%s", gameID),
|
|
fmt.Sprintf("/register?return_url=/snake/%s", gameID),
|
|
fmt.Sprintf("/snake/%s", gameID),
|
|
)
|
|
}
|
|
}
|
|
|
|
templ NicknamePage(gameID string) {
|
|
@layouts.Base("Snake - Join") {
|
|
@components.NicknamePrompt(fmt.Sprintf("/snake/%s/join", gameID))
|
|
}
|
|
}
|