Fix build errors and upgrade templ to v0.3.1020

- Add missing bcc argument to NewEmail call in pkg/email/fetch.go
- Upgrade github.com/a-h/templ from v0.3.833 to v0.3.1020 to match generator
- Add player management routes (add/delete/edit) and playershandler
- Update templates and loaddata with pending changes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Harry Culpan 2026-06-29 20:05:53 -04:00
parent 4a778b1dc0
commit 04f687a278
15 changed files with 441 additions and 87 deletions

86
cmd/web/playershandler.go Normal file
View file

@ -0,0 +1,86 @@
package main
import (
"net/http"
"github.com/hculpan/areweplaying/pkg/data"
)
func addPlayerHandler(w http.ResponseWriter, r *http.Request) {
if !ValidateJWTFromCookie(r, appKey) {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
r.ParseForm()
session, err := data.ReadSessionData()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
p := data.Player{
Name: r.FormValue("name"),
Email: r.FormValue("email"),
Gm: r.FormValue("gm") == "on",
Attending: "unknown",
}
if err := data.AddPlayer(session, p); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
http.Redirect(w, r, "/setup", http.StatusSeeOther)
}
func deletePlayerHandler(w http.ResponseWriter, r *http.Request) {
if !ValidateJWTFromCookie(r, appKey) {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
r.ParseForm()
session, err := data.ReadSessionData()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
name := r.FormValue("name")
if err := data.DeletePlayer(session, name); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
http.Redirect(w, r, "/setup", http.StatusSeeOther)
}
func editPlayerHandler(w http.ResponseWriter, r *http.Request) {
if !ValidateJWTFromCookie(r, appKey) {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
r.ParseForm()
session, err := data.ReadSessionData()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
originalName := r.FormValue("originalName")
updated := data.Player{
Name: r.FormValue("name"),
Email: r.FormValue("email"),
Gm: r.FormValue("gm") == "on",
Attending: r.FormValue("attending"),
}
if err := data.UpdatePlayer(session, originalName, updated); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
http.Redirect(w, r, "/setup", http.StatusSeeOther)
}

View file

@ -48,6 +48,18 @@ func routes(r *chi.Mux) {
sendReminderHandler(w, r)
})
r.Post("/admin/players/add", func(w http.ResponseWriter, r *http.Request) {
addPlayerHandler(w, r)
})
r.Post("/admin/players/delete", func(w http.ResponseWriter, r *http.Request) {
deletePlayerHandler(w, r)
})
r.Post("/admin/players/edit", func(w http.ResponseWriter, r *http.Request) {
editPlayerHandler(w, r)
})
r.Get("/sessioninfo", func(w http.ResponseWriter, r *http.Request) {
session, dataErr := data.ReadSessionData()
if dataErr != nil {

View file

@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.778
// templ: version: v0.3.1020
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
@ -29,11 +29,11 @@ func Header() templ.Component {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<head><title>Are We Playing?</title><link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC\" crossorigin=\"anonymous\"><script src=\"https://unpkg.com/htmx.org@1.9.10\" integrity=\"sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC\" crossorigin=\"anonymous\"></script><link rel=\"icon\" type=\"image/x-icon\" href=\"/static/awp-logo.ico\"></head>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<head><title>Are We Playing?</title><link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC\" crossorigin=\"anonymous\"><script src=\"https://unpkg.com/htmx.org@1.9.10\" integrity=\"sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC\" crossorigin=\"anonymous\"></script><link rel=\"icon\" type=\"image/x-icon\" href=\"/static/awp-logo.ico\"></head>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
return nil
})
}

View file

@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.778
// templ: version: v0.3.1020
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
@ -29,7 +29,7 @@ func MainPage() templ.Component {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<html>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<html>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -37,11 +37,11 @@ func MainPage() templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<body class=\"bg-dark text-light\"><div class=\"container mt-4\" id=\"session-info\" hx-get=\"/sessioninfo\" hx-swap=\"innerHTML\" hx-trigger=\"load\" hx-target=\"#session-info\"></div><div class=\"container\"><div class=\"d-flex justify-content-end\"><a href=\"/login\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"currentColor\" class=\"bi bi-gear text-secondary\" viewBox=\"0 0 16 16\"><path d=\"M8 4.754a3.246 3.246 0 1 0 0 6.492 3.246 3.246 0 0 0 0-6.492M5.754 8a2.246 2.246 0 1 1 4.492 0 2.246 2.246 0 0 1-4.492 0\"></path> <path d=\"M9.796 1.343c-.527-1.79-3.065-1.79-3.592 0l-.094.319a.873.873 0 0 1-1.255.52l-.292-.16c-1.64-.892-3.433.902-2.54 2.541l.159.292a.873.873 0 0 1-.52 1.255l-.319.094c-1.79.527-1.79 3.065 0 3.592l.319.094a.873.873 0 0 1 .52 1.255l-.16.292c-.892 1.64.901 3.434 2.541 2.54l.292-.159a.873.873 0 0 1 1.255.52l.094.319c.527 1.79 3.065 1.79 3.592 0l.094-.319a.873.873 0 0 1 1.255-.52l.292.16c1.64.893 3.434-.902 2.54-2.541l-.159-.292a.873.873 0 0 1 .52-1.255l.319-.094c1.79-.527 1.79-3.065 0-3.592l-.319-.094a.873.873 0 0 1-.52-1.255l.16-.292c.893-1.64-.902-3.433-2.541-2.54l-.292.159a.873.873 0 0 1-1.255-.52zm-2.633.283c.246-.835 1.428-.835 1.674 0l.094.319a1.873 1.873 0 0 0 2.693 1.115l.291-.16c.764-.415 1.6.42 1.184 1.185l-.159.292a1.873 1.873 0 0 0 1.116 2.692l.318.094c.835.246.835 1.428 0 1.674l-.319.094a1.873 1.873 0 0 0-1.115 2.693l.16.291c.415.764-.42 1.6-1.185 1.184l-.291-.159a1.873 1.873 0 0 0-2.693 1.116l-.094.318c-.246.835-1.428.835-1.674 0l-.094-.319a1.873 1.873 0 0 0-2.692-1.115l-.292.16c-.764.415-1.6-.42-1.184-1.185l.159-.291A1.873 1.873 0 0 0 1.945 8.93l-.319-.094c-.835-.246-.835-1.428 0-1.674l.319-.094A1.873 1.873 0 0 0 3.06 4.377l-.16-.292c-.415-.764.42-1.6 1.185-1.184l.292.159a1.873 1.873 0 0 0 2.692-1.115z\"></path></svg></a></div></div><script src=\" https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js\" integrity=\"sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM\" crossorigin=\"anonymous\">\n </script></body></html>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<body class=\"bg-dark text-light\"><div class=\"container mt-4\" id=\"session-info\" hx-get=\"/sessioninfo\" hx-swap=\"innerHTML\" hx-trigger=\"load\" hx-target=\"#session-info\"></div><div class=\"container\"><div class=\"d-flex justify-content-end\"><a href=\"/login\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"currentColor\" class=\"bi bi-gear text-secondary\" viewBox=\"0 0 16 16\"><path d=\"M8 4.754a3.246 3.246 0 1 0 0 6.492 3.246 3.246 0 0 0 0-6.492M5.754 8a2.246 2.246 0 1 1 4.492 0 2.246 2.246 0 0 1-4.492 0\"></path> <path d=\"M9.796 1.343c-.527-1.79-3.065-1.79-3.592 0l-.094.319a.873.873 0 0 1-1.255.52l-.292-.16c-1.64-.892-3.433.902-2.54 2.541l.159.292a.873.873 0 0 1-.52 1.255l-.319.094c-1.79.527-1.79 3.065 0 3.592l.319.094a.873.873 0 0 1 .52 1.255l-.16.292c-.892 1.64.901 3.434 2.541 2.54l.292-.159a.873.873 0 0 1 1.255.52l.094.319c.527 1.79 3.065 1.79 3.592 0l.094-.319a.873.873 0 0 1 1.255-.52l.292.16c1.64.893 3.434-.902 2.54-2.541l-.159-.292a.873.873 0 0 1 .52-1.255l.319-.094c1.79-.527 1.79-3.065 0-3.592l-.319-.094a.873.873 0 0 1-.52-1.255l.16-.292c.893-1.64-.902-3.433-2.541-2.54l-.292.159a.873.873 0 0 1-1.255-.52zm-2.633.283c.246-.835 1.428-.835 1.674 0l.094.319a1.873 1.873 0 0 0 2.693 1.115l.291-.16c.764-.415 1.6.42 1.184 1.185l-.159.292a1.873 1.873 0 0 0 1.116 2.692l.318.094c.835.246.835 1.428 0 1.674l-.319.094a1.873 1.873 0 0 0-1.115 2.693l.16.291c.415.764-.42 1.6-1.185 1.184l-.291-.159a1.873 1.873 0 0 0-2.693 1.116l-.094.318c-.246.835-1.428.835-1.674 0l-.094-.319a1.873 1.873 0 0 0-2.692-1.115l-.292.16c-.764.415-1.6-.42-1.184-1.185l.159-.291A1.873 1.873 0 0 0 1.945 8.93l-.319-.094c-.835-.246-.835-1.428 0-1.674l.319-.094A1.873 1.873 0 0 0 3.06 4.377l-.16-.292c-.415-.764.42-1.6 1.185-1.184l.292.159a1.873 1.873 0 0 0 2.692-1.115z\"></path></svg></a></div></div><script src=\" https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js\" integrity=\"sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM\" crossorigin=\"anonymous\">\n </script></body></html>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
return nil
})
}

View file

@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.778
// templ: version: v0.3.1020
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
@ -29,7 +29,7 @@ func Login() templ.Component {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<html>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<html>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -37,11 +37,11 @@ func Login() templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<body class=\"bg-dark text-light\"><div class=\"container\"><div class=\"row d-flex justify-content-center\"><div class=\"col-4\"><form action=\"/setup\" method=\"POST\"><h1 class=\"h3 mb-3 mt-4 fw-normal\">Please sign in</h1><div class=\"form-floating\"><input type=\"password\" class=\"form-control mb-2\" id=\"password\" name=\"password\" placeholder=\"Password\"> <label for=\"floatingPassword\">Password</label></div><button class=\"w-100 btn btn-lg btn-primary\" type=\"submit\">Sign in</button></form></div></div></div></body></html>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<body class=\"bg-dark text-light\"><div class=\"container\"><div class=\"row d-flex justify-content-center\"><div class=\"col-4\"><form action=\"/setup\" method=\"POST\"><h1 class=\"h3 mb-3 mt-4 fw-normal\">Please sign in</h1><div class=\"form-floating\"><input type=\"password\" class=\"form-control mb-2\" id=\"password\" name=\"password\" placeholder=\"Password\"> <label for=\"floatingPassword\">Password</label></div><button class=\"w-100 btn btn-lg btn-primary\" type=\"submit\">Sign in</button></form></div></div></div></body></html>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
return nil
})
}

View file

@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.778
// templ: version: v0.3.1020
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
@ -33,7 +33,7 @@ func PageBody(session data.Session) templ.Component {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"row\"><div class=\"col h1 text-center\">Next Session: ")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"row\"><div class=\"col h1 text-center\">Next Session: ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -46,45 +46,45 @@ func PageBody(session data.Session) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div><div class=\"row justify-content-center mt-4\"><div class=\"col col-lg-3\"><table class=\"table table-dark table-striped border border-secondary\"><thead><tr><th scope=\"col\" class=\"col-1 text-center\">Attending</th><th scope=\"col\" class=\"col-2 text-center\">Player</th></tr></thead> <tbody>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</div></div><div class=\"row justify-content-center mt-4\"><div class=\"col col-lg-3\"><table class=\"table table-dark table-striped border border-secondary\"><thead><tr><th scope=\"col\" class=\"col-1 text-center\">Attending</th><th scope=\"col\" class=\"col-2 text-center\">Player</th></tr></thead> <tbody>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, player := range session.Players {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<tr><td class=\"col col-lg-1 align-middle text-center\" hx-get=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<tr><td class=\"col col-lg-1 align-middle text-center\" hx-get=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(player.ToggleUrl)
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.ResolveAttributeValue(player.ToggleUrl)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `cmd/web/templates/pagebody.templ`, Line: 23, Col: 95}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" hx-swap=\"innerHTML\" hx-target=\"#session-info\" hx-trigger=\"click\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" hx-swap=\"innerHTML\" hx-target=\"#session-info\" hx-trigger=\"click\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if player.Attending == "yes" {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<img src=\"/static/check_green.png\" width=\"30\" height=\"30\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<img src=\"/static/check_green.png\" width=\"30\" height=\"30\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else if player.Attending == "no" {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<img src=\"/static/check_red.png\" width=\"30\" height=\"30\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<img src=\"/static/check_red.png\" width=\"30\" height=\"30\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<img src=\"/static/check_grey.png\" width=\"30\" height=\"30\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<img src=\"/static/check_grey.png\" width=\"30\" height=\"30\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td class=\"col col-lg-2 align-middle text-center\" style=\"height: 50px;\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</td><td class=\"col col-lg-2 align-middle text-center\" style=\"height: 50px;\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -97,17 +97,17 @@ func PageBody(session data.Session) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td></tr>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</td></tr>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</tbody></table></div></div><div class=\"row\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</tbody></table></div></div><div class=\"row\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if session.Status == "planned" {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"col h1 text-center text-success\">Status: ")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"col h1 text-center text-success\">Status: ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -120,12 +120,12 @@ func PageBody(session data.Session) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else if session.Status == "canceled" {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"col h1 text-center text-danger\">Status: ")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<div class=\"col h1 text-center text-danger\">Status: ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -138,12 +138,12 @@ func PageBody(session data.Session) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"col h1 text-center\">Status: ")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<div class=\"col h1 text-center\">Status: ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -156,16 +156,16 @@ func PageBody(session data.Session) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
return nil
})
}

View file

@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.778
// templ: version: v0.3.1020
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
@ -29,7 +29,7 @@ func SaveSetup(status string) templ.Component {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<html>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<html>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -37,7 +37,7 @@ func SaveSetup(status string) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<body class=\"bg-dark text-light\"><div class=\"container\"><div class=\"row\"><div class=\"col-3\"><a href=\"/\" class=\"btn btn-secondary\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"currentColor\" class=\"bi bi-arrow-left\" viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8\"></path></svg>Back to Main Page</a></div></div><div class=\"row mt-4\"><h1>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<body class=\"bg-dark text-light\"><div class=\"container\"><div class=\"row\"><div class=\"col-3\"><a href=\"/\" class=\"btn btn-secondary\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"currentColor\" class=\"bi bi-arrow-left\" viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8\"></path></svg>Back to Main Page</a></div></div><div class=\"row mt-4\"><h1>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -50,11 +50,11 @@ func SaveSetup(status string) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h1></div></div><footer class=\" container\"></footer></body></html>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</h1></div></div><footer class=\"container\"></footer></body></html>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
return nil
})
}

View file

@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.778
// templ: version: v0.3.1020
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
@ -29,7 +29,7 @@ func SendEmail(status string, msg string) templ.Component {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<html>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<html>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -37,7 +37,7 @@ func SendEmail(status string, msg string) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<body class=\"bg-dark text-light\"><div class=\"container\"><div class=\"row\"><div class=\"col-3\"><a href=\"/\" class=\"btn btn-secondary\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"currentColor\" class=\"bi bi-arrow-left\" viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8\"></path></svg>Back to Main Page</a></div></div><div class=\"row mt-4\"><h1>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<body class=\"bg-dark text-light\"><div class=\"container\"><div class=\"row\"><div class=\"col-3\"><a href=\"/\" class=\"btn btn-secondary\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"currentColor\" class=\"bi bi-arrow-left\" viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8\"></path></svg>Back to Main Page</a></div></div><div class=\"row mt-4\"><h1>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -50,7 +50,7 @@ func SendEmail(status string, msg string) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h1></div><div class=\"row\"><p>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</h1></div><div class=\"row\"><p>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -63,11 +63,11 @@ func SendEmail(status string, msg string) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p></div></div><footer class=\" container\"></footer></body></html>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</p></div></div><footer class=\"container\"></footer></body></html>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
return nil
})
}

View file

@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.778
// templ: version: v0.3.1020
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
@ -29,7 +29,7 @@ func SendReminder(to string, subject string, text, msg string) templ.Component {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<html>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<html>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -37,33 +37,33 @@ func SendReminder(to string, subject string, text, msg string) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<body class=\"bg-dark text-light\"><div class=\"container\"><div class=\"row\"><div class=\"col-3\"><a href=\"/\" class=\"btn btn-secondary\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"currentColor\" class=\"bi bi-arrow-left\" viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8\"></path></svg>Back to Main Page</a></div></div><div class=\"row mt-4\"><h1>Send Reminder</h1></div><div class=\"row\"><form action=\"/send-email\" method=\"post\"><div class=\"mb-3\"><label for=\"toControl\" class=\"form-label\">To</label> <input type=\"text\" id=\"toControl\" name=\"to\" value=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<body class=\"bg-dark text-light\"><div class=\"container\"><div class=\"row\"><div class=\"col-3\"><a href=\"/\" class=\"btn btn-secondary\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"currentColor\" class=\"bi bi-arrow-left\" viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8\"></path></svg>Back to Main Page</a></div></div><div class=\"row mt-4\"><h1>Send Reminder</h1></div><div class=\"row\"><form action=\"/send-email\" method=\"post\"><div class=\"mb-3\"><label for=\"toControl\" class=\"form-label\">To</label> <input type=\"text\" id=\"toControl\" name=\"to\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(to)
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.ResolveAttributeValue(to)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `cmd/web/templates/sendreminder.templ`, Line: 26, Col: 73}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var2)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"></div><div class=\"mb-3\"><label for=\"subjectControl\" class=\"form-label\">Subject</label> <input type=\"text\" class=\"form-control\" id=\"subjectControl\" name=\"subject\" value=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\"></div><div class=\"mb-3\"><label for=\"subjectControl\" class=\"form-label\">Subject</label> <input type=\"text\" class=\"form-control\" id=\"subjectControl\" name=\"subject\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(subject)
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.ResolveAttributeValue(subject)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `cmd/web/templates/sendreminder.templ`, Line: 30, Col: 110}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"></div><div class=\"mb-3\"><label for=\"textControl\" class=\"form-label\">Text to send</label> <textarea class=\"form-control\" id=\"subjectControl\" name=\"text\" rows=\"5\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\"></div><div class=\"mb-3\"><label for=\"textControl\" class=\"form-label\">Text to send</label> <textarea class=\"form-control\" id=\"subjectControl\" name=\"text\" rows=\"5\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -76,27 +76,27 @@ func SendReminder(to string, subject string, text, msg string) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</textarea></div>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</textarea></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if msg == "" {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<button type=\"submit\" class=\"btn btn-primary\">Send Reminder</button>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<button type=\"submit\" class=\"btn btn-primary\">Send Reminder</button>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<button type=\"submit\" class=\"btn btn-primary\" disabled>Send Reminder</button>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<button type=\"submit\" class=\"btn btn-primary\" disabled>Send Reminder</button>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</form>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</form>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if msg != "" {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"alert alert-danger\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<div class=\"alert alert-danger\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -109,16 +109,16 @@ func SendReminder(to string, subject string, text, msg string) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div><footer class=\" container\"></footer></body></html>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</div></div><footer class=\"container\"></footer></body></html>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
return nil
})
}

View file

@ -63,7 +63,139 @@ templ Setup(session data.Session) {
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
<div class="row mt-5">
<div class="col d-flex align-items-center gap-3">
<h2 class="mb-0">Players</h2>
<button type="button" class="btn btn-success btn-sm" data-bs-toggle="modal" data-bs-target="#addPlayerModal">
+ Add Player
</button>
</div>
</div>
<div class="row mt-2">
<div class="col">
<table class="table table-dark table-striped table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>GM</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
for _, p := range session.Players {
<tr>
<td>{ p.Name }</td>
<td>{ p.Email }</td>
<td>
if p.Gm {
<span class="badge bg-warning text-dark">GM</span>
}
</td>
<td>
<button type="button" class="btn btn-secondary btn-sm me-1"
data-bs-toggle="modal"
data-bs-target="#editPlayerModal"
data-name={ p.Name }
data-email={ p.Email }
data-gm={ strconv.FormatBool(p.Gm) }
data-attending={ p.Attending }
onclick="populateEditModal(this)">
Edit
</button>
<form action="/admin/players/delete" method="post" class="d-inline">
<input type="hidden" name="name" value={ p.Name } />
<button type="submit" class="btn btn-danger btn-sm"
onclick="return confirm('Delete ' + this.form.querySelector('[name=name]').value + '?')">Delete</button>
</form>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
<!-- Add Player Modal -->
<div class="modal fade" id="addPlayerModal" tabindex="-1" aria-labelledby="addPlayerModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content bg-dark text-light">
<div class="modal-header">
<h5 class="modal-title" id="addPlayerModalLabel">Add Player</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form action="/admin/players/add" method="post">
<div class="modal-body">
<div class="mb-3">
<label for="addName" class="form-label">Name</label>
<input type="text" class="form-control" id="addName" name="name" required />
</div>
<div class="mb-3">
<label for="addEmail" class="form-label">Email</label>
<input type="email" class="form-control" id="addEmail" name="email" required />
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="addGm" name="gm" />
<label class="form-check-label" for="addGm">Game Master</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary">Add Player</button>
</div>
</form>
</div>
</div>
</div>
<!-- Edit Player Modal -->
<div class="modal fade" id="editPlayerModal" tabindex="-1" aria-labelledby="editPlayerModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content bg-dark text-light">
<div class="modal-header">
<h5 class="modal-title" id="editPlayerModalLabel">Edit Player</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form action="/admin/players/edit" method="post">
<input type="hidden" id="editOriginalName" name="originalName" />
<input type="hidden" id="editAttending" name="attending" />
<div class="modal-body">
<div class="mb-3">
<label for="editName" class="form-label">Name</label>
<input type="text" class="form-control" id="editName" name="name" required />
</div>
<div class="mb-3">
<label for="editEmail" class="form-label">Email</label>
<input type="email" class="form-control" id="editEmail" name="email" required />
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="editGm" name="gm" />
<label class="form-check-label" for="editGm">Game Master</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary">Save Changes</button>
</div>
</form>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
<script>
function populateEditModal(btn) {
document.getElementById('editOriginalName').value = btn.dataset.name;
document.getElementById('editName').value = btn.dataset.name;
document.getElementById('editEmail').value = btn.dataset.email;
document.getElementById('editGm').checked = btn.dataset.gm === 'true';
document.getElementById('editAttending').value = btn.dataset.attending;
}
</script>
<footer class=" container">
</footer>

View file

@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.778
// templ: version: v0.3.1020
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
@ -34,7 +34,7 @@ func Setup(session data.Session) templ.Component {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<html>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<html>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -42,24 +42,135 @@ func Setup(session data.Session) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<body class=\"bg-dark text-light\"><div class=\"container\"><div class=\"row\"><div class=\"col-3\"><a href=\"/\" class=\"btn btn-secondary\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"currentColor\" class=\"bi bi-arrow-left\" viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8\"></path></svg>Back to Main Page</a></div><div class=\"col-3\"><a href=\"/send-reminder\" class=\"btn btn-secondary\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"currentColor\" class=\"bi bi-envelope-plus\" viewBox=\"0 0 16 16\"><path d=\"M2 2a2 2 0 0 0-2 2v8.01A2 2 0 0 0 2 14h5.5a.5.5 0 0 0 0-1H2a1 1 0 0 1-.966-.741l5.64-3.471L8 9.583l7-4.2V8.5a.5.5 0 0 0 1 0V4a2 2 0 0 0-2-2zm3.708 6.208L1 11.105V5.383zM1 4.217V4a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v.217l-7 4.2z\"></path> <path d=\"M16 12.5a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0m-3.5-2a.5.5 0 0 0-.5.5v1h-1a.5.5 0 0 0 0 1h1v1a.5.5 0 0 0 1 0v-1h1a.5.5 0 0 0 0-1h-1v-1a.5.5 0 0 0-.5-.5\"></path></svg> Send Reminder</a></div></div><div class=\"row mt-4\"><h1>Setup</h1></div><div class=\"row\"><form action=\"/save-setup\" method=\"post\"><div class=\"form-check mb-3\"><input class=\"form-check-input\" type=\"checkbox\" value=\"nextSession\" id=\"nextSession\" name=\"nextSession\"> <label class=\"form-check-label\" for=\"nextSession\">Change to next session</label></div><div class=\"mb-3\"><label for=\"incrementDaysInput\" class=\"form-label\">Days to Increment</label> <input type=\"number\" class=\"form-control\" id=\"incrementDaysInput\" name=\"incDays\" min=\"1\" style=\"max-width: 150px;\" max=\"999\" value=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<body class=\"bg-dark text-light\"><div class=\"container\"><div class=\"row\"><div class=\"col-3\"><a href=\"/\" class=\"btn btn-secondary\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"currentColor\" class=\"bi bi-arrow-left\" viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8\"></path></svg>Back to Main Page</a></div><div class=\"col-3\"><a href=\"/send-reminder\" class=\"btn btn-secondary\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"currentColor\" class=\"bi bi-envelope-plus\" viewBox=\"0 0 16 16\"><path d=\"M2 2a2 2 0 0 0-2 2v8.01A2 2 0 0 0 2 14h5.5a.5.5 0 0 0 0-1H2a1 1 0 0 1-.966-.741l5.64-3.471L8 9.583l7-4.2V8.5a.5.5 0 0 0 1 0V4a2 2 0 0 0-2-2zm3.708 6.208L1 11.105V5.383zM1 4.217V4a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v.217l-7 4.2z\"></path> <path d=\"M16 12.5a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0m-3.5-2a.5.5 0 0 0-.5.5v1h-1a.5.5 0 0 0 0 1h1v1a.5.5 0 0 0 1 0v-1h1a.5.5 0 0 0 0-1h-1v-1a.5.5 0 0 0-.5-.5\"></path></svg> Send Reminder</a></div></div><div class=\"row mt-4\"><h1>Setup</h1></div><div class=\"row\"><form action=\"/save-setup\" method=\"post\"><div class=\"form-check mb-3\"><input class=\"form-check-input\" type=\"checkbox\" value=\"nextSession\" id=\"nextSession\" name=\"nextSession\"> <label class=\"form-check-label\" for=\"nextSession\">Change to next session</label></div><div class=\"mb-3\"><label for=\"incrementDaysInput\" class=\"form-label\">Days to Increment</label> <input type=\"number\" class=\"form-control\" id=\"incrementDaysInput\" name=\"incDays\" min=\"1\" style=\"max-width: 150px;\" max=\"999\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(session.IncrementDays))
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.ResolveAttributeValue(strconv.Itoa(session.IncrementDays))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `cmd/web/templates/setup.templ`, Line: 48, Col: 103}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var2)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"></div><div class=\"mb-3\"><label for=\"sessionStatus\" class=\"form-label\">Session Status</label> <select class=\"form-select\" aria-label=\"Default select example\" name=\"sessionStatus\" style=\"max-width: 150px;\"><option selected></option> <option value=\"planned\">Planned</option> <option value=\"canceled\">Canceled</option></select></div><div class=\"form-check mb-3\"><input class=\"form-check-input\" type=\"checkbox\" value=\"sendEmail\" id=\"sendEmail\" name=\"sendEmail\"> <label class=\"form-check-label\" for=\"sendEmail\">Send Email</label></div><button type=\"submit\" class=\"btn btn-primary\">Save</button></form></div></div><footer class=\" container\"></footer></body></html>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\"></div><div class=\"mb-3\"><label for=\"sessionStatus\" class=\"form-label\">Session Status</label> <select class=\"form-select\" aria-label=\"Default select example\" name=\"sessionStatus\" style=\"max-width: 150px;\"><option selected></option> <option value=\"planned\">Planned</option> <option value=\"canceled\">Canceled</option></select></div><div class=\"form-check mb-3\"><input class=\"form-check-input\" type=\"checkbox\" value=\"sendEmail\" id=\"sendEmail\" name=\"sendEmail\"> <label class=\"form-check-label\" for=\"sendEmail\">Send Email</label></div><button type=\"submit\" class=\"btn btn-primary\">Save</button></form></div><div class=\"row mt-5\"><div class=\"col d-flex align-items-center gap-3\"><h2 class=\"mb-0\">Players</h2><button type=\"button\" class=\"btn btn-success btn-sm\" data-bs-toggle=\"modal\" data-bs-target=\"#addPlayerModal\">+ Add Player</button></div></div><div class=\"row mt-2\"><div class=\"col\"><table class=\"table table-dark table-striped table-bordered\"><thead><tr><th>Name</th><th>Email</th><th>GM</th><th>Actions</th></tr></thead> <tbody>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, p := range session.Players {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<tr><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(p.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `cmd/web/templates/setup.templ`, Line: 89, Col: 44}
}
_, 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, 5, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(p.Email)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `cmd/web/templates/setup.templ`, Line: 90, Col: 45}
}
_, 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, 6, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if p.Gm {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<span class=\"badge bg-warning text-dark\">GM</span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</td><td><button type=\"button\" class=\"btn btn-secondary btn-sm me-1\" data-bs-toggle=\"modal\" data-bs-target=\"#editPlayerModal\" data-name=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `cmd/web/templates/setup.templ`, Line: 100, Col: 58}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var5)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\" data-email=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.Email)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `cmd/web/templates/setup.templ`, Line: 101, Col: 60}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var6)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\" data-gm=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.ResolveAttributeValue(strconv.FormatBool(p.Gm))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `cmd/web/templates/setup.templ`, Line: 102, Col: 74}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var7)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\" data-attending=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.Attending)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `cmd/web/templates/setup.templ`, Line: 103, Col: 68}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var8)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\" onclick=\"populateEditModal(this)\">Edit</button><form action=\"/admin/players/delete\" method=\"post\" class=\"d-inline\"><input type=\"hidden\" name=\"name\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `cmd/web/templates/setup.templ`, Line: 108, Col: 87}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var9)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "\"> <button type=\"submit\" class=\"btn btn-danger btn-sm\" onclick=\"return confirm('Delete ' + this.form.querySelector('[name=name]').value + '?')\">Delete</button></form></td></tr>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</tbody></table></div></div></div><!-- Add Player Modal --><div class=\"modal fade\" id=\"addPlayerModal\" tabindex=\"-1\" aria-labelledby=\"addPlayerModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog\"><div class=\"modal-content bg-dark text-light\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"addPlayerModalLabel\">Add Player</h5><button type=\"button\" class=\"btn-close btn-close-white\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button></div><form action=\"/admin/players/add\" method=\"post\"><div class=\"modal-body\"><div class=\"mb-3\"><label for=\"addName\" class=\"form-label\">Name</label> <input type=\"text\" class=\"form-control\" id=\"addName\" name=\"name\" required></div><div class=\"mb-3\"><label for=\"addEmail\" class=\"form-label\">Email</label> <input type=\"email\" class=\"form-control\" id=\"addEmail\" name=\"email\" required></div><div class=\"form-check\"><input class=\"form-check-input\" type=\"checkbox\" id=\"addGm\" name=\"gm\"> <label class=\"form-check-label\" for=\"addGm\">Game Master</label></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"submit\" class=\"btn btn-primary\">Add Player</button></div></form></div></div></div><!-- Edit Player Modal --><div class=\"modal fade\" id=\"editPlayerModal\" tabindex=\"-1\" aria-labelledby=\"editPlayerModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog\"><div class=\"modal-content bg-dark text-light\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"editPlayerModalLabel\">Edit Player</h5><button type=\"button\" class=\"btn-close btn-close-white\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button></div><form action=\"/admin/players/edit\" method=\"post\"><input type=\"hidden\" id=\"editOriginalName\" name=\"originalName\"> <input type=\"hidden\" id=\"editAttending\" name=\"attending\"><div class=\"modal-body\"><div class=\"mb-3\"><label for=\"editName\" class=\"form-label\">Name</label> <input type=\"text\" class=\"form-control\" id=\"editName\" name=\"name\" required></div><div class=\"mb-3\"><label for=\"editEmail\" class=\"form-label\">Email</label> <input type=\"email\" class=\"form-control\" id=\"editEmail\" name=\"email\" required></div><div class=\"form-check\"><input class=\"form-check-input\" type=\"checkbox\" id=\"editGm\" name=\"gm\"> <label class=\"form-check-label\" for=\"editGm\">Game Master</label></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"submit\" class=\"btn btn-primary\">Save Changes</button></div></form></div></div></div><script src=\"https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js\" integrity=\"sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM\" crossorigin=\"anonymous\"></script><script>\n function populateEditModal(btn) {\n document.getElementById('editOriginalName').value = btn.dataset.name;\n document.getElementById('editName').value = btn.dataset.name;\n document.getElementById('editEmail').value = btn.dataset.email;\n document.getElementById('editGm').checked = btn.dataset.gm === 'true';\n document.getElementById('editAttending').value = btn.dataset.attending;\n }\n </script><footer class=\"container\"></footer></body></html>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}

6
go.mod
View file

@ -1,11 +1,9 @@
module github.com/hculpan/areweplaying
go 1.23.0
toolchain go1.24.0
go 1.25.0
require (
github.com/a-h/templ v0.3.833
github.com/a-h/templ v0.3.1020
github.com/go-chi/chi/v5 v5.2.1
)

17
go.sum
View file

@ -1,23 +1,15 @@
github.com/a-h/templ v0.2.543 h1:8YyLvyUtf0/IE2nIwZ62Z/m2o2NqwhnMynzOL78Lzbk=
github.com/a-h/templ v0.2.543/go.mod h1:jP908DQCwI08IrnTalhzSEH9WJqG/Q94+EODQcJGFUA=
github.com/a-h/templ v0.3.833 h1:L/KOk/0VvVTBegtE0fp2RJQiBm7/52Zxv5fqlEHiQUU=
github.com/a-h/templ v0.3.833/go.mod h1:cAu4AiZhtJfBjMY0HASlyzvkrtjnHWPeEsyGK2YYmfk=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/a-h/templ v0.3.1020 h1:ypAT/L5ySWEnZ6Zft/5yfoWXYYkhFNvEFOeeqecg4tw=
github.com/a-h/templ v0.3.1020/go.mod h1:A2DlK61v+K+NRoGnhmYbNYVmtYHcFO5/AisMvBdDxTM=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/emersion/go-imap v1.2.1 h1:+s9ZjMEjOB8NzZMVTM3cCenz2JrQIGGo5j1df19WjTA=
github.com/emersion/go-imap v1.2.1/go.mod h1:Qlx1FSx2FTxjnjWpIlVNEuX+ylerZQNFE5NsmKFSejY=
github.com/emersion/go-message v0.15.0/go.mod h1:wQUEfE+38+7EW8p8aZ96ptg6bAb1iwdgej19uXASlE4=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 h1:oP4q0fw+fOSWn3DfFi4EXdT+B+gTtzx8GC9xsc26Znk=
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
github.com/go-chi/chi/v5 v5.0.11 h1:BnpYbFZ3T3S1WMpD79r7R5ThWX40TaFB7L31Y8xqSwA=
github.com/go-chi/chi/v5 v5.0.11/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
@ -27,16 +19,11 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=

View file

@ -2,6 +2,7 @@ package data
import (
"encoding/json"
"fmt"
"os"
)
@ -33,3 +34,29 @@ func PersistSession(session Session) error {
err = os.WriteFile("players.json", jsonData, 0644)
return err
}
func AddPlayer(session Session, p Player) error {
session.Players = append(session.Players, p)
return PersistSession(session)
}
func DeletePlayer(session Session, name string) error {
players := make([]Player, 0, len(session.Players))
for _, p := range session.Players {
if p.Name != name {
players = append(players, p)
}
}
session.Players = players
return PersistSession(session)
}
func UpdatePlayer(session Session, originalName string, updated Player) error {
for i, p := range session.Players {
if p.Name == originalName {
session.Players[i] = updated
return PersistSession(session)
}
}
return fmt.Errorf("player %q not found", originalName)
}

View file

@ -88,6 +88,7 @@ func fetchEmails(imapClient *client.Client) ([]Email, error) {
email := NewEmail(
[]string{toAddress},
[]string{},
fromAddress,
msg.Envelope.Subject,
string(body),