Files
games/features/lobby/pages/lobby.templ
Ryan Hamamura 64b5d384ed
All checks were successful
CI / Deploy / test (push) Successful in 15s
CI / Deploy / lint (push) Successful in 25s
CI / Deploy / deploy (push) Successful in 34s
fix: use correct Datastar keydown event syntax
Replace invalid .key_enter and .enter modifiers with evt.key === 'Enter'
guard in the expression, per Datastar docs. Also fix __stop and __throttle
modifier syntax to use double underscores.
2026-03-02 23:05:11 -10:00

172 lines
4.8 KiB
Plaintext

package pages
import (
"fmt"
"github.com/ryanhamamura/games/features/common/components"
"github.com/ryanhamamura/games/features/common/layouts"
lobbycomponents "github.com/ryanhamamura/games/features/lobby/components"
"github.com/ryanhamamura/games/snake"
"github.com/starfederation/datastar-go/datastar"
)
templ LobbyPage(data LobbyData) {
@layouts.Base("Game Lobby") {
<main
class="max-w-md mx-auto mt-8 text-center"
data-signals="{activeTab: 'connect4', nickname: '', selectedSpeed: 1}"
>
// Auth header
if data.IsLoggedIn {
<div class="flex justify-center items-center gap-4 mb-4 p-2 bg-base-200 rounded-lg">
<span>Logged in as <strong>{ data.Username }</strong></span>
<button
type="button"
class="btn btn-ghost btn-sm"
data-on:click={ datastar.PostSSE("/logout") }
>
Logout
</button>
</div>
} else {
<div class="alert text-sm mb-4">
Playing as guest.
<a class="link" href="/login">Login</a>
or
<a class="link" href="/register">Register</a>
to save your games.
</div>
}
// Title
<h1 class="text-3xl font-bold mb-4">
@components.StealthTitle("")
</h1>
// Tab buttons
<div class="tabs tabs-box mb-6 justify-center">
<button
class="tab"
type="button"
data-class="{'tab-active': $activeTab==='connect4'}"
data-on:click="$activeTab='connect4'"
>
@components.StealthTitle("")
</button>
<button
class="tab"
type="button"
data-class="{'tab-active': $activeTab==='snake'}"
data-on:click="$activeTab='snake'"
>
~~~~
</button>
</div>
// Connect4 tab
<div data-show="$activeTab==='connect4'">
<p class="mb-4">Start a new session</p>
<form>
<fieldset class="fieldset">
<label class="label" for="nickname">Your Nickname</label>
<input
class="input input-bordered w-full"
id="nickname"
type="text"
placeholder="Enter your nickname"
data-bind="nickname"
required
data-on:keydown={ "evt.key === 'Enter' && " + datastar.PostSSE("/games") }
/>
</fieldset>
<button
class="btn btn-primary w-full"
type="button"
data-on:click={ datastar.PostSSE("/games") }
>
Create Game
</button>
</form>
@lobbycomponents.GameList(data.UserGames)
</div>
// Snake tab
<div data-show="$activeTab==='snake'">
// Nickname
<div class="mb-4">
<fieldset class="fieldset">
<label class="label" for="snake-nickname">Your Nickname</label>
<input
class="input input-bordered w-full"
id="snake-nickname"
type="text"
placeholder="Enter your nickname"
data-bind="nickname"
required
/>
</fieldset>
</div>
// Speed selector
<div class="mb-4">
<label class="label">Speed</label>
<div class="btn-group">
for i, preset := range snake.SpeedPresets {
<button
class="btn btn-sm"
type="button"
data-class={ fmt.Sprintf("{'btn-active': $selectedSpeed===%d}", i) }
data-on:click={ fmt.Sprintf("$selectedSpeed=%d", i) }
>
{ preset.Name }
</button>
}
</div>
</div>
// Solo play
<div class="mb-6">
<h3 class="text-lg font-bold mb-2">Play Solo</h3>
<div class="flex gap-2 justify-center flex-wrap">
for i, preset := range snake.GridPresets {
<button
class="btn btn-secondary"
type="button"
data-on:click={ datastar.PostSSE("/snake?mode=solo&preset=%d", i) }
>
{ fmt.Sprintf("%s (%d\u00d7%d)", preset.Name, preset.Width, preset.Height) }
</button>
}
</div>
</div>
// Multiplayer
<div class="mb-6">
<h3 class="text-lg font-bold mb-2">Create Multiplayer Game</h3>
<div class="flex gap-2 justify-center flex-wrap">
for i, preset := range snake.GridPresets {
<button
class="btn btn-primary"
type="button"
data-on:click={ datastar.PostSSE("/snake?mode=multi&preset=%d", i) }
>
{ fmt.Sprintf("%s (%d\u00d7%d)", preset.Name, preset.Width, preset.Height) }
</button>
}
</div>
</div>
// Active snake games
if len(data.ActiveSnakeGames) > 0 {
<div class="mt-6">
<h3 class="text-lg font-bold mb-2 text-center">Join a Game</h3>
<div class="flex flex-col gap-2">
for _, g := range data.ActiveSnakeGames {
<a
href={ templ.SafeURL("/snake/" + g.ID) }
class="flex justify-between items-center p-3 bg-base-200 rounded-lg hover:bg-base-300 no-underline text-base-content"
>
<span>{ fmt.Sprintf("%d\u00d7%d \u2014 %d/8 players", g.Width, g.Height, g.PlayerCount) }</span>
<span class="text-sm opacity-60">{ g.StatusLabel }</span>
</a>
}
</div>
</div>
}
</div>
</main>
}
}