persist form values on errors

This commit is contained in:
Ruidy 2024-03-10 19:36:57 +01:00
parent de8dad8fa8
commit 89ffba3af3
No known key found for this signature in database
GPG key ID: E00F51288CB857CC
3 changed files with 164 additions and 56 deletions

View file

@ -1,7 +1,6 @@
package server package server
import ( import (
"errors"
"fmt" "fmt"
"net/http" "net/http"
"time" "time"
@ -20,27 +19,36 @@ func handleHomePage() echo.HandlerFunc {
func handleRequestBooking() echo.HandlerFunc { func handleRequestBooking() echo.HandlerFunc {
return func(c echo.Context) error { return func(c echo.Context) error {
// validate the form request itemStr := c.FormValue("item")
// no time travelling
fromStr := c.FormValue("from") fromStr := c.FormValue("from")
toStr := c.FormValue("to") toStr := c.FormValue("to")
name := c.FormValue("item")
phoneNumber := c.FormValue("phone")
email := c.FormValue("email")
from, fErr := myTime.ParseFromForm(fromStr) from, fErr := myTime.ParseFromForm(fromStr)
to, tErr := myTime.ParseFromForm(toStr) to, tErr := myTime.ParseFromForm(toStr)
if fErr != nil || tErr != nil { if fErr != nil || tErr != nil {
return fmt.Errorf("error parsing booking request time: %q %q", fErr, tErr) return fmt.Errorf("error parsing booking request time: %q %q", fErr, tErr)
} }
errs := make([]error, 0) errs := make([]string, 0)
if to.Sub(from) < time.Duration(0) { if to.Sub(from) < time.Duration(0) {
errs = append(errs, errors.New("invalid_time_range")) errs = append(errs, "invalid_time_range")
} }
phoneNumber := c.FormValue("phone")
email := c.FormValue("email")
if phoneNumber == "" && email == "" { if phoneNumber == "" && email == "" {
errs = append(errs, errors.New("missing_communication_method")) errs = append(errs, "missing_communication_method")
} }
return renderTempl(c, http.StatusOK, view.RequestBookingForm(errs)) return renderTempl(c, http.StatusOK, view.RequestBookingForm(&view.RequestBookingViewModel{
Item: itemStr,
From: fromStr,
To: toStr,
Name: name,
PhoneNumber: phoneNumber,
Email: email,
Errors: errs,
}))
} }
} }

View file

@ -15,25 +15,35 @@ func makeItems() []string {
var items = makeItems() var items = makeItems()
func invalidTimeRange(errs []error) bool { type RequestBookingViewModel struct {
for _, e := range errs { Item string
if e.Error() == "invalid_time_range" { From string
To string
Name string
PhoneNumber string
Email string
Errors []string
}
func (rbvm RequestBookingViewModel) invalidTimeRange() bool {
for _, e := range rbvm.Errors {
if e == "invalid_time_range" {
return true return true
} }
} }
return false return false
} }
func missingCommunicationMethod(errs []error) bool { func (rbvm RequestBookingViewModel) missingCommunicationMethod() bool {
for _, e := range errs { for _, e := range rbvm.Errors {
if e.Error() == "missing_communication_method" { if e == "missing_communication_method" {
return true return true
} }
} }
return false return false
} }
templ RequestBookingForm(errors []error) { templ RequestBookingForm(rbvm *RequestBookingViewModel) {
<form id="booking-request-form" hx-post="/request-booking"> <form id="booking-request-form" hx-post="/request-booking">
<fieldset class="grid"> <fieldset class="grid">
<label for="item"> <label for="item">
@ -46,38 +56,38 @@ templ RequestBookingForm(errors []error) {
</label> </label>
<label for="from"> <label for="from">
Du Du
<input type="date" id="from" name="from" required/> <input type="date" id="from" name="from" value={ rbvm.From } required/>
</label> </label>
<label for="to"> <label for="to">
Au Au
if (invalidTimeRange(errors)) { if rbvm.invalidTimeRange() {
<input type="date" id="to" name="to" required aria-invalid="true"/> <input type="date" id="to" name="to" value={ rbvm.To } required aria-invalid="true"/>
<small>La date de depart doit etre apres celle d'arrivee</small> <small>La date de depart doit etre apres celle d'arrivee</small>
} else { } else {
<input type="date" id="to" name="to" required/> <input type="date" id="to" name="to" value={ rbvm.To } required/>
} }
</label> </label>
</fieldset> </fieldset>
<fieldset class="grid"> <fieldset class="grid">
<label for="name"> <label for="name">
Nom * Nom *
<input type="text" id="name" name="name" required/> <input type="text" id="name" name="name" value={ rbvm.Name } required/>
</label> </label>
<label for="phone"> <label for="phone">
Telephone Telephone
if missingCommunicationMethod(errors) { if rbvm.missingCommunicationMethod() {
<input type="tel" id="phone" name="phone" aria-invalid="true"/> <input type="tel" id="phone" name="phone" value={ rbvm.PhoneNumber } aria-invalid="true"/>
<small>Veuillez renseigner votre numéro de télephone ou votre adresse email</small> <small>Veuillez renseigner votre numéro de télephone ou votre adresse email</small>
} else { } else {
<input type="tel" id="phone" name="phone"/> <input type="tel" id="phone" value={ rbvm.PhoneNumber } name="phone"/>
} }
</label> </label>
<label for="email"> <label for="email">
Email Email
if missingCommunicationMethod(errors) { if rbvm.missingCommunicationMethod() {
<input type="email" id="email" name="email" aria-invalid="true"/> <input type="email" id="email" name="email" value={ rbvm.Email } aria-invalid="true"/>
} else { } else {
<input type="email" id="email" name="email"/> <input type="email" id="email" name="email" value={ rbvm.Email }/>
} }
</label> </label>
</fieldset> </fieldset>
@ -94,7 +104,15 @@ templ Index() {
<section> <section>
<h1>Reserver votre sejour des maintenant</h1> <h1>Reserver votre sejour des maintenant</h1>
<article> <article>
@RequestBookingForm(nil) @RequestBookingForm(&RequestBookingViewModel{
Item: "T2",
From: "",
To: "",
Name: "",
PhoneNumber: "",
Email: "",
Errors: nil,
})
</article> </article>
</section> </section>
} }

View file

@ -25,25 +25,35 @@ func makeItems() []string {
var items = makeItems() var items = makeItems()
func invalidTimeRange(errs []error) bool { type RequestBookingViewModel struct {
for _, e := range errs { Item string
if e.Error() == "invalid_time_range" { From string
To string
Name string
PhoneNumber string
Email string
Errors []string
}
func (rbvm RequestBookingViewModel) invalidTimeRange() bool {
for _, e := range rbvm.Errors {
if e == "invalid_time_range" {
return true return true
} }
} }
return false return false
} }
func missingCommunicationMethod(errs []error) bool { func (rbvm RequestBookingViewModel) missingCommunicationMethod() bool {
for _, e := range errs { for _, e := range rbvm.Errors {
if e.Error() == "missing_communication_method" { if e == "missing_communication_method" {
return true return true
} }
} }
return false return false
} }
func RequestBookingForm(errors []error) templ.Component { func RequestBookingForm(rbvm *RequestBookingViewModel) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer { if !templ_7745c5c3_IsBuffer {
@ -56,12 +66,12 @@ func RequestBookingForm(errors []error) templ.Component {
templ_7745c5c3_Var1 = templ.NopComponent templ_7745c5c3_Var1 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<form id=\"booking-request-form\" hx-post=\"/request-booking\"><fieldset class=\"grid\"><label for=\"item\">Logement <select name=\"item\" id=\"item\" required>") templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
for _, i := range items { for _, i := range items {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<option value=\"") templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -69,70 +79,134 @@ func RequestBookingForm(errors []error) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var2 string var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(i) templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(i)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/index.templ`, Line: 42, Col: 29} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/index.templ`, Line: 52, Col: 29}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</option>") templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</select></label> <label for=\"from\">Du <input type=\"date\" id=\"from\" name=\"from\" required></label> <label for=\"to\">Au ") templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
if invalidTimeRange(errors) { _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(rbvm.From))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<input type=\"date\" id=\"to\" name=\"to\" required aria-invalid=\"true\"> <small>La date de depart doit etre apres celle d'arrivee</small>") if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 6)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if rbvm.invalidTimeRange() {
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(rbvm.To))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
} else { } else {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<input type=\"date\" id=\"to\" name=\"to\" required>") templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(rbvm.To))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 10)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</label></fieldset><fieldset class=\"grid\"><label for=\"name\">Nom * <input type=\"text\" id=\"name\" name=\"name\" required></label> <label for=\"phone\">Telephone ") templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 11)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
if missingCommunicationMethod(errors) { _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(rbvm.Name))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<input type=\"tel\" id=\"phone\" name=\"phone\" aria-invalid=\"true\"> <small>Veuillez renseigner votre numéro de télephone ou votre adresse email</small>") if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 12)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if rbvm.missingCommunicationMethod() {
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 13)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(rbvm.PhoneNumber))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 14)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
} else { } else {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<input type=\"tel\" id=\"phone\" name=\"phone\">") templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 15)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(rbvm.PhoneNumber))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 16)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</label> <label for=\"email\">Email ") templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 17)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
if missingCommunicationMethod(errors) { if rbvm.missingCommunicationMethod() {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<input type=\"email\" id=\"email\" name=\"email\" aria-invalid=\"true\">") templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 18)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(rbvm.Email))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 19)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
} else { } else {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<input type=\"email\" id=\"email\" name=\"email\">") templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 20)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(rbvm.Email))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 21)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</label></fieldset><label for=\"message\">Message <textarea name=\"message\" id=\"message\"></textarea></label> <button type=\"submit\">Book</button></form>") templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 22)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -162,15 +236,23 @@ func Index() templ.Component {
templ_7745c5c3_Buffer = templ.GetBuffer() templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<section><h1>Reserver votre sejour des maintenant</h1><article>") templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 23)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = RequestBookingForm(nil).Render(ctx, templ_7745c5c3_Buffer) templ_7745c5c3_Err = RequestBookingForm(&RequestBookingViewModel{
Item: "T2",
From: "",
To: "",
Name: "",
PhoneNumber: "",
Email: "",
Errors: nil,
}).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</article></section>") templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 24)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }