- User registration/login with bcrypt password hashing - SQLite database with goose migrations and sqlc-generated queries - Games and players persisted to database, resumable after restart - Guest play still supported alongside authenticated users - Auth UI components (login/register forms, auth header, guest banner)
128 lines
2.9 KiB
Go
128 lines
2.9 KiB
Go
package ui
|
|
|
|
import (
|
|
"github.com/ryanhamamura/via/h"
|
|
)
|
|
|
|
func LoginView(usernameBind, passwordBind, loginKeyDown, loginClick h.H, errorMsg string) h.H {
|
|
var errorEl h.H
|
|
if errorMsg != "" {
|
|
errorEl = h.P(h.Class("error"), h.Text(errorMsg))
|
|
}
|
|
|
|
return h.Main(h.Class("container"),
|
|
h.Div(h.Class("lobby"),
|
|
h.H1(h.Text("Login")),
|
|
h.P(h.Text("Sign in to your account")),
|
|
errorEl,
|
|
h.Form(
|
|
h.FieldSet(
|
|
h.Label(h.Text("Username"), h.Attr("for", "username")),
|
|
h.Input(
|
|
h.ID("username"),
|
|
h.Type("text"),
|
|
h.Placeholder("Enter your username"),
|
|
usernameBind,
|
|
h.Attr("required"),
|
|
h.Attr("autofocus"),
|
|
),
|
|
h.Label(h.Text("Password"), h.Attr("for", "password")),
|
|
h.Input(
|
|
h.ID("password"),
|
|
h.Type("password"),
|
|
h.Placeholder("Enter your password"),
|
|
passwordBind,
|
|
h.Attr("required"),
|
|
loginKeyDown,
|
|
),
|
|
),
|
|
h.Button(
|
|
h.Type("button"),
|
|
h.Text("Login"),
|
|
loginClick,
|
|
),
|
|
),
|
|
h.P(
|
|
h.Text("Don't have an account? "),
|
|
h.A(h.Href("/register"), h.Text("Register")),
|
|
),
|
|
),
|
|
)
|
|
}
|
|
|
|
func RegisterView(usernameBind, passwordBind, confirmBind, registerKeyDown, registerClick h.H, errorMsg string) h.H {
|
|
var errorEl h.H
|
|
if errorMsg != "" {
|
|
errorEl = h.P(h.Class("error"), h.Text(errorMsg))
|
|
}
|
|
|
|
return h.Main(h.Class("container"),
|
|
h.Div(h.Class("lobby"),
|
|
h.H1(h.Text("Register")),
|
|
h.P(h.Text("Create a new account")),
|
|
errorEl,
|
|
h.Form(
|
|
h.FieldSet(
|
|
h.Label(h.Text("Username"), h.Attr("for", "username")),
|
|
h.Input(
|
|
h.ID("username"),
|
|
h.Type("text"),
|
|
h.Placeholder("Choose a username"),
|
|
usernameBind,
|
|
h.Attr("required"),
|
|
h.Attr("autofocus"),
|
|
),
|
|
h.Label(h.Text("Password"), h.Attr("for", "password")),
|
|
h.Input(
|
|
h.ID("password"),
|
|
h.Type("password"),
|
|
h.Placeholder("Choose a password (min 8 chars)"),
|
|
passwordBind,
|
|
h.Attr("required"),
|
|
),
|
|
h.Label(h.Text("Confirm Password"), h.Attr("for", "confirm")),
|
|
h.Input(
|
|
h.ID("confirm"),
|
|
h.Type("password"),
|
|
h.Placeholder("Confirm your password"),
|
|
confirmBind,
|
|
h.Attr("required"),
|
|
registerKeyDown,
|
|
),
|
|
),
|
|
h.Button(
|
|
h.Type("button"),
|
|
h.Text("Register"),
|
|
registerClick,
|
|
),
|
|
),
|
|
h.P(
|
|
h.Text("Already have an account? "),
|
|
h.A(h.Href("/login"), h.Text("Login")),
|
|
),
|
|
),
|
|
)
|
|
}
|
|
|
|
func AuthHeader(username string, logoutClick h.H) h.H {
|
|
return h.Div(h.Class("auth-header"),
|
|
h.Span(h.Text("Logged in as "), h.Strong(h.Text(username))),
|
|
h.Button(
|
|
h.Type("button"),
|
|
h.Class("secondary outline small"),
|
|
h.Text("Logout"),
|
|
logoutClick,
|
|
),
|
|
)
|
|
}
|
|
|
|
func GuestBanner() h.H {
|
|
return h.Div(h.Class("guest-banner"),
|
|
h.Text("Playing as guest. "),
|
|
h.A(h.Href("/login"), h.Text("Login")),
|
|
h.Text(" or "),
|
|
h.A(h.Href("/register"), h.Text("Register")),
|
|
h.Text(" to save your games."),
|
|
)
|
|
}
|