package server import ( "context" "fmt" "net/http" "github.com/a-h/templ" "github.com/go-playground/validator/v10" "gopics.develent.net/internal/components" ) // Extract form and validate fields func (srv *server) bindAndValidate(r *http.Request, form any) (map[string]string, error) { err := r.ParseForm() if err != nil { return nil, err } err = srv.formDecoder.Decode(form, r.PostForm) if err != nil { return nil, err } err = srv.validate.Struct(form) if err != nil { ve, ok := err.(validator.ValidationErrors) srv.logger.Info("BnV Validation", "ok", ok, "ve", ve) if ok { return mapValidationErrors(ve), nil // validation failed } return nil, err // something else went wrong } return nil, nil // valid } // Render TEMPL pages func (srv *server) RenderPage(w http.ResponseWriter, r *http.Request, status int, page templ.Component, title string) { w.WriteHeader(status) flash := srv.sessionManager.PopString(r.Context(), "flash") components.Base(page, title, flash).Render(r.Context(), w) } // Inject flash messages into context func (srv *server) PutFlash(ctx context.Context, msg string) { srv.sessionManager.Put(ctx, "flash", msg) } // Pop flash messages from context func (srv *server) PopFlash(ctx context.Context) string { srv.logger.Info("Pre-Pop", "flash", srv.sessionManager.GetString(ctx, "flash")) flash := srv.sessionManager.PopString(ctx, "flash") srv.logger.Info("Post-Pop", "flash", srv.sessionManager.GetString(ctx, "flash")) return flash } // Map validator errors to user presentable errors func mapValidationErrors(errs validator.ValidationErrors) map[string]string { errors := make(map[string]string) for _, fe := range errs { field := fe.Field() tag := fe.Tag() var msg string switch tag { case "required": msg = fmt.Sprintf("%s is required", field) case "email": msg = "Invalid email format" case "gte": msg = fmt.Sprintf("%s must be %s or greater", field, fe.Param()) default: msg = fmt.Sprintf("%s is not valid", field) } errors[field] = msg } return errors }