diff --git a/controller/htmx.go b/controller/htmx.go new file mode 100644 index 0000000..1ed8461 --- /dev/null +++ b/controller/htmx.go @@ -0,0 +1,48 @@ +package controller + +import ( + "github.com/labstack/echo/v4" +) + +// HTMX headers (https://htmx.org/docs/#requests) +const ( + HTMXHeaderRequest = "HX-Request" + HTMXHeaderTrigger = "HX-Trigger" + HTMXHeaderTriggerName = "HX-Trigger-Name" + HTMXHeaderTriggerAfterSwap = "HX-Trigger-After-Swap" + HTMXHeaderTriggerAfterSettle = "HX-Trigger-After-Settle" + HTMXHeaderTarget = "HX-Target" + HTMXHeaderPrompt = "HX-Prompt" + HTMXHeaderPush = "HX-Push" + HTMXHeaderRedirect = "HX-Redirect" + HTMXHeaderRefresh = "HX-Refresh" +) + +type ( + HTMXRequest struct { + Enabled bool + Trigger string + TriggerName string + Target string + Prompt string + } + + HTMXResponse struct { + Push string + Redirect string + Refresh bool + Trigger string + TriggerAfterSwap string + TriggerAfterSettle string + } +) + +func NewHTMXRequest(ctx echo.Context) HTMXRequest { + return HTMXRequest{ + Enabled: ctx.Request().Header.Get(HTMXHeaderRequest) == "true", + Trigger: ctx.Request().Header.Get(HTMXHeaderTrigger), + TriggerName: ctx.Request().Header.Get(HTMXHeaderTriggerName), + Target: ctx.Request().Header.Get(HTMXHeaderTarget), + Prompt: ctx.Request().Header.Get(HTMXHeaderPrompt), + } +} diff --git a/routes/about.go b/routes/about.go index 2aeb460..b49b685 100644 --- a/routes/about.go +++ b/routes/about.go @@ -16,7 +16,7 @@ func (a *About) Get(c echo.Context) error { p.Name = "about" p.Title = "About" p.Data = "This is the about page" - p.Cache.Enabled = true + p.Cache.Enabled = false p.Cache.Tags = []string{"page_about", "page:list"} return a.RenderPage(c, p) diff --git a/routes/contact.go b/routes/contact.go index 7dc5881..a787e3f 100644 --- a/routes/contact.go +++ b/routes/contact.go @@ -1,27 +1,67 @@ package routes import ( + "net/http" + + "goweb/context" "goweb/controller" "goweb/msg" "github.com/labstack/echo/v4" ) -type Contact struct { - controller.Controller -} +type ( + Contact struct { + controller.Controller + } -func (a *Contact) Get(c echo.Context) error { - p := controller.NewPage(c) + ContactForm struct { + Email string `form:"email" validate:"required,email" label:"Email address"` + Message string `form:"message" validate:"required" label:"Message"` + } +) + +func (c *Contact) Get(ctx echo.Context) error { + p := controller.NewPage(ctx) p.Layout = "main" p.Name = "contact" p.Title = "Contact us" - p.Data = "This is the contact page" - return a.RenderPage(c, p) + p.Data = ContactForm{} + + if form := ctx.Get(context.FormKey); form != nil { + p.Data = form.(ContactForm) + } + + return c.RenderPage(ctx, p) } -func (a *Contact) Post(c echo.Context) error { - msg.Success(c, "Thank you for contacting us!") - msg.Info(c, "We will respond to you shortly.") - return a.Redirect(c, "home") +func (c *Contact) Post(ctx echo.Context) error { + fail := func(message string, err error) error { + ctx.Logger().Errorf("%s: %v", message, err) + msg.Danger(ctx, "An error occurred. Please try again.") + return c.Get(ctx) + } + + // Parse the form values + var form ContactForm + if err := ctx.Bind(&form); err != nil { + return fail("unable to parse contact form", err) + } + ctx.Set(context.FormKey, form) + + // Validate the form + if err := ctx.Validate(form); err != nil { + c.SetValidationErrorMessages(ctx, err, form) + return c.Get(ctx) + } + + p := controller.NewHTMX(ctx) + + if p.Request.Enabled { + return ctx.String(http.StatusOK, "HELLO!") + } else { + msg.Success(ctx, "Thank you for contacting us!") + msg.Info(ctx, "We will respond to you shortly.") + return c.Redirect(ctx, "home") + } } diff --git a/routes/forgot_password.go b/routes/forgot_password.go index f7a19d3..545395e 100644 --- a/routes/forgot_password.go +++ b/routes/forgot_password.go @@ -50,11 +50,11 @@ func (f *ForgotPassword) Post(c echo.Context) error { } // Parse the form values - form := new(ForgotPasswordForm) - if err := c.Bind(form); err != nil { + var form ForgotPasswordForm + if err := c.Bind(&form); err != nil { return fail("unable to parse forgot password form", err) } - c.Set(context.FormKey, *form) + c.Set(context.FormKey, form) // Validate the form if err := c.Validate(form); err != nil { diff --git a/routes/login.go b/routes/login.go index f45520f..2219dee 100644 --- a/routes/login.go +++ b/routes/login.go @@ -45,11 +45,11 @@ func (l *Login) Post(c echo.Context) error { } // Parse the form values - form := new(LoginForm) - if err := c.Bind(form); err != nil { + var form LoginForm + if err := c.Bind(&form); err != nil { return fail("unable to parse login form", err) } - c.Set(context.FormKey, *form) + c.Set(context.FormKey, form) // Validate the form if err := c.Validate(form); err != nil { diff --git a/routes/register.go b/routes/register.go index 3ed267e..43d9298 100644 --- a/routes/register.go +++ b/routes/register.go @@ -44,11 +44,11 @@ func (r *Register) Post(c echo.Context) error { } // Parse the form values - form := new(RegisterForm) - if err := c.Bind(form); err != nil { + var form RegisterForm + if err := c.Bind(&form); err != nil { return fail("unable to parse form values", err) } - c.Set(context.FormKey, *form) + c.Set(context.FormKey, form) // Validate the form if err := c.Validate(form); err != nil { diff --git a/routes/reset_password.go b/routes/reset_password.go index 4024da5..6dcb643 100644 --- a/routes/reset_password.go +++ b/routes/reset_password.go @@ -37,8 +37,8 @@ func (r *ResetPassword) Post(c echo.Context) error { } // Parse the form values - form := new(ResetPasswordForm) - if err := c.Bind(form); err != nil { + var form ResetPasswordForm + if err := c.Bind(&form); err != nil { return fail("unable to parse forgot password form", err) } diff --git a/templates/components/head.gohtml b/templates/components/head.gohtml index 950fbc0..af80dd8 100644 --- a/templates/components/head.gohtml +++ b/templates/components/head.gohtml @@ -17,5 +17,6 @@ {{end}} {{define "js"}} + {{end}} \ No newline at end of file diff --git a/templates/layouts/main.gohtml b/templates/layouts/main.gohtml index dfe4f24..8b73007 100644 --- a/templates/layouts/main.gohtml +++ b/templates/layouts/main.gohtml @@ -7,7 +7,7 @@