Compare commits
2 Commits
5120eef776
...
303c45cab1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
303c45cab1 | ||
|
|
587f392b8b |
@@ -1,6 +1,11 @@
|
|||||||
version: "3"
|
version: "3"
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
|
download:
|
||||||
|
desc: Download latest client-side libs
|
||||||
|
cmds:
|
||||||
|
- go run cmd/downloader/main.go
|
||||||
|
|
||||||
build:styles:
|
build:styles:
|
||||||
desc: Build TailwindCSS styles
|
desc: Build TailwindCSS styles
|
||||||
cmds:
|
cmds:
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
9
assets/js/datastar.js
Normal file
9
assets/js/datastar.js
Normal file
File diff suppressed because one or more lines are too long
7
assets/js/datastar.js.map
Normal file
7
assets/js/datastar.js.map
Normal file
File diff suppressed because one or more lines are too long
100
cmd/downloader/main.go
Normal file
100
cmd/downloader/main.go
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log/slog"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Asset directories, relative to project root.
|
||||||
|
const (
|
||||||
|
jsDir = "assets/js"
|
||||||
|
cssDir = "assets/css"
|
||||||
|
)
|
||||||
|
|
||||||
|
// files maps download URLs to local destination paths.
|
||||||
|
var files = map[string]string{
|
||||||
|
"https://raw.githubusercontent.com/starfederation/datastar/main/bundles/datastar.js": jsDir + "/datastar.js",
|
||||||
|
"https://raw.githubusercontent.com/starfederation/datastar/main/bundles/datastar.js.map": jsDir + "/datastar.js.map",
|
||||||
|
"https://github.com/saadeghi/daisyui/releases/latest/download/daisyui.mjs": cssDir + "/daisyui.mjs",
|
||||||
|
"https://github.com/saadeghi/daisyui/releases/latest/download/daisyui-theme.mjs": cssDir + "/daisyui-theme.mjs",
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if err := run(); err != nil {
|
||||||
|
slog.Error("failure", "error", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func run() error {
|
||||||
|
dirs := []string{jsDir, cssDir}
|
||||||
|
|
||||||
|
for _, dir := range dirs {
|
||||||
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||||
|
return fmt.Errorf("create directory %s: %w", dir, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return download(files)
|
||||||
|
}
|
||||||
|
|
||||||
|
func download(files map[string]string) error {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
errCh := make(chan error, len(files))
|
||||||
|
|
||||||
|
for url, dest := range files {
|
||||||
|
wg.Go(func() {
|
||||||
|
base := filepath.Base(dest)
|
||||||
|
slog.Info("downloading...", "file", base, "url", url)
|
||||||
|
if err := downloadFile(url, dest); err != nil {
|
||||||
|
errCh <- fmt.Errorf("download %s: %w", base, err)
|
||||||
|
} else {
|
||||||
|
slog.Info("finished", "file", base)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
close(errCh)
|
||||||
|
|
||||||
|
var errs []error
|
||||||
|
for err := range errCh {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.Join(errs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func downloadFile(url, dest string) error {
|
||||||
|
resp, err := http.Get(url) //nolint:gosec,noctx // static URLs, simple tool
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("GET %s: %w", url, err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return fmt.Errorf("GET %s: status %s", url, resp.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := os.Create(dest) //nolint:gosec // paths are hardcoded constants
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("create %s: %w", dest, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := io.Copy(out, resp.Body); err != nil {
|
||||||
|
out.Close() //nolint:errcheck
|
||||||
|
return fmt.Errorf("write %s: %w", dest, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := out.Close(); err != nil {
|
||||||
|
return fmt.Errorf("close %s: %w", dest, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -46,33 +46,33 @@ func LoginPage() templ.Component {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
ctx = templ.InitializeContext(ctx)
|
ctx = templ.InitializeContext(ctx)
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<main class=\"max-w-sm mx-auto mt-8 text-center\" data-signals=\"{username: '', password: '', error: ''}\"><h1 class=\"text-3xl font-bold\">Login</h1><p class=\"mb-4\">Sign in to your account</p><div data-show=\"$error != ''\" class=\"alert alert-error mb-4\" data-text=\"$error\"></div><form><fieldset class=\"fieldset\"><label class=\"label\" for=\"username\">Username</label> <input class=\"input input-bordered w-full\" id=\"username\" type=\"text\" placeholder=\"Enter your username\" data-bind=\"username\" required autofocus> <label class=\"label\" for=\"password\">Password</label> <input class=\"input input-bordered w-full\" id=\"password\" type=\"password\" placeholder=\"Enter your password\" data-bind=\"password\" required data-on:keydown.key_enter=\"")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<main class=\"max-w-sm mx-auto mt-8 text-center\" data-signals=\"{username: '', password: '', error: ''}\"><h1 class=\"text-3xl font-bold\">Login</h1><p class=\"mb-4\">Sign in to your account</p><div data-show=\"$error != ''\" class=\"alert alert-error mb-4\" data-text=\"$error\"></div><div><fieldset class=\"fieldset\"><label class=\"label\" for=\"username\">Username</label> <input class=\"input input-bordered w-full\" id=\"username\" type=\"text\" placeholder=\"Enter your username\" data-bind=\"username\" autofocus> <label class=\"label\" for=\"password\">Password</label> <input class=\"input input-bordered w-full\" id=\"password\" type=\"password\" placeholder=\"Enter your password\" data-bind=\"password\" data-on:keydown.key_enter=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var3 string
|
var templ_7745c5c3_Var3 string
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(datastar.PostSSE("/auth/login"))
|
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(datastar.PostSSE("/auth/login"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/auth/pages/login.templ`, Line: 34, Col: 65}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/auth/pages/login.templ`, Line: 32, Col: 65}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\"></fieldset><button class=\"btn btn-primary w-full\" type=\"button\" data-on:click=\"")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\"></fieldset><button class=\"btn btn-primary w-full\" data-on:click=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var4 string
|
var templ_7745c5c3_Var4 string
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(datastar.PostSSE("/auth/login"))
|
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(datastar.PostSSE("/auth/login"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/auth/pages/login.templ`, Line: 40, Col: 52}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/auth/pages/login.templ`, Line: 37, Col: 52}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\">Login</button></form><p>Don't have an account? <a class=\"link\" href=\"/register\">Register</a></p></main>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\">Login</button></div><p>Don't have an account? <a class=\"link\" href=\"/register\">Register</a></p></main>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,33 +46,33 @@ func RegisterPage() templ.Component {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
ctx = templ.InitializeContext(ctx)
|
ctx = templ.InitializeContext(ctx)
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<main class=\"max-w-sm mx-auto mt-8 text-center\" data-signals=\"{username: '', password: '', confirm: '', error: ''}\"><h1 class=\"text-3xl font-bold\">Register</h1><p class=\"mb-4\">Create a new account</p><div data-show=\"$error != ''\" class=\"alert alert-error mb-4\" data-text=\"$error\"></div><form><fieldset class=\"fieldset\"><label class=\"label\" for=\"username\">Username</label> <input class=\"input input-bordered w-full\" id=\"username\" type=\"text\" placeholder=\"Choose a username\" data-bind=\"username\" required autofocus> <label class=\"label\" for=\"password\">Password</label> <input class=\"input input-bordered w-full\" id=\"password\" type=\"password\" placeholder=\"Choose a password (min 8 chars)\" data-bind=\"password\" required> <label class=\"label\" for=\"confirm\">Confirm Password</label> <input class=\"input input-bordered w-full\" id=\"confirm\" type=\"password\" placeholder=\"Confirm your password\" data-bind=\"confirm\" required data-on:keydown.key_enter=\"")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<main class=\"max-w-sm mx-auto mt-8 text-center\" data-signals=\"{username: '', password: '', confirm: '', error: ''}\"><h1 class=\"text-3xl font-bold\">Register</h1><p class=\"mb-4\">Create a new account</p><div data-show=\"$error != ''\" class=\"alert alert-error mb-4\" data-text=\"$error\"></div><div><fieldset class=\"fieldset\"><label class=\"label\" for=\"username\">Username</label> <input class=\"input input-bordered w-full\" id=\"username\" type=\"text\" placeholder=\"Choose a username\" data-bind=\"username\" autofocus> <label class=\"label\" for=\"password\">Password</label> <input class=\"input input-bordered w-full\" id=\"password\" type=\"password\" placeholder=\"Choose a password (min 8 chars)\" data-bind=\"password\"> <label class=\"label\" for=\"confirm\">Confirm Password</label> <input class=\"input input-bordered w-full\" id=\"confirm\" type=\"password\" placeholder=\"Confirm your password\" data-bind=\"confirm\" data-on:keydown.key_enter=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var3 string
|
var templ_7745c5c3_Var3 string
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(datastar.PostSSE("/auth/register"))
|
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(datastar.PostSSE("/auth/register"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/auth/pages/register.templ`, Line: 43, Col: 68}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/auth/pages/register.templ`, Line: 40, Col: 68}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\"></fieldset><button class=\"btn btn-primary w-full\" type=\"button\" data-on:click=\"")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\"></fieldset><button class=\"btn btn-primary w-full\" data-on:click=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var4 string
|
var templ_7745c5c3_Var4 string
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(datastar.PostSSE("/auth/register"))
|
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(datastar.PostSSE("/auth/register"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/auth/pages/register.templ`, Line: 49, Col: 55}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/auth/pages/register.templ`, Line: 45, Col: 55}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\">Register</button></form><p>Already have an account? <a class=\"link\" href=\"/login\">Login</a></p></main>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\">Register</button></div><p>Already have an account? <a class=\"link\" href=\"/login\">Login</a></p></main>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,9 @@ import (
|
|||||||
"github.com/ryanhamamura/c4/db/repository"
|
"github.com/ryanhamamura/c4/db/repository"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetupRoutes(router chi.Router, queries *repository.Queries, sessions *scs.SessionManager) error {
|
func SetupRoutes(router chi.Router, queries *repository.Queries, sessions *scs.SessionManager) {
|
||||||
router.Get("/login", HandleLoginPage())
|
router.Get("/login", HandleLoginPage())
|
||||||
router.Get("/register", HandleRegisterPage())
|
router.Get("/register", HandleRegisterPage())
|
||||||
router.Post("/auth/login", HandleLogin(queries, sessions))
|
router.Post("/auth/login", HandleLogin(queries, sessions))
|
||||||
router.Post("/auth/register", HandleRegister(queries, sessions))
|
router.Post("/auth/register", HandleRegister(queries, sessions))
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ func SetupRoutes(
|
|||||||
nc *nats.Conn,
|
nc *nats.Conn,
|
||||||
sessions *scs.SessionManager,
|
sessions *scs.SessionManager,
|
||||||
queries *repository.Queries,
|
queries *repository.Queries,
|
||||||
) error {
|
) {
|
||||||
router.Route("/games/{id}", func(r chi.Router) {
|
router.Route("/games/{id}", func(r chi.Router) {
|
||||||
r.Get("/", HandleGamePage(store, sessions, queries))
|
r.Get("/", HandleGamePage(store, sessions, queries))
|
||||||
r.Get("/events", HandleGameEvents(store, nc, sessions, queries))
|
r.Get("/events", HandleGameEvents(store, nc, sessions, queries))
|
||||||
@@ -25,6 +25,4 @@ func SetupRoutes(
|
|||||||
r.Post("/join", HandleSetNickname(store, sessions))
|
r.Post("/join", HandleSetNickname(store, sessions))
|
||||||
r.Post("/rematch", HandleRematch(store, sessions))
|
r.Post("/rematch", HandleRematch(store, sessions))
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ func Base(title string) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\"><script defer type=\"module\" src=\"https://cdn.jsdelivr.net/npm/@starfederation/datastar@1.0.0-beta.11/dist/datastar.min.js\"></script><link href=\"/assets/css/output.css\" rel=\"stylesheet\" type=\"text/css\"></head><body class=\"flex flex-col h-screen\">")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\"><script defer type=\"module\" src=\"/assets/js/datastar.js\"></script><link href=\"/assets/css/output.css\" rel=\"stylesheet\" type=\"text/css\"></head><body class=\"flex flex-col h-screen\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ func LobbyPage(data LobbyData) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</h1><div class=\"tabs tabs-box mb-6 justify-center\"><button class=\"tab\" type=\"button\" data-class=\"{tab-active: $activeTab==='connect4'}\" data-on:click=\"$activeTab='connect4'\">")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</h1><div class=\"tabs tabs-box mb-6 justify-center\"><button class=\"tab\" type=\"button\" data-class=\"{'tab-active': $activeTab==='connect4'}\" data-on:click=\"$activeTab='connect4'\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@@ -108,7 +108,7 @@ func LobbyPage(data LobbyData) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</button> <button class=\"tab\" type=\"button\" data-class=\"{tab-active: $activeTab==='snake'}\" data-on:click=\"$activeTab='snake'\">~~~~</button></div><div data-show=\"$activeTab==='connect4'\"><p class=\"mb-4\">Start a new session</p><form><fieldset class=\"fieldset\"><label class=\"label\" for=\"nickname\">Your Nickname</label> <input class=\"input input-bordered w-full\" id=\"nickname\" type=\"text\" placeholder=\"Enter your nickname\" data-bind=\"nickname\" required data-on:keydown.enter=\"")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</button> <button class=\"tab\" type=\"button\" data-class=\"{'tab-active': $activeTab==='snake'}\" data-on:click=\"$activeTab='snake'\">~~~~</button></div><div data-show=\"$activeTab==='connect4'\"><p class=\"mb-4\">Start a new session</p><form><fieldset class=\"fieldset\"><label class=\"label\" for=\"nickname\">Your Nickname</label> <input class=\"input input-bordered w-full\" id=\"nickname\" type=\"text\" placeholder=\"Enter your nickname\" data-bind=\"nickname\" required data-on:keydown.enter=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@@ -152,9 +152,9 @@ func LobbyPage(data LobbyData) templ.Component {
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var7 string
|
var templ_7745c5c3_Var7 string
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("{btn-active: $selectedSpeed===%d}", i))
|
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("{'btn-active': $selectedSpeed===%d}", i))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/lobby/pages/lobby.templ`, Line: 113, Col: 72}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/lobby/pages/lobby.templ`, Line: 113, Col: 74}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
|
|||||||
@@ -16,13 +16,11 @@ func SetupRoutes(
|
|||||||
sessions *scs.SessionManager,
|
sessions *scs.SessionManager,
|
||||||
store *game.GameStore,
|
store *game.GameStore,
|
||||||
snakeStore *snake.SnakeStore,
|
snakeStore *snake.SnakeStore,
|
||||||
) error {
|
) {
|
||||||
router.Get("/", HandleLobbyPage(queries, sessions, snakeStore))
|
router.Get("/", HandleLobbyPage(queries, sessions, snakeStore))
|
||||||
|
|
||||||
router.Post("/games", HandleCreateGame(store, sessions))
|
router.Post("/games", HandleCreateGame(store, sessions))
|
||||||
router.Delete("/games/{id}", HandleDeleteGame(store, sessions))
|
router.Delete("/games/{id}", HandleDeleteGame(store, sessions))
|
||||||
router.Post("/snake", HandleCreateSnakeGame(snakeStore, sessions))
|
router.Post("/snake", HandleCreateSnakeGame(snakeStore, sessions))
|
||||||
router.Post("/logout", HandleLogout(sessions))
|
router.Post("/logout", HandleLogout(sessions))
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/ryanhamamura/c4/snake"
|
"github.com/ryanhamamura/c4/snake"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetupRoutes(router chi.Router, snakeStore *snake.SnakeStore, nc *nats.Conn, sessions *scs.SessionManager) error {
|
func SetupRoutes(router chi.Router, snakeStore *snake.SnakeStore, nc *nats.Conn, sessions *scs.SessionManager) {
|
||||||
router.Route("/snake/{id}", func(r chi.Router) {
|
router.Route("/snake/{id}", func(r chi.Router) {
|
||||||
r.Get("/", HandleSnakePage(snakeStore, sessions))
|
r.Get("/", HandleSnakePage(snakeStore, sessions))
|
||||||
r.Get("/events", HandleSnakeEvents(snakeStore, nc, sessions))
|
r.Get("/events", HandleSnakeEvents(snakeStore, nc, sessions))
|
||||||
@@ -18,6 +18,4 @@ func SetupRoutes(router chi.Router, snakeStore *snake.SnakeStore, nc *nats.Conn,
|
|||||||
r.Post("/join", HandleSetNickname(snakeStore, sessions))
|
r.Post("/join", HandleSetNickname(snakeStore, sessions))
|
||||||
r.Post("/rematch", HandleRematch(snakeStore, sessions))
|
r.Post("/rematch", HandleRematch(snakeStore, sessions))
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
4
main.go
4
main.go
@@ -90,9 +90,7 @@ func run(ctx context.Context) error {
|
|||||||
sessionManager.LoadAndSave,
|
sessionManager.LoadAndSave,
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := router.SetupRoutes(r, queries, sessionManager, nc, store, snakeStore, assets); err != nil {
|
router.SetupRoutes(r, queries, sessionManager, nc, store, snakeStore, assets)
|
||||||
return fmt.Errorf("setting up routes: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTP server
|
// HTTP server
|
||||||
srv := &http.Server{
|
srv := &http.Server{
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func SetupRoutes(
|
|||||||
store *game.GameStore,
|
store *game.GameStore,
|
||||||
snakeStore *snake.SnakeStore,
|
snakeStore *snake.SnakeStore,
|
||||||
assets embed.FS,
|
assets embed.FS,
|
||||||
) error {
|
) {
|
||||||
// Static assets
|
// Static assets
|
||||||
subFS, _ := fs.Sub(assets, "assets")
|
subFS, _ := fs.Sub(assets, "assets")
|
||||||
router.Handle("/assets/*", http.StripPrefix("/assets/", http.FileServerFS(subFS)))
|
router.Handle("/assets/*", http.StripPrefix("/assets/", http.FileServerFS(subFS)))
|
||||||
@@ -40,20 +40,10 @@ func SetupRoutes(
|
|||||||
setupReload(router)
|
setupReload(router)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := auth.SetupRoutes(router, queries, sessions); err != nil {
|
auth.SetupRoutes(router, queries, sessions)
|
||||||
return err
|
lobby.SetupRoutes(router, queries, sessions, store, snakeStore)
|
||||||
}
|
c4game.SetupRoutes(router, store, nc, sessions, queries)
|
||||||
if err := lobby.SetupRoutes(router, queries, sessions, store, snakeStore); err != nil {
|
snakegame.SetupRoutes(router, snakeStore, nc, sessions)
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := c4game.SetupRoutes(router, store, nc, sessions, queries); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := snakegame.SetupRoutes(router, snakeStore, nc, sessions); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupReload(router chi.Router) {
|
func setupReload(router chi.Router) {
|
||||||
|
|||||||
@@ -20,9 +20,10 @@ func SetupSessionManager(db *sql.DB) (*scs.SessionManager, func()) {
|
|||||||
sessionManager := scs.New()
|
sessionManager := scs.New()
|
||||||
sessionManager.Store = store
|
sessionManager.Store = store
|
||||||
sessionManager.Lifetime = 30 * 24 * time.Hour
|
sessionManager.Lifetime = 30 * 24 * time.Hour
|
||||||
|
sessionManager.Cookie.Name = "c4_session"
|
||||||
sessionManager.Cookie.Path = "/"
|
sessionManager.Cookie.Path = "/"
|
||||||
sessionManager.Cookie.HttpOnly = true
|
sessionManager.Cookie.HttpOnly = true
|
||||||
sessionManager.Cookie.Secure = false
|
sessionManager.Cookie.Secure = true
|
||||||
sessionManager.Cookie.SameSite = http.SameSiteLaxMode
|
sessionManager.Cookie.SameSite = http.SameSiteLaxMode
|
||||||
|
|
||||||
slog.Info("session manager configured")
|
slog.Info("session manager configured")
|
||||||
|
|||||||
Reference in New Issue
Block a user