Show form errors
This commit is contained in:
parent
5788d5b509
commit
e868f91f84
|
@ -3,6 +3,7 @@ package handler
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
"git.ekzyis.com/ekzyis/delphi.market/server/router/context"
|
"git.ekzyis.com/ekzyis/delphi.market/server/router/context"
|
||||||
"git.ekzyis.com/ekzyis/delphi.market/server/router/pages"
|
"git.ekzyis.com/ekzyis/delphi.market/server/router/pages"
|
||||||
|
@ -13,7 +14,7 @@ import (
|
||||||
func HandleUser(sc context.Context) echo.HandlerFunc {
|
func HandleUser(sc context.Context) echo.HandlerFunc {
|
||||||
return func(c echo.Context) error {
|
return func(c echo.Context) error {
|
||||||
u := c.Get("session").(types.User)
|
u := c.Get("session").(types.User)
|
||||||
return pages.User(&u).Render(context.RenderContext(sc, c), c.Response().Writer)
|
return pages.User(&u, nil).Render(context.RenderContext(sc, c), c.Response().Writer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,15 +27,25 @@ func HandleUserEdit(sc context.Context) echo.HandlerFunc {
|
||||||
name = c.FormValue("name")
|
name = c.FormValue("name")
|
||||||
|
|
||||||
maxLength = 16
|
maxLength = 16
|
||||||
|
errors types.UserEditError
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "name is required")
|
errors.Name = "required"
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(name) > maxLength {
|
if len(name) > maxLength {
|
||||||
echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("name cannot be longer than %d characters", maxLength))
|
errors.Name = fmt.Sprintf("%d characters too long", len(name)-maxLength)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !regexp.MustCompile(`^[a-zA-Z0-9_-]+$`).MatchString(name) {
|
||||||
|
errors.Name = "only letters, numbers, _ and - allowed"
|
||||||
|
}
|
||||||
|
|
||||||
|
if errors.Name != "" {
|
||||||
|
c.Response().WriteHeader(http.StatusBadRequest)
|
||||||
|
return pages.User(&u, &errors).Render(context.RenderContext(sc, c), c.Response().Writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = db.QueryRowContext(ctx,
|
if err = db.QueryRowContext(ctx,
|
||||||
|
@ -43,6 +54,6 @@ func HandleUserEdit(sc context.Context) echo.HandlerFunc {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return pages.User(&u).Render(context.RenderContext(sc, c), c.Response().Writer)
|
return pages.User(&u, &errors).Render(context.RenderContext(sc, c), c.Response().Writer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
package pages
|
package pages
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"git.ekzyis.com/ekzyis/delphi.market/server/router/pages/components"
|
"git.ekzyis.com/ekzyis/delphi.market/server/router/pages/components"
|
||||||
"git.ekzyis.com/ekzyis/delphi.market/types"
|
"git.ekzyis.com/ekzyis/delphi.market/types"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
templ User(user *types.User) {
|
templ User(user *types.User, errors *types.UserEditError) {
|
||||||
<html>
|
<html>
|
||||||
@components.Head()
|
@components.Head()
|
||||||
<body class="container">
|
<body class="container">
|
||||||
|
@ -25,27 +26,33 @@ templ User(user *types.User) {
|
||||||
<div class="font-bold">id</div>
|
<div class="font-bold">id</div>
|
||||||
<div>{ strconv.Itoa(user.Id) }</div>
|
<div>{ strconv.Itoa(user.Id) }</div>
|
||||||
<div class="font-bold">name</div>
|
<div class="font-bold">name</div>
|
||||||
<div class="flex">
|
<div>
|
||||||
<span id="name">{ user.Name }</span>
|
<div class="flex">
|
||||||
<form
|
<span id="name" class={ maybeShow("", errors == nil || errors.Name == "") }>{ user.Name }</span>
|
||||||
class="hidden flex mb-0"
|
<form
|
||||||
hx-put="/user"
|
class="hidden flex mb-0"
|
||||||
hx-push-url="false"
|
hx-put="/user"
|
||||||
hx-target="#name"
|
hx-push-url="false"
|
||||||
hx-select="#name"
|
hx-target="#name"
|
||||||
>
|
hx-select="#name"
|
||||||
<input
|
hx-select-oob="#error"
|
||||||
name="name"
|
>
|
||||||
type="text"
|
<input
|
||||||
value={ user.Name }
|
name="name"
|
||||||
required
|
type="text"
|
||||||
maxlength="16"
|
value={ user.Name }
|
||||||
class="font-mono w-[160px]"
|
class="font-mono w-[160px]"
|
||||||
/>
|
/>
|
||||||
<button class="ms-1 px-1" type="submit">save</button>
|
<button class="ms-1 px-1" type="submit">save</button>
|
||||||
</form>
|
</form>
|
||||||
<button id="cancel" class="hidden flex text-muted hover:text-reset text-xs items-center ms-1">cancel</button>
|
<button id="cancel" class="hidden flex text-muted hover:text-reset text-xs items-center ms-1">cancel</button>
|
||||||
<button id="edit" class="flex text-muted hover:text-reset text-xs items-center ms-1" hx-preserve>edit</button>
|
<button id="edit" class="flex text-muted hover:text-reset text-xs items-center ms-1">edit</button>
|
||||||
|
</div>
|
||||||
|
if errors != nil && errors.Name != "" {
|
||||||
|
<div id="error" class="text-xs text-error">{ errors.Name }</div>
|
||||||
|
} else {
|
||||||
|
<div id="error" class="hidden"></div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="font-bold">joined</div>
|
<div class="font-bold">joined</div>
|
||||||
<div>{ user.CreatedAt.Format(time.DateOnly) }</div>
|
<div>{ user.CreatedAt.Format(time.DateOnly) }</div>
|
||||||
|
@ -69,10 +76,19 @@ templ User(user *types.User) {
|
||||||
|
|
||||||
htmx.on("#edit", "click", toggleForm)
|
htmx.on("#edit", "click", toggleForm)
|
||||||
htmx.on("#cancel", "click", toggleForm)
|
htmx.on("#cancel", "click", toggleForm)
|
||||||
htmx.on("form", "htmx:afterRequest", toggleForm)
|
htmx.on("form", "htmx:afterRequest", ({ detail }) => {
|
||||||
|
if (detail.successful) toggleForm()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
@components.Footer()
|
@components.Footer()
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func maybeShow(class string, show bool) string {
|
||||||
|
if show {
|
||||||
|
return class
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s %s", class, "hidden")
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,10 @@ type User struct {
|
||||||
Msats int64
|
Msats int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserEditError struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
type Invoice struct {
|
type Invoice struct {
|
||||||
Id int
|
Id int
|
||||||
UserId int
|
UserId int
|
||||||
|
|
Loading…
Reference in New Issue