From 4f1ee11fa33c90249aabfbb70cca52fe7b172dc2 Mon Sep 17 00:00:00 2001
From: Ryan Hamamura <58859899+ryanhamamura@users.noreply.github.com>
Date: Mon, 2 Mar 2026 15:06:01 -1000
Subject: [PATCH 1/2] fix: add Enter key handlers to all auth and nickname
inputs
Pressing Enter on the username field in login/register or the nickname
field in the join-game prompt now submits the form, matching user
expectations. Also add *.templ to the gitignore allowlist.
---
.gitignore | 1 +
features/auth/pages/login.templ | 48 ++++++++++++++++
features/auth/pages/login_templ.go | 23 ++++++--
features/auth/pages/register.templ | 57 +++++++++++++++++++
features/auth/pages/register_templ.go | 36 ++++++++++--
features/common/components/shared.templ | 60 ++++++++++++++++++++
features/common/components/shared_templ.go | 65 +++++++++++++---------
7 files changed, 254 insertions(+), 36 deletions(-)
create mode 100644 features/auth/pages/login.templ
create mode 100644 features/auth/pages/register.templ
create mode 100644 features/common/components/shared.templ
diff --git a/.gitignore b/.gitignore
index 9dca485..6a7aed8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@
!.gitignore
!*.go
+!*.templ
!*.sql
!go.sum
!go.mod
diff --git a/features/auth/pages/login.templ b/features/auth/pages/login.templ
new file mode 100644
index 0000000..3a4bcae
--- /dev/null
+++ b/features/auth/pages/login.templ
@@ -0,0 +1,48 @@
+package pages
+
+import (
+ "github.com/ryanhamamura/c4/features/common/layouts"
+ "github.com/starfederation/datastar-go/datastar"
+)
+
+templ LoginPage() {
+ @layouts.Base("Login") {
+
+ Login
+ Sign in to your account
+
+
+
+ Username
+
+ Password
+
+
+
+ Login
+
+
+
+ Don't have an account? Register
+
+
+ }
+}
diff --git a/features/auth/pages/login_templ.go b/features/auth/pages/login_templ.go
index 5d0cec4..55ae981 100644
--- a/features/auth/pages/login_templ.go
+++ b/features/auth/pages/login_templ.go
@@ -46,33 +46,46 @@ func LoginPage() templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "Login Sign in to your account
Don't have an account? Register
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
diff --git a/features/auth/pages/register.templ b/features/auth/pages/register.templ
new file mode 100644
index 0000000..00ef50a
--- /dev/null
+++ b/features/auth/pages/register.templ
@@ -0,0 +1,57 @@
+package pages
+
+import (
+ "github.com/ryanhamamura/c4/features/common/layouts"
+ "github.com/starfederation/datastar-go/datastar"
+)
+
+templ RegisterPage() {
+ @layouts.Base("Register") {
+
+ Register
+ Create a new account
+
+
+
+ Username
+
+ Password
+
+ Confirm Password
+
+
+
+ Register
+
+
+
+ Already have an account? Login
+
+
+ }
+}
diff --git a/features/auth/pages/register_templ.go b/features/auth/pages/register_templ.go
index 7486adb..c7961d5 100644
--- a/features/auth/pages/register_templ.go
+++ b/features/auth/pages/register_templ.go
@@ -46,33 +46,59 @@ func RegisterPage() templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "Register Create a new account
Already have an account? Login
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
diff --git a/features/common/components/shared.templ b/features/common/components/shared.templ
new file mode 100644
index 0000000..7d0b631
--- /dev/null
+++ b/features/common/components/shared.templ
@@ -0,0 +1,60 @@
+package components
+
+import "github.com/starfederation/datastar-go/datastar"
+
+templ BackToLobby() {
+ ← Back
+}
+
+templ StealthTitle(class string) {
+
+ ●
+ ●
+ ●
+ ●
+
+}
+
+templ NicknamePrompt(returnPath string) {
+
+ Join Game
+ Enter your nickname to join the game.
+
+
+}
+
+templ GameJoinPrompt(loginURL string, registerURL string, gamePath string) {
+
+ Join Game
+ Log in to track your game history, or continue as a guest.
+
+
+ Don't have an account?
+ Register
+
+
+}
diff --git a/features/common/components/shared_templ.go b/features/common/components/shared_templ.go
index 9c74d6c..7341d8c 100644
--- a/features/common/components/shared_templ.go
+++ b/features/common/components/shared_templ.go
@@ -107,20 +107,33 @@ func NicknamePrompt(returnPath string) templ.Component {
templ_7745c5c3_Var5 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "Join Game Enter your nickname to join the game.
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\" required autofocus>Join ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -144,51 +157,51 @@ func GameJoinPrompt(loginURL string, registerURL string, gamePath string) templ.
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var7 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var7 == nil {
- templ_7745c5c3_Var7 = templ.NopComponent
+ templ_7745c5c3_Var8 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var8 == nil {
+ templ_7745c5c3_Var8 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "Join Game Log in to track your game history, or continue as a guest.
Don't have an account? Register
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
From 2bea5bb48986bff2f8b90e927c4bd704272654b6 Mon Sep 17 00:00:00 2001
From: Ryan Hamamura <58859899+ryanhamamura@users.noreply.github.com>
Date: Mon, 2 Mar 2026 15:27:38 -1000
Subject: [PATCH 2/2] chore: gitignore generated _templ.go files, track .templ
sources
Generated _templ.go files are deterministic output from .templ sources,
same as output.css from input.css. Remove them from version control to
reduce diff noise and merge conflicts. Add build:templ and live:templ
tasks to the Taskfile so generation happens as part of the build.
---
.gitignore | 3 +-
Taskfile.yml | 19 +-
features/auth/pages/login_templ.go | 102 ----
features/auth/pages/register_templ.go | 115 -----
features/c4game/components/board.templ | 65 +++
features/c4game/components/board_templ.go | 199 --------
features/c4game/components/chat.templ | 69 +++
features/c4game/components/chat_templ.go | 173 -------
features/c4game/components/status.templ | 151 ++++++
features/c4game/components/status_templ.go | 352 -------------
features/c4game/pages/game.templ | 47 ++
features/c4game/pages/game_templ.go | 219 --------
features/common/components/shared_templ.go | 212 --------
features/common/layouts/base.templ | 21 +
features/common/layouts/base_templ.go | 69 ---
features/lobby/components/gamelist.templ | 109 ++++
features/lobby/components/gamelist_templ.go | 239 ---------
features/lobby/pages/lobby.templ | 171 +++++++
features/lobby/pages/lobby_templ.go | 339 -------------
features/snakegame/components/board.templ | 113 +++++
features/snakegame/components/board_templ.go | 295 -----------
features/snakegame/components/chat.templ | 66 +++
features/snakegame/components/chat_templ.go | 173 -------
features/snakegame/components/status.templ | 137 +++++
features/snakegame/components/status_templ.go | 470 ------------------
features/snakegame/pages/game.templ | 75 +++
features/snakegame/pages/game_templ.go | 277 -----------
27 files changed, 1044 insertions(+), 3236 deletions(-)
delete mode 100644 features/auth/pages/login_templ.go
delete mode 100644 features/auth/pages/register_templ.go
create mode 100644 features/c4game/components/board.templ
delete mode 100644 features/c4game/components/board_templ.go
create mode 100644 features/c4game/components/chat.templ
delete mode 100644 features/c4game/components/chat_templ.go
create mode 100644 features/c4game/components/status.templ
delete mode 100644 features/c4game/components/status_templ.go
create mode 100644 features/c4game/pages/game.templ
delete mode 100644 features/c4game/pages/game_templ.go
delete mode 100644 features/common/components/shared_templ.go
create mode 100644 features/common/layouts/base.templ
delete mode 100644 features/common/layouts/base_templ.go
create mode 100644 features/lobby/components/gamelist.templ
delete mode 100644 features/lobby/components/gamelist_templ.go
create mode 100644 features/lobby/pages/lobby.templ
delete mode 100644 features/lobby/pages/lobby_templ.go
create mode 100644 features/snakegame/components/board.templ
delete mode 100644 features/snakegame/components/board_templ.go
create mode 100644 features/snakegame/components/chat.templ
delete mode 100644 features/snakegame/components/chat_templ.go
create mode 100644 features/snakegame/components/status.templ
delete mode 100644 features/snakegame/components/status_templ.go
create mode 100644 features/snakegame/pages/game.templ
delete mode 100644 features/snakegame/pages/game_templ.go
diff --git a/.gitignore b/.gitignore
index 6a7aed8..90c8dd5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,7 +22,8 @@
!assets/**/*
-# Generated CSS stays out of version control
+# Generated files stay out of version control
+*_templ.go
assets/css/output.css
# Deploy scripts and configs
diff --git a/Taskfile.yml b/Taskfile.yml
index 7e8f9b6..e0df8ef 100644
--- a/Taskfile.yml
+++ b/Taskfile.yml
@@ -6,12 +6,22 @@ tasks:
cmds:
- go run cmd/downloader/main.go
+ build:templ:
+ desc: Compile .templ files to Go
+ cmds:
+ - go tool templ generate
+ sources:
+ - "**/*.templ"
+ generates:
+ - "**/*_templ.go"
+
build:styles:
desc: Build TailwindCSS styles
cmds:
- go tool gotailwind -i assets/css/input.css -o assets/css/output.css --minify
sources:
- "assets/css/input.css"
+ - "**/*.templ"
- "**/*.go"
generates:
- "assets/css/output.css"
@@ -21,8 +31,14 @@ tasks:
cmds:
- go build -o bin/c4 .
deps:
+ - build:templ
- build:styles
+ live:templ:
+ desc: Watch and recompile .templ files
+ cmds:
+ - go tool templ generate -watch
+
live:styles:
desc: Watch and rebuild TailwindCSS styles
cmds:
@@ -36,12 +52,13 @@ tasks:
-build.cmd "go build -tags=dev -o tmp/bin/c4 ." \
-build.bin "tmp/bin/c4" \
-build.exclude_dir "data,bin,tmp,deploy" \
- -build.include_ext "go" \
+ -build.include_ext "go,templ" \
-misc.clean_on_exit "true"
live:
desc: Dev mode with hot-reload
deps:
+ - live:templ
- live:styles
- live:server
diff --git a/features/auth/pages/login_templ.go b/features/auth/pages/login_templ.go
deleted file mode 100644
index 55ae981..0000000
--- a/features/auth/pages/login_templ.go
+++ /dev/null
@@ -1,102 +0,0 @@
-// Code generated by templ - DO NOT EDIT.
-
-// templ: version: v0.3.1001
-package pages
-
-//lint:file-ignore SA4006 This context is only used if a nested component is present.
-
-import "github.com/a-h/templ"
-import templruntime "github.com/a-h/templ/runtime"
-
-import (
- "github.com/ryanhamamura/c4/features/common/layouts"
- "github.com/starfederation/datastar-go/datastar"
-)
-
-func LoginPage() templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var1 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var1 == nil {
- templ_7745c5c3_Var1 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "Login Sign in to your account
Username Password Login Don't have an account? Register
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
- templ_7745c5c3_Err = layouts.Base("Login").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-var _ = templruntime.GeneratedTemplate
diff --git a/features/auth/pages/register_templ.go b/features/auth/pages/register_templ.go
deleted file mode 100644
index c7961d5..0000000
--- a/features/auth/pages/register_templ.go
+++ /dev/null
@@ -1,115 +0,0 @@
-// Code generated by templ - DO NOT EDIT.
-
-// templ: version: v0.3.1001
-package pages
-
-//lint:file-ignore SA4006 This context is only used if a nested component is present.
-
-import "github.com/a-h/templ"
-import templruntime "github.com/a-h/templ/runtime"
-
-import (
- "github.com/ryanhamamura/c4/features/common/layouts"
- "github.com/starfederation/datastar-go/datastar"
-)
-
-func RegisterPage() templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var1 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var1 == nil {
- templ_7745c5c3_Var1 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "Register Create a new account
Username Password Confirm Password Register Already have an account? Login
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
- templ_7745c5c3_Err = layouts.Base("Register").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-var _ = templruntime.GeneratedTemplate
diff --git a/features/c4game/components/board.templ b/features/c4game/components/board.templ
new file mode 100644
index 0000000..ee4cb72
--- /dev/null
+++ b/features/c4game/components/board.templ
@@ -0,0 +1,65 @@
+package components
+
+import (
+ "fmt"
+
+ "github.com/ryanhamamura/c4/game"
+ "github.com/starfederation/datastar-go/datastar"
+)
+
+templ Board(g *game.Game, myColor int) {
+
+ for col := 0; col < 7; col++ {
+ @column(g, col, myColor)
+ }
+
+}
+
+templ column(g *game.Game, colIdx int, myColor int) {
+ if g.Status == game.StatusInProgress && myColor == g.CurrentTurn {
+
+ for row := 0; row < 6; row++ {
+ @cell(g, row, colIdx)
+ }
+
+ } else {
+
+ for row := 0; row < 6; row++ {
+ @cell(g, row, colIdx)
+ }
+
+ }
+}
+
+templ cell(g *game.Game, row int, col int) {
+
+}
+
+func cellClass(g *game.Game, row, col int) string {
+ color := g.Board[row][col]
+ activeTurn := 0
+ if g.Status == game.StatusInProgress {
+ activeTurn = g.CurrentTurn
+ }
+
+ class := "cell"
+ switch color {
+ case 1:
+ class += " red"
+ case 2:
+ class += " yellow"
+ }
+ if g.IsWinningCell(row, col) {
+ class += " winning"
+ }
+ if color != 0 && color == activeTurn {
+ class += " active-turn"
+ }
+ return class
+}
+
+// suppress unused import
+var _ = fmt.Sprintf
diff --git a/features/c4game/components/board_templ.go b/features/c4game/components/board_templ.go
deleted file mode 100644
index 7c638be..0000000
--- a/features/c4game/components/board_templ.go
+++ /dev/null
@@ -1,199 +0,0 @@
-// Code generated by templ - DO NOT EDIT.
-
-// templ: version: v0.3.1001
-package components
-
-//lint:file-ignore SA4006 This context is only used if a nested component is present.
-
-import "github.com/a-h/templ"
-import templruntime "github.com/a-h/templ/runtime"
-
-import (
- "fmt"
-
- "github.com/ryanhamamura/c4/game"
- "github.com/starfederation/datastar-go/datastar"
-)
-
-func Board(g *game.Game, myColor int) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var1 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var1 == nil {
- templ_7745c5c3_Var1 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- for col := 0; col < 7; col++ {
- templ_7745c5c3_Err = column(g, col, myColor).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func column(g *game.Game, colIdx int, myColor int) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var2 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var2 == nil {
- templ_7745c5c3_Var2 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- if g.Status == game.StatusInProgress && myColor == g.CurrentTurn {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- for row := 0; row < 6; row++ {
- templ_7745c5c3_Err = cell(g, row, colIdx).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- } else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- for row := 0; row < 6; row++ {
- templ_7745c5c3_Err = cell(g, row, colIdx).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- return nil
- })
-}
-
-func cell(g *game.Game, row int, col int) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var4 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var4 == nil {
- templ_7745c5c3_Var4 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- var templ_7745c5c3_Var5 = []any{cellClass(g, row, col)}
- templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func cellClass(g *game.Game, row, col int) string {
- color := g.Board[row][col]
- activeTurn := 0
- if g.Status == game.StatusInProgress {
- activeTurn = g.CurrentTurn
- }
-
- class := "cell"
- switch color {
- case 1:
- class += " red"
- case 2:
- class += " yellow"
- }
- if g.IsWinningCell(row, col) {
- class += " winning"
- }
- if color != 0 && color == activeTurn {
- class += " active-turn"
- }
- return class
-}
-
-// suppress unused import
-var _ = fmt.Sprintf
-
-var _ = templruntime.GeneratedTemplate
diff --git a/features/c4game/components/chat.templ b/features/c4game/components/chat.templ
new file mode 100644
index 0000000..c1e6c07
--- /dev/null
+++ b/features/c4game/components/chat.templ
@@ -0,0 +1,69 @@
+package components
+
+import (
+ "fmt"
+
+ "github.com/starfederation/datastar-go/datastar"
+)
+
+type ChatMessage struct {
+ Nickname string `json:"nickname"`
+ Color int `json:"color"`
+ Message string `json:"message"`
+ Time int64 `json:"time"`
+}
+
+var chatColors = map[int]string{
+ 1: "#4a2a3a",
+ 2: "#2a4545",
+}
+
+templ Chat(messages []ChatMessage, gameID string) {
+
+
+ for _, m := range messages {
+
+
+ { m.Nickname }:
+
+ { m.Message }
+
+ }
+ @chatAutoScroll()
+
+
+
+
+ Send
+
+
+
+}
+
+templ chatAutoScroll() {
+
+}
+
+func chatColor(color int) string {
+ if c, ok := chatColors[color]; ok {
+ return c
+ }
+ return "#666"
+}
diff --git a/features/c4game/components/chat_templ.go b/features/c4game/components/chat_templ.go
deleted file mode 100644
index b70da12..0000000
--- a/features/c4game/components/chat_templ.go
+++ /dev/null
@@ -1,173 +0,0 @@
-// Code generated by templ - DO NOT EDIT.
-
-// templ: version: v0.3.1001
-package components
-
-//lint:file-ignore SA4006 This context is only used if a nested component is present.
-
-import "github.com/a-h/templ"
-import templruntime "github.com/a-h/templ/runtime"
-
-import (
- "fmt"
-
- "github.com/starfederation/datastar-go/datastar"
-)
-
-type ChatMessage struct {
- Nickname string `json:"nickname"`
- Color int `json:"color"`
- Message string `json:"message"`
- Time int64 `json:"time"`
-}
-
-var chatColors = map[int]string{
- 1: "#4a2a3a",
- 2: "#2a4545",
-}
-
-func Chat(messages []ChatMessage, gameID string) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var1 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var1 == nil {
- templ_7745c5c3_Var1 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- for _, m := range messages {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var3 string
- templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(m.Nickname)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/c4game/components/chat.templ`, Line: 27, Col: 18}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, ": ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var4 string
- templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(m.Message)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/c4game/components/chat.templ`, Line: 29, Col: 22}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = chatAutoScroll().Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "
Send
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func chatAutoScroll() templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var7 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var7 == nil {
- templ_7745c5c3_Var7 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func chatColor(color int) string {
- if c, ok := chatColors[color]; ok {
- return c
- }
- return "#666"
-}
-
-var _ = templruntime.GeneratedTemplate
diff --git a/features/c4game/components/status.templ b/features/c4game/components/status.templ
new file mode 100644
index 0000000..d4f4e71
--- /dev/null
+++ b/features/c4game/components/status.templ
@@ -0,0 +1,151 @@
+package components
+
+import (
+ "github.com/ryanhamamura/c4/config"
+ "github.com/ryanhamamura/c4/game"
+ "github.com/starfederation/datastar-go/datastar"
+)
+
+templ StatusBanner(g *game.Game, myColor int) {
+
+ { statusMessage(g, myColor) }
+ if g.IsFinished() {
+ if g.RematchGameID != nil {
+
+ Join Rematch
+
+ } else {
+
+ Play again
+
+ }
+ }
+
+}
+
+templ PlayerInfo(g *game.Game, myColor int) {
+
+ for _, info := range playerInfoPairs(g, myColor) {
+
+
+ { info.Label }
+
+ }
+
+}
+
+templ InviteLink(gameID string) {
+
+
Share this link with your opponent:
+
+ { config.Global.AppURL + "/games/" + gameID }
+
+
+ Copy Link
+
+
+}
+
+script copyToClipboard(url string) {
+ navigator.clipboard.writeText(url)
+}
+
+func statusClass(g *game.Game, myColor int) string {
+ switch g.Status {
+ case game.StatusWaitingForPlayer:
+ return "alert bg-base-200 text-xl font-bold"
+ case game.StatusInProgress:
+ if g.CurrentTurn == myColor {
+ return "alert alert-success text-xl font-bold"
+ }
+ return "alert bg-base-200 text-xl font-bold"
+ case game.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 game.StatusDraw:
+ return "alert alert-warning text-xl font-bold"
+ }
+ return "alert bg-base-200 text-xl font-bold"
+}
+
+func statusMessage(g *game.Game, myColor int) string {
+ switch g.Status {
+ case game.StatusWaitingForPlayer:
+ return "Waiting for opponent..."
+ case game.StatusInProgress:
+ if g.CurrentTurn == myColor {
+ return "Your turn!"
+ }
+ return opponentName(g, myColor) + "'s turn"
+ case game.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 game.StatusDraw:
+ return "It's a draw!"
+ }
+ return ""
+}
+
+func opponentName(g *game.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 *game.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
+}
diff --git a/features/c4game/components/status_templ.go b/features/c4game/components/status_templ.go
deleted file mode 100644
index c87c799..0000000
--- a/features/c4game/components/status_templ.go
+++ /dev/null
@@ -1,352 +0,0 @@
-// Code generated by templ - DO NOT EDIT.
-
-// templ: version: v0.3.1001
-package components
-
-//lint:file-ignore SA4006 This context is only used if a nested component is present.
-
-import "github.com/a-h/templ"
-import templruntime "github.com/a-h/templ/runtime"
-
-import (
- "github.com/ryanhamamura/c4/config"
- "github.com/ryanhamamura/c4/game"
- "github.com/starfederation/datastar-go/datastar"
-)
-
-func StatusBanner(g *game.Game, myColor int) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var1 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var1 == nil {
- templ_7745c5c3_Var1 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- var templ_7745c5c3_Var2 = []any{statusClass(g, myColor)}
- templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var4 string
- templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(statusMessage(g, myColor))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/c4game/components/status.templ`, Line: 11, Col: 29}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- if g.IsFinished() {
- if g.RematchGameID != nil {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
Join Rematch ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- } else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "
Play again ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func PlayerInfo(g *game.Game, myColor int) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var7 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var7 == nil {
- templ_7745c5c3_Var7 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- for _, info := range playerInfoPairs(g, myColor) {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var8 = []any{"player-chip " + info.ColorClass}
- templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var8...)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var10 string
- templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(info.Label)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/c4game/components/status.templ`, Line: 38, Col: 22}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func InviteLink(gameID string) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var11 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var11 == nil {
- templ_7745c5c3_Var11 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "Share this link with your opponent:
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var12 string
- templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(config.Global.AppURL + "/games/" + gameID)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/c4game/components/status.templ`, Line: 48, Col: 46}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, copyToClipboard(config.Global.AppURL+"/games/"+gameID))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "
Copy Link ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func copyToClipboard(url string) templ.ComponentScript {
- return templ.ComponentScript{
- Name: `__templ_copyToClipboard_1463`,
- Function: `function __templ_copyToClipboard_1463(url){navigator.clipboard.writeText(url)
-}`,
- Call: templ.SafeScript(`__templ_copyToClipboard_1463`, url),
- CallInline: templ.SafeScriptInline(`__templ_copyToClipboard_1463`, url),
- }
-}
-
-func statusClass(g *game.Game, myColor int) string {
- switch g.Status {
- case game.StatusWaitingForPlayer:
- return "alert bg-base-200 text-xl font-bold"
- case game.StatusInProgress:
- if g.CurrentTurn == myColor {
- return "alert alert-success text-xl font-bold"
- }
- return "alert bg-base-200 text-xl font-bold"
- case game.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 game.StatusDraw:
- return "alert alert-warning text-xl font-bold"
- }
- return "alert bg-base-200 text-xl font-bold"
-}
-
-func statusMessage(g *game.Game, myColor int) string {
- switch g.Status {
- case game.StatusWaitingForPlayer:
- return "Waiting for opponent..."
- case game.StatusInProgress:
- if g.CurrentTurn == myColor {
- return "Your turn!"
- }
- return opponentName(g, myColor) + "'s turn"
- case game.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 game.StatusDraw:
- return "It's a draw!"
- }
- return ""
-}
-
-func opponentName(g *game.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 *game.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
-}
-
-var _ = templruntime.GeneratedTemplate
diff --git a/features/c4game/pages/game.templ b/features/c4game/pages/game.templ
new file mode 100644
index 0000000..eb328ad
--- /dev/null
+++ b/features/c4game/pages/game.templ
@@ -0,0 +1,47 @@
+package pages
+
+import (
+ "github.com/ryanhamamura/c4/features/c4game/components"
+ sharedcomponents "github.com/ryanhamamura/c4/features/common/components"
+ "github.com/ryanhamamura/c4/features/common/layouts"
+ "github.com/ryanhamamura/c4/game"
+ "github.com/starfederation/datastar-go/datastar"
+)
+
+templ GamePage(g *game.Game, myColor int, messages []components.ChatMessage) {
+ @layouts.Base("Connect 4") {
+
+ @sharedcomponents.BackToLobby()
+ @sharedcomponents.StealthTitle("text-3xl font-bold")
+ @components.PlayerInfo(g, myColor)
+ @components.StatusBanner(g, myColor)
+
+ @components.Board(g, myColor)
+ @components.Chat(messages, g.ID)
+
+ if g.Status == game.StatusWaitingForPlayer {
+ @components.InviteLink(g.ID)
+ }
+
+ }
+}
+
+templ JoinPage(gameID string) {
+ @layouts.Base("Connect 4 - Join") {
+ @sharedcomponents.GameJoinPrompt(
+ "/login?return_url=/games/"+gameID,
+ "/register?return_url=/games/"+gameID,
+ "/games/"+gameID,
+ )
+ }
+}
+
+templ NicknamePage(gameID string) {
+ @layouts.Base("Connect 4 - Join") {
+ @sharedcomponents.NicknamePrompt("/games/" + gameID + "/join")
+ }
+}
diff --git a/features/c4game/pages/game_templ.go b/features/c4game/pages/game_templ.go
deleted file mode 100644
index 903e9a3..0000000
--- a/features/c4game/pages/game_templ.go
+++ /dev/null
@@ -1,219 +0,0 @@
-// Code generated by templ - DO NOT EDIT.
-
-// templ: version: v0.3.1001
-package pages
-
-//lint:file-ignore SA4006 This context is only used if a nested component is present.
-
-import "github.com/a-h/templ"
-import templruntime "github.com/a-h/templ/runtime"
-
-import (
- "github.com/ryanhamamura/c4/features/c4game/components"
- sharedcomponents "github.com/ryanhamamura/c4/features/common/components"
- "github.com/ryanhamamura/c4/features/common/layouts"
- "github.com/ryanhamamura/c4/game"
- "github.com/starfederation/datastar-go/datastar"
-)
-
-func GamePage(g *game.Game, myColor int, messages []components.ChatMessage) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var1 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var1 == nil {
- templ_7745c5c3_Var1 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = sharedcomponents.BackToLobby().Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = sharedcomponents.StealthTitle("text-3xl font-bold").Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = components.PlayerInfo(g, myColor).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = components.StatusBanner(g, myColor).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = components.Board(g, myColor).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = components.Chat(messages, g.ID).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- if g.Status == game.StatusWaitingForPlayer {
- templ_7745c5c3_Err = components.InviteLink(g.ID).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
- templ_7745c5c3_Err = layouts.Base("Connect 4").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func JoinPage(gameID string) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var4 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var4 == nil {
- templ_7745c5c3_Var4 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Var5 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = sharedcomponents.GameJoinPrompt(
- "/login?return_url=/games/"+gameID,
- "/register?return_url=/games/"+gameID,
- "/games/"+gameID,
- ).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
- templ_7745c5c3_Err = layouts.Base("Connect 4 - Join").Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func NicknamePage(gameID string) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var6 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var6 == nil {
- templ_7745c5c3_Var6 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Var7 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = sharedcomponents.NicknamePrompt("/games/"+gameID+"/join").Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
- templ_7745c5c3_Err = layouts.Base("Connect 4 - Join").Render(templ.WithChildren(ctx, templ_7745c5c3_Var7), templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-var _ = templruntime.GeneratedTemplate
diff --git a/features/common/components/shared_templ.go b/features/common/components/shared_templ.go
deleted file mode 100644
index 7341d8c..0000000
--- a/features/common/components/shared_templ.go
+++ /dev/null
@@ -1,212 +0,0 @@
-// Code generated by templ - DO NOT EDIT.
-
-// templ: version: v0.3.1001
-package components
-
-//lint:file-ignore SA4006 This context is only used if a nested component is present.
-
-import "github.com/a-h/templ"
-import templruntime "github.com/a-h/templ/runtime"
-
-import "github.com/starfederation/datastar-go/datastar"
-
-func BackToLobby() templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var1 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var1 == nil {
- templ_7745c5c3_Var1 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "← Back ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func StealthTitle(class string) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var2 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var2 == nil {
- templ_7745c5c3_Var2 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- var templ_7745c5c3_Var3 = []any{class}
- templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "● ● ● ● ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func NicknamePrompt(returnPath string) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var5 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var5 == nil {
- templ_7745c5c3_Var5 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "Join Game Enter your nickname to join the game.
Your Nickname Join ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func GameJoinPrompt(loginURL string, registerURL string, gamePath string) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var8 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var8 == nil {
- templ_7745c5c3_Var8 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "Join Game Log in to track your game history, or continue as a guest.
Don't have an account? Register
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-var _ = templruntime.GeneratedTemplate
diff --git a/features/common/layouts/base.templ b/features/common/layouts/base.templ
new file mode 100644
index 0000000..ffd9585
--- /dev/null
+++ b/features/common/layouts/base.templ
@@ -0,0 +1,21 @@
+package layouts
+
+import "github.com/ryanhamamura/c4/config"
+
+templ Base(title string) {
+
+
+
+ { title }
+
+
+
+
+
+ if config.Global.Environment == config.Dev {
+
+ }
+ { children... }
+
+
+}
diff --git a/features/common/layouts/base_templ.go b/features/common/layouts/base_templ.go
deleted file mode 100644
index 083a510..0000000
--- a/features/common/layouts/base_templ.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// Code generated by templ - DO NOT EDIT.
-
-// templ: version: v0.3.1001
-package layouts
-
-//lint:file-ignore SA4006 This context is only used if a nested component is present.
-
-import "github.com/a-h/templ"
-import templruntime "github.com/a-h/templ/runtime"
-
-import "github.com/ryanhamamura/c4/config"
-
-func Base(title string) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var1 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var1 == nil {
- templ_7745c5c3_Var1 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var2 string
- templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/common/layouts/base.templ`, Line: 9, Col: 17}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- if config.Global.Environment == config.Dev {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-var _ = templruntime.GeneratedTemplate
diff --git a/features/lobby/components/gamelist.templ b/features/lobby/components/gamelist.templ
new file mode 100644
index 0000000..24563e5
--- /dev/null
+++ b/features/lobby/components/gamelist.templ
@@ -0,0 +1,109 @@
+package components
+
+import (
+ "fmt"
+ "time"
+
+ "github.com/ryanhamamura/c4/game"
+ "github.com/starfederation/datastar-go/datastar"
+)
+
+templ GameList(games []GameListItem) {
+ if len(games) > 0 {
+
+
Your Games
+
+ for _, g := range games {
+ @gameListEntry(g)
+ }
+
+
+ }
+}
+
+templ gameListEntry(g GameListItem) {
+
+}
+
+func statusText(g GameListItem) string {
+ switch game.GameStatus(g.Status) {
+ case game.StatusWaitingForPlayer:
+ return "Waiting for opponent"
+ case game.StatusInProgress:
+ if g.IsMyTurn {
+ return "Your turn!"
+ }
+ return "Opponent's turn"
+ }
+ return ""
+}
+
+func statusClass(g GameListItem) string {
+ switch game.GameStatus(g.Status) {
+ case game.StatusWaitingForPlayer:
+ return "text-sm opacity-60"
+ case game.StatusInProgress:
+ if g.IsMyTurn {
+ return "text-sm text-success font-bold"
+ }
+ return "text-sm"
+ }
+ return ""
+}
+
+func opponentDisplay(g GameListItem) string {
+ if g.OpponentName == "" {
+ return "Waiting for opponent..."
+ }
+ return "vs " + g.OpponentName
+}
+
+func formatTimeAgo(t time.Time) string {
+ if t.IsZero() {
+ return ""
+ }
+ duration := time.Since(t)
+
+ if duration < time.Minute {
+ return "just now"
+ }
+ if duration < time.Hour {
+ mins := int(duration.Minutes())
+ if mins == 1 {
+ return "1 minute ago"
+ }
+ return fmt.Sprintf("%d minutes ago", mins)
+ }
+ if duration < 24*time.Hour {
+ hours := int(duration.Hours())
+ if hours == 1 {
+ return "1 hour ago"
+ }
+ return fmt.Sprintf("%d hours ago", hours)
+ }
+ days := int(duration.Hours() / 24)
+ if days == 1 {
+ return "yesterday"
+ }
+ return fmt.Sprintf("%d days ago", days)
+}
diff --git a/features/lobby/components/gamelist_templ.go b/features/lobby/components/gamelist_templ.go
deleted file mode 100644
index 4157630..0000000
--- a/features/lobby/components/gamelist_templ.go
+++ /dev/null
@@ -1,239 +0,0 @@
-// Code generated by templ - DO NOT EDIT.
-
-// templ: version: v0.3.1001
-package components
-
-//lint:file-ignore SA4006 This context is only used if a nested component is present.
-
-import "github.com/a-h/templ"
-import templruntime "github.com/a-h/templ/runtime"
-
-import (
- "fmt"
- "time"
-
- "github.com/ryanhamamura/c4/game"
- "github.com/starfederation/datastar-go/datastar"
-)
-
-func GameList(games []GameListItem) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var1 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var1 == nil {
- templ_7745c5c3_Var1 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- if len(games) > 0 {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "Your Games ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- for _, g := range games {
- templ_7745c5c3_Err = gameListEntry(g).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- return nil
- })
-}
-
-func gameListEntry(g GameListItem) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var2 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var2 == nil {
- templ_7745c5c3_Var2 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var4 string
- templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(opponentDisplay(g))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/lobby/components/gamelist.templ`, Line: 31, Col: 48}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var5 = []any{statusClass(g)}
- templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var7 string
- templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(statusText(g))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/lobby/components/gamelist.templ`, Line: 32, Col: 50}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var8 string
- templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(formatTimeAgo(g.LastPlayed))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/lobby/components/gamelist.templ`, Line: 35, Col: 66}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "
× ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func statusText(g GameListItem) string {
- switch game.GameStatus(g.Status) {
- case game.StatusWaitingForPlayer:
- return "Waiting for opponent"
- case game.StatusInProgress:
- if g.IsMyTurn {
- return "Your turn!"
- }
- return "Opponent's turn"
- }
- return ""
-}
-
-func statusClass(g GameListItem) string {
- switch game.GameStatus(g.Status) {
- case game.StatusWaitingForPlayer:
- return "text-sm opacity-60"
- case game.StatusInProgress:
- if g.IsMyTurn {
- return "text-sm text-success font-bold"
- }
- return "text-sm"
- }
- return ""
-}
-
-func opponentDisplay(g GameListItem) string {
- if g.OpponentName == "" {
- return "Waiting for opponent..."
- }
- return "vs " + g.OpponentName
-}
-
-func formatTimeAgo(t time.Time) string {
- if t.IsZero() {
- return ""
- }
- duration := time.Since(t)
-
- if duration < time.Minute {
- return "just now"
- }
- if duration < time.Hour {
- mins := int(duration.Minutes())
- if mins == 1 {
- return "1 minute ago"
- }
- return fmt.Sprintf("%d minutes ago", mins)
- }
- if duration < 24*time.Hour {
- hours := int(duration.Hours())
- if hours == 1 {
- return "1 hour ago"
- }
- return fmt.Sprintf("%d hours ago", hours)
- }
- days := int(duration.Hours() / 24)
- if days == 1 {
- return "yesterday"
- }
- return fmt.Sprintf("%d days ago", days)
-}
-
-var _ = templruntime.GeneratedTemplate
diff --git a/features/lobby/pages/lobby.templ b/features/lobby/pages/lobby.templ
new file mode 100644
index 0000000..cff0080
--- /dev/null
+++ b/features/lobby/pages/lobby.templ
@@ -0,0 +1,171 @@
+package pages
+
+import (
+ "fmt"
+
+ "github.com/ryanhamamura/c4/features/common/components"
+ "github.com/ryanhamamura/c4/features/common/layouts"
+ lobbycomponents "github.com/ryanhamamura/c4/features/lobby/components"
+ "github.com/ryanhamamura/c4/snake"
+ "github.com/starfederation/datastar-go/datastar"
+)
+
+templ LobbyPage(data LobbyData) {
+ @layouts.Base("Game Lobby") {
+
+ // Auth header
+ if data.IsLoggedIn {
+
+ Logged in as { data.Username }
+
+ Logout
+
+
+ } else {
+
+ Playing as guest.
+
Login
+ or
+
Register
+ to save your games.
+
+ }
+ // Title
+
+ @components.StealthTitle("")
+
+ // Tab buttons
+
+
+ @components.StealthTitle("")
+
+
+ ~~~~
+
+
+ // Connect4 tab
+
+
Start a new session
+
+
+ Your Nickname
+
+
+
+ Create Game
+
+
+ @lobbycomponents.GameList(data.UserGames)
+
+ // Snake tab
+
+ // Nickname
+
+
+ Your Nickname
+
+
+
+ // Speed selector
+
+
Speed
+
+ for i, preset := range snake.SpeedPresets {
+
+ { preset.Name }
+
+ }
+
+
+ // Solo play
+
+
Play Solo
+
+ for i, preset := range snake.GridPresets {
+
+ { fmt.Sprintf("%s (%d\u00d7%d)", preset.Name, preset.Width, preset.Height) }
+
+ }
+
+
+ // Multiplayer
+
+
Create Multiplayer Game
+
+ for i, preset := range snake.GridPresets {
+
+ { fmt.Sprintf("%s (%d\u00d7%d)", preset.Name, preset.Width, preset.Height) }
+
+ }
+
+
+ // Active snake games
+ if len(data.ActiveSnakeGames) > 0 {
+
+ }
+
+
+ }
+}
diff --git a/features/lobby/pages/lobby_templ.go b/features/lobby/pages/lobby_templ.go
deleted file mode 100644
index 9e11bd7..0000000
--- a/features/lobby/pages/lobby_templ.go
+++ /dev/null
@@ -1,339 +0,0 @@
-// Code generated by templ - DO NOT EDIT.
-
-// templ: version: v0.3.1001
-package pages
-
-//lint:file-ignore SA4006 This context is only used if a nested component is present.
-
-import "github.com/a-h/templ"
-import templruntime "github.com/a-h/templ/runtime"
-
-import (
- "fmt"
-
- "github.com/ryanhamamura/c4/features/common/components"
- "github.com/ryanhamamura/c4/features/common/layouts"
- lobbycomponents "github.com/ryanhamamura/c4/features/lobby/components"
- "github.com/ryanhamamura/c4/snake"
- "github.com/starfederation/datastar-go/datastar"
-)
-
-func LobbyPage(data LobbyData) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var1 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var1 == nil {
- templ_7745c5c3_Var1 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- if data.IsLoggedIn {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "Logged in as ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var3 string
- templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(data.Username)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/lobby/pages/lobby.templ`, Line: 22, Col: 47}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, " Logout
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- } else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = components.StealthTitle("").Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = components.StealthTitle("").Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, " ~~~~
Your Nickname Speed ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- for i, preset := range snake.SpeedPresets {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var9 string
- templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(preset.Name)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/lobby/pages/lobby.templ`, Line: 116, Col: 21}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "
Play Solo ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- for i, preset := range snake.GridPresets {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var11 string
- templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%s (%d\u00d7%d)", preset.Name, preset.Width, preset.Height))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/lobby/pages/lobby.templ`, Line: 131, Col: 82}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "
Create Multiplayer Game ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- for i, preset := range snake.GridPresets {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var13 string
- templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%s (%d\u00d7%d)", preset.Name, preset.Width, preset.Height))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/lobby/pages/lobby.templ`, Line: 146, Col: 82}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- if len(data.ActiveSnakeGames) > 0 {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "
Join a Game ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- for _, g := range data.ActiveSnakeGames {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var15 string
- templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d\u00d7%d \u2014 %d/8 players", g.Width, g.Height, g.PlayerCount))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/lobby/pages/lobby.templ`, Line: 161, Col: 96}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var16 string
- templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(g.StatusLabel)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/lobby/pages/lobby.templ`, Line: 162, Col: 57}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
- templ_7745c5c3_Err = layouts.Base("Game Lobby").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-var _ = templruntime.GeneratedTemplate
diff --git a/features/snakegame/components/board.templ b/features/snakegame/components/board.templ
new file mode 100644
index 0000000..6083935
--- /dev/null
+++ b/features/snakegame/components/board.templ
@@ -0,0 +1,113 @@
+package components
+
+import (
+ "fmt"
+
+ "github.com/ryanhamamura/c4/snake"
+)
+
+func cellSizeForGrid(width, height int) int {
+ maxDim := width
+ if height > maxDim {
+ maxDim = height
+ }
+ switch {
+ case maxDim <= 15:
+ return 28
+ case maxDim <= 20:
+ return 24
+ case maxDim <= 30:
+ return 20
+ case maxDim <= 40:
+ return 16
+ default:
+ return 14
+ }
+}
+
+type cellInfo struct {
+ snakeIdx int // -1 = empty, -2 = food
+ isHead bool
+}
+
+templ Board(sg *snake.SnakeGame) {
+
+ if sg.State != nil && (sg.Status == snake.StatusInProgress || sg.Status == snake.StatusFinished) {
+ @boardCells(sg)
+ }
+
+}
+
+templ boardCells(sg *snake.SnakeGame) {
+ {{ state := sg.State }}
+ {{ grid := buildGrid(state) }}
+ {{ cellSize := cellSizeForGrid(state.Width, state.Height) }}
+ for y := 0; y < state.Height; y++ {
+
+ for x := 0; x < state.Width; x++ {
+ {{ ci := grid[y][x] }}
+ if ci.snakeIdx == -2 {
+
+ } else if ci.snakeIdx >= 0 {
+ {{ s := state.Snakes[ci.snakeIdx] }}
+ {{ bg := snakeColor(ci.snakeIdx) }}
+ if ci.isHead {
+ if s.Alive {
+
+ } else {
+
+ }
+ } else {
+ if s.Alive {
+
+ } else {
+
+ }
+ }
+ } else {
+
+ }
+ }
+
+ }
+}
+
+func buildGrid(state *snake.GameState) [][]cellInfo {
+ grid := make([][]cellInfo, state.Height)
+ for y := 0; y < state.Height; y++ {
+ grid[y] = make([]cellInfo, state.Width)
+ for x := 0; x < state.Width; x++ {
+ grid[y][x] = cellInfo{snakeIdx: -1}
+ }
+ }
+ for fi := range state.Food {
+ f := state.Food[fi]
+ if f.X >= 0 && f.X < state.Width && f.Y >= 0 && f.Y < state.Height {
+ grid[f.Y][f.X] = cellInfo{snakeIdx: -2}
+ }
+ }
+ for si, s := range state.Snakes {
+ if s == nil {
+ continue
+ }
+ for bi, bp := range s.Body {
+ if bp.X >= 0 && bp.X < state.Width && bp.Y >= 0 && bp.Y < state.Height {
+ grid[bp.Y][bp.X] = cellInfo{snakeIdx: si, isHead: bi == 0}
+ }
+ }
+ }
+ return grid
+}
+
+func snakeColor(idx int) string {
+ if idx >= 0 && idx < len(snake.SnakeColors) {
+ return snake.SnakeColors[idx]
+ }
+ return "#666"
+}
diff --git a/features/snakegame/components/board_templ.go b/features/snakegame/components/board_templ.go
deleted file mode 100644
index cbe1237..0000000
--- a/features/snakegame/components/board_templ.go
+++ /dev/null
@@ -1,295 +0,0 @@
-// Code generated by templ - DO NOT EDIT.
-
-// templ: version: v0.3.1001
-package components
-
-//lint:file-ignore SA4006 This context is only used if a nested component is present.
-
-import "github.com/a-h/templ"
-import templruntime "github.com/a-h/templ/runtime"
-
-import (
- "fmt"
-
- "github.com/ryanhamamura/c4/snake"
-)
-
-func cellSizeForGrid(width, height int) int {
- maxDim := width
- if height > maxDim {
- maxDim = height
- }
- switch {
- case maxDim <= 15:
- return 28
- case maxDim <= 20:
- return 24
- case maxDim <= 30:
- return 20
- case maxDim <= 40:
- return 16
- default:
- return 14
- }
-}
-
-type cellInfo struct {
- snakeIdx int // -1 = empty, -2 = food
- isHead bool
-}
-
-func Board(sg *snake.SnakeGame) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var1 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var1 == nil {
- templ_7745c5c3_Var1 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- if sg.State != nil && (sg.Status == snake.StatusInProgress || sg.Status == snake.StatusFinished) {
- templ_7745c5c3_Err = boardCells(sg).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func boardCells(sg *snake.SnakeGame) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var3 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var3 == nil {
- templ_7745c5c3_Var3 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- state := sg.State
- grid := buildGrid(state)
- cellSize := cellSizeForGrid(state.Width, state.Height)
- for y := 0; y < state.Height; y++ {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- for x := 0; x < state.Width; x++ {
- ci := grid[y][x]
- if ci.snakeIdx == -2 {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- } else if ci.snakeIdx >= 0 {
- s := state.Snakes[ci.snakeIdx]
- bg := snakeColor(ci.snakeIdx)
- if ci.isHead {
- if s.Alive {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- } else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- } else {
- if s.Alive {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- } else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- }
- } else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- return nil
- })
-}
-
-func buildGrid(state *snake.GameState) [][]cellInfo {
- grid := make([][]cellInfo, state.Height)
- for y := 0; y < state.Height; y++ {
- grid[y] = make([]cellInfo, state.Width)
- for x := 0; x < state.Width; x++ {
- grid[y][x] = cellInfo{snakeIdx: -1}
- }
- }
- for fi := range state.Food {
- f := state.Food[fi]
- if f.X >= 0 && f.X < state.Width && f.Y >= 0 && f.Y < state.Height {
- grid[f.Y][f.X] = cellInfo{snakeIdx: -2}
- }
- }
- for si, s := range state.Snakes {
- if s == nil {
- continue
- }
- for bi, bp := range s.Body {
- if bp.X >= 0 && bp.X < state.Width && bp.Y >= 0 && bp.Y < state.Height {
- grid[bp.Y][bp.X] = cellInfo{snakeIdx: si, isHead: bi == 0}
- }
- }
- }
- return grid
-}
-
-func snakeColor(idx int) string {
- if idx >= 0 && idx < len(snake.SnakeColors) {
- return snake.SnakeColors[idx]
- }
- return "#666"
-}
-
-var _ = templruntime.GeneratedTemplate
diff --git a/features/snakegame/components/chat.templ b/features/snakegame/components/chat.templ
new file mode 100644
index 0000000..58c137b
--- /dev/null
+++ b/features/snakegame/components/chat.templ
@@ -0,0 +1,66 @@
+package components
+
+import (
+ "fmt"
+
+ "github.com/ryanhamamura/c4/snake"
+ "github.com/starfederation/datastar-go/datastar"
+)
+
+type ChatMessage struct {
+ Nickname string `json:"nickname"`
+ Slot int `json:"slot"`
+ Message string `json:"message"`
+ Time int64 `json:"time"`
+}
+
+templ Chat(messages []ChatMessage, gameID string) {
+
+
+ for _, m := range messages {
+
+
+ { m.Nickname + ": " }
+
+ { m.Message }
+
+ }
+
+
+
+
+ Send
+
+
+ @chatAutoScroll()
+
+}
+
+templ chatAutoScroll() {
+
+}
+
+func chatColor(slot int) string {
+ if slot >= 0 && slot < len(snake.SnakeColors) {
+ return snake.SnakeColors[slot]
+ }
+ return "#666"
+}
diff --git a/features/snakegame/components/chat_templ.go b/features/snakegame/components/chat_templ.go
deleted file mode 100644
index db1946e..0000000
--- a/features/snakegame/components/chat_templ.go
+++ /dev/null
@@ -1,173 +0,0 @@
-// Code generated by templ - DO NOT EDIT.
-
-// templ: version: v0.3.1001
-package components
-
-//lint:file-ignore SA4006 This context is only used if a nested component is present.
-
-import "github.com/a-h/templ"
-import templruntime "github.com/a-h/templ/runtime"
-
-import (
- "fmt"
-
- "github.com/ryanhamamura/c4/snake"
- "github.com/starfederation/datastar-go/datastar"
-)
-
-type ChatMessage struct {
- Nickname string `json:"nickname"`
- Slot int `json:"slot"`
- Message string `json:"message"`
- Time int64 `json:"time"`
-}
-
-func Chat(messages []ChatMessage, gameID string) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var1 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var1 == nil {
- templ_7745c5c3_Var1 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- for _, m := range messages {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var3 string
- templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(m.Nickname + ": ")
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/snakegame/components/chat.templ`, Line: 23, Col: 25}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var4 string
- templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(m.Message)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/snakegame/components/chat.templ`, Line: 25, Col: 22}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "
Send
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = chatAutoScroll().Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func chatAutoScroll() templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var7 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var7 == nil {
- templ_7745c5c3_Var7 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func chatColor(slot int) string {
- if slot >= 0 && slot < len(snake.SnakeColors) {
- return snake.SnakeColors[slot]
- }
- return "#666"
-}
-
-var _ = templruntime.GeneratedTemplate
diff --git a/features/snakegame/components/status.templ b/features/snakegame/components/status.templ
new file mode 100644
index 0000000..b09613d
--- /dev/null
+++ b/features/snakegame/components/status.templ
@@ -0,0 +1,137 @@
+package components
+
+import (
+ "fmt"
+ "math"
+ "time"
+
+ "github.com/ryanhamamura/c4/config"
+ "github.com/ryanhamamura/c4/snake"
+ "github.com/starfederation/datastar-go/datastar"
+)
+
+templ StatusBanner(sg *snake.SnakeGame, mySlot int, gameID string) {
+
+ switch sg.Status {
+ case snake.StatusWaitingForPlayers:
+ if sg.Mode == snake.ModeSinglePlayer {
+
Ready?
+ } else {
+
Waiting for players...
+ }
+ case snake.StatusCountdown:
+ {{ remaining := time.Until(sg.CountdownEnd) }}
+ {{ secs := int(math.Ceil(remaining.Seconds())) }}
+ if secs < 0 {
+ {{ secs = 0 }}
+ }
+
+ { fmt.Sprintf("Starting in %d...", secs) }
+
+ case snake.StatusInProgress:
+ if sg.State != nil && mySlot >= 0 && mySlot < len(sg.State.Snakes) && sg.State.Snakes[mySlot] != nil && !sg.State.Snakes[mySlot].Alive {
+
You're out!
+ } else if sg.Mode == snake.ModeSinglePlayer {
+
+ { fmt.Sprintf("Score: %d", sg.Score) }
+
+ } else {
+
Go!
+ }
+ case snake.StatusFinished:
+ @finishedBanner(sg, mySlot, gameID)
+ }
+
+}
+
+templ finishedBanner(sg *snake.SnakeGame, mySlot int, gameID string) {
+ if sg.Mode == snake.ModeSinglePlayer {
+
+ { fmt.Sprintf("Game Over! Score: %d", sg.Score) }
+ @rematchOrJoin(sg, gameID)
+
+ } else if sg.Winner != nil {
+ if sg.Winner.Slot == mySlot {
+
+ You win!
+ @rematchOrJoin(sg, gameID)
+
+ } else {
+
+ { sg.Winner.Nickname + " wins!" }
+ @rematchOrJoin(sg, gameID)
+
+ }
+ } else {
+
+ It's a draw!
+ @rematchOrJoin(sg, gameID)
+
+ }
+}
+
+templ rematchOrJoin(sg *snake.SnakeGame, gameID string) {
+ if sg.RematchGameID != nil {
+
+ Join Rematch
+
+ } else {
+
+ Play again
+
+ }
+}
+
+templ PlayerList(sg *snake.SnakeGame, mySlot int) {
+
+ for i, p := range sg.Players {
+ if p != nil {
+
+
+
+ { p.Nickname }
+ if i == mySlot {
+ { " (You)" }
+ }
+
+ if sg.Status == snake.StatusInProgress || sg.Status == snake.StatusFinished {
+ if sg.State != nil && i < len(sg.State.Snakes) && sg.State.Snakes[i] != nil {
+ if sg.State.Snakes[i].Alive {
+
+ { fmt.Sprintf("(%d)", len(sg.State.Snakes[i].Body)) }
+
+ } else {
+ (dead)
+ }
+ }
+ }
+
+ }
+ }
+
+}
+
+templ InviteLink(gameID string) {
+ {{ fullURL := config.Global.AppURL + "/snake/" + gameID }}
+
+
Share this link to invite players:
+
+ { fullURL }
+
+
+ Copy Link
+
+
+}
+
+script copyToClipboard(url string) {
+ navigator.clipboard.writeText(url)
+}
diff --git a/features/snakegame/components/status_templ.go b/features/snakegame/components/status_templ.go
deleted file mode 100644
index 57416eb..0000000
--- a/features/snakegame/components/status_templ.go
+++ /dev/null
@@ -1,470 +0,0 @@
-// Code generated by templ - DO NOT EDIT.
-
-// templ: version: v0.3.1001
-package components
-
-//lint:file-ignore SA4006 This context is only used if a nested component is present.
-
-import "github.com/a-h/templ"
-import templruntime "github.com/a-h/templ/runtime"
-
-import (
- "fmt"
- "math"
- "time"
-
- "github.com/ryanhamamura/c4/config"
- "github.com/ryanhamamura/c4/snake"
- "github.com/starfederation/datastar-go/datastar"
-)
-
-func StatusBanner(sg *snake.SnakeGame, mySlot int, gameID string) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var1 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var1 == nil {
- templ_7745c5c3_Var1 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- switch sg.Status {
- case snake.StatusWaitingForPlayers:
- if sg.Mode == snake.ModeSinglePlayer {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "
Ready?
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- } else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "
Waiting for players...
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- case snake.StatusCountdown:
- remaining := time.Until(sg.CountdownEnd)
- secs := int(math.Ceil(remaining.Seconds()))
- if secs < 0 {
- secs = 0
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var2 string
- templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("Starting in %d...", secs))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/snakegame/components/status.templ`, Line: 29, Col: 45}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- case snake.StatusInProgress:
- if sg.State != nil && mySlot >= 0 && mySlot < len(sg.State.Snakes) && sg.State.Snakes[mySlot] != nil && !sg.State.Snakes[mySlot].Alive {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "
You're out!
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- } else if sg.Mode == snake.ModeSinglePlayer {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var3 string
- templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("Score: %d", sg.Score))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/snakegame/components/status.templ`, Line: 36, Col: 42}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- } else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "
Go!
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- case snake.StatusFinished:
- templ_7745c5c3_Err = finishedBanner(sg, mySlot, gameID).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func finishedBanner(sg *snake.SnakeGame, mySlot int, gameID string) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var4 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var4 == nil {
- templ_7745c5c3_Var4 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- if sg.Mode == snake.ModeSinglePlayer {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var5 string
- templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("Game Over! Score: %d", sg.Score))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/snakegame/components/status.templ`, Line: 50, Col: 50}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = rematchOrJoin(sg, gameID).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- } else if sg.Winner != nil {
- if sg.Winner.Slot == mySlot {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "You win!")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = rematchOrJoin(sg, gameID).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- } else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var6 string
- templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(sg.Winner.Nickname + " wins!")
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/snakegame/components/status.templ`, Line: 61, Col: 35}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = rematchOrJoin(sg, gameID).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- } else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "It's a draw!")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = rematchOrJoin(sg, gameID).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- return nil
- })
-}
-
-func rematchOrJoin(sg *snake.SnakeGame, gameID string) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var7 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var7 == nil {
- templ_7745c5c3_Var7 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- if sg.RematchGameID != nil {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "Join Rematch ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- } else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "Play again ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- return nil
- })
-}
-
-func PlayerList(sg *snake.SnakeGame, mySlot int) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var10 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var10 == nil {
- templ_7745c5c3_Var10 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- for i, p := range sg.Players {
- if p != nil {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var12 string
- templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(p.Nickname)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/snakegame/components/status.templ`, Line: 96, Col: 18}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- if i == mySlot {
- var templ_7745c5c3_Var13 string
- templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(" (You)")
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/snakegame/components/status.templ`, Line: 98, Col: 17}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- if sg.Status == snake.StatusInProgress || sg.Status == snake.StatusFinished {
- if sg.State != nil && i < len(sg.State.Snakes) && sg.State.Snakes[i] != nil {
- if sg.State.Snakes[i].Alive {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var14 string
- templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("(%d)", len(sg.State.Snakes[i].Body)))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/snakegame/components/status.templ`, Line: 105, Col: 60}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- } else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "(dead) ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func InviteLink(gameID string) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var15 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var15 == nil {
- templ_7745c5c3_Var15 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- fullURL := config.Global.AppURL + "/snake/" + gameID
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "Share this link to invite players:
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var16 string
- templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(fullURL)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/snakegame/components/status.templ`, Line: 123, Col: 12}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, copyToClipboard(fullURL))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "
Copy Link ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func copyToClipboard(url string) templ.ComponentScript {
- return templ.ComponentScript{
- Name: `__templ_copyToClipboard_1463`,
- Function: `function __templ_copyToClipboard_1463(url){navigator.clipboard.writeText(url)
-}`,
- Call: templ.SafeScript(`__templ_copyToClipboard_1463`, url),
- CallInline: templ.SafeScriptInline(`__templ_copyToClipboard_1463`, url),
- }
-}
-
-var _ = templruntime.GeneratedTemplate
diff --git a/features/snakegame/pages/game.templ b/features/snakegame/pages/game.templ
new file mode 100644
index 0000000..49b90de
--- /dev/null
+++ b/features/snakegame/pages/game.templ
@@ -0,0 +1,75 @@
+package pages
+
+import (
+ "fmt"
+
+ "github.com/ryanhamamura/c4/features/common/components"
+ "github.com/ryanhamamura/c4/features/common/layouts"
+ snakecomponents "github.com/ryanhamamura/c4/features/snakegame/components"
+ "github.com/ryanhamamura/c4/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 []snakecomponents.ChatMessage, gameID string) {
+ @layouts.Base("Snake") {
+
+ @components.BackToLobby()
+ ~~~~
+ @snakecomponents.PlayerList(sg, mySlot)
+ @snakecomponents.StatusBanner(sg, mySlot, gameID)
+ if sg.Status == snake.StatusInProgress || sg.Status == snake.StatusFinished {
+ if sg.Mode == snake.ModeMultiplayer {
+
+ @snakecomponents.Board(sg)
+ @snakecomponents.Chat(messages, gameID)
+
+ } else {
+ @snakecomponents.Board(sg)
+ }
+ } else if sg.Mode == snake.ModeMultiplayer {
+ @snakecomponents.Chat(messages, gameID)
+ }
+ if sg.Mode == snake.ModeMultiplayer && (sg.Status == snake.StatusWaitingForPlayers || sg.Status == snake.StatusCountdown) {
+ @snakecomponents.InviteLink(gameID)
+ }
+
+ }
+}
+
+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))
+ }
+}
diff --git a/features/snakegame/pages/game_templ.go b/features/snakegame/pages/game_templ.go
deleted file mode 100644
index 123aaab..0000000
--- a/features/snakegame/pages/game_templ.go
+++ /dev/null
@@ -1,277 +0,0 @@
-// Code generated by templ - DO NOT EDIT.
-
-// templ: version: v0.3.1001
-package pages
-
-//lint:file-ignore SA4006 This context is only used if a nested component is present.
-
-import "github.com/a-h/templ"
-import templruntime "github.com/a-h/templ/runtime"
-
-import (
- "fmt"
-
- "github.com/ryanhamamura/c4/features/common/components"
- "github.com/ryanhamamura/c4/features/common/layouts"
- snakecomponents "github.com/ryanhamamura/c4/features/snakegame/components"
- "github.com/ryanhamamura/c4/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),
- )
-}
-
-func GamePage(sg *snake.SnakeGame, mySlot int, messages []snakecomponents.ChatMessage, gameID string) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var1 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var1 == nil {
- templ_7745c5c3_Var1 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = components.BackToLobby().Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "~~~~ ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = snakecomponents.PlayerList(sg, mySlot).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = snakecomponents.StatusBanner(sg, mySlot, gameID).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- if sg.Status == snake.StatusInProgress || sg.Status == snake.StatusFinished {
- if sg.Mode == snake.ModeMultiplayer {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = snakecomponents.Board(sg).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = snakecomponents.Chat(messages, gameID).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- } else {
- templ_7745c5c3_Err = snakecomponents.Board(sg).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- } else if sg.Mode == snake.ModeMultiplayer {
- templ_7745c5c3_Err = snakecomponents.Chat(messages, gameID).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- if sg.Mode == snake.ModeMultiplayer && (sg.Status == snake.StatusWaitingForPlayers || sg.Status == snake.StatusCountdown) {
- templ_7745c5c3_Err = snakecomponents.InviteLink(gameID).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
- templ_7745c5c3_Err = layouts.Base("Snake").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func JoinPage(gameID string) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var6 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var6 == nil {
- templ_7745c5c3_Var6 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Var7 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = components.GameJoinPrompt(
- fmt.Sprintf("/login?return_url=/snake/%s", gameID),
- fmt.Sprintf("/register?return_url=/snake/%s", gameID),
- fmt.Sprintf("/snake/%s", gameID),
- ).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
- templ_7745c5c3_Err = layouts.Base("Snake - Join").Render(templ.WithChildren(ctx, templ_7745c5c3_Var7), templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func NicknamePage(gameID string) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var8 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var8 == nil {
- templ_7745c5c3_Var8 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Var9 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = components.NicknamePrompt(fmt.Sprintf("/snake/%s/join", gameID)).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
- templ_7745c5c3_Err = layouts.Base("Snake - Join").Render(templ.WithChildren(ctx, templ_7745c5c3_Var9), templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-var _ = templruntime.GeneratedTemplate