fix: renderOTPForm in auth.go now uses cached single-field template

- Was using its own inline template with 6 digit_0..digit_5 fields
- Now calls getTemplate('otp_form') which has the single 6-digit input
- templates.go already had the correct single-field version
This commit is contained in:
Claus Lohmar 2026-06-03 07:57:56 +00:00
parent cb42efa395
commit 91534ed8bd

View file

@ -257,35 +257,10 @@ func renderError(w http.ResponseWriter, message string) {
fmt.Fprintf(w, `<div class="error-message" style="color: #fca5a5; margin-bottom: 1rem;">%s</div>`, template.HTMLEscapeString(message))
}
// renderOTPForm writes the OTP verification form partial as an HTMX fragment.
// It renders 6 individual digit input boxes for a better mobile UX, plus a
// hidden email field. The handler combines the 6 digits server-side.
// If errMsg is non-empty, it is displayed as an error banner above the form.
// renderOTPForm writes the OTP verification form partial as an HTMX fragment
// using the cached otp_form template from templates.go.
func renderOTPForm(w http.ResponseWriter, email string, errMsg string) {
tmpl := template.Must(template.New("otp_form").Parse(`
<form hx-post="/verify-otp" hx-target="#otp-form" hx-swap="innerHTML">
<input type="hidden" name="email" value="{{.Email}}">
{{if .Error}}<div class="error-message" style="color: #fca5a5; background: #450a0a; border: 1px solid #7f1d1d; padding: 0.75rem; border-radius: 0.5rem; margin-bottom: 1rem;">{{.Error}}</div>{{end}}
<div style="display: flex; gap: 0.5rem; justify-content: center; margin: 1rem 0;">
<input type="text" name="digit_0" maxlength="1" pattern="[0-9]" inputmode="numeric" autocomplete="one-time-code" required
style="width: 3rem; height: 3rem; text-align: center; font-size: 1.5rem; border: 2px solid #d1d5db; border-radius: 0.5rem;">
<input type="text" name="digit_1" maxlength="1" pattern="[0-9]" inputmode="numeric" required
style="width: 3rem; height: 3rem; text-align: center; font-size: 1.5rem; border: 2px solid #d1d5db; border-radius: 0.5rem;">
<input type="text" name="digit_2" maxlength="1" pattern="[0-9]" inputmode="numeric" required
style="width: 3rem; height: 3rem; text-align: center; font-size: 1.5rem; border: 2px solid #d1d5db; border-radius: 0.5rem;">
<input type="text" name="digit_3" maxlength="1" pattern="[0-9]" inputmode="numeric" required
style="width: 3rem; height: 3rem; text-align: center; font-size: 1.5rem; border: 2px solid #d1d5db; border-radius: 0.5rem;">
<input type="text" name="digit_4" maxlength="1" pattern="[0-9]" inputmode="numeric" required
style="width: 3rem; height: 3rem; text-align: center; font-size: 1.5rem; border: 2px solid #d1d5db; border-radius: 0.5rem;">
<input type="text" name="digit_5" maxlength="1" pattern="[0-9]" inputmode="numeric" required
style="width: 3rem; height: 3rem; text-align: center; font-size: 1.5rem; border: 2px solid #d1d5db; border-radius: 0.5rem;">
</div>
<button type="submit" style="width: 100%; padding: 0.75rem; background-color: #10b981; color: white; border: none; border-radius: 0.5rem; font-size: 1rem; cursor: pointer;">
Verify Code
</button>
</form>
`))
tmpl := getTemplate("otp_form")
w.Header().Set("Content-Type", "text/html; charset=utf-8")
if err := tmpl.Execute(w, map[string]string{"Email": email, "Error": errMsg}); err != nil {
log.Printf("ERROR [%s] handlers: renderOTPForm execute: %v", time.Now().Format(time.RFC3339), err)