/* * SPDX-FileCopyrightText: 2023 jordi fita mas * SPDX-License-Identifier: AGPL-3.0-only */ package campsite import ( "context" "net/http" "dev.tandem.ws/tandem/camper/pkg/auth" "dev.tandem.ws/tandem/camper/pkg/database" "dev.tandem.ws/tandem/camper/pkg/form" httplib "dev.tandem.ws/tandem/camper/pkg/http" "dev.tandem.ws/tandem/camper/pkg/locale" "dev.tandem.ws/tandem/camper/pkg/template" ) type typeHandler struct { } func (h *typeHandler) Handler(user *auth.User, company *auth.Company, conn *database.Conn) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var head string head, r.URL.Path = httplib.ShiftPath(r.URL.Path) switch head { case "new": switch r.Method { case http.MethodGet: f := newTypeForm() f.MustRender(w, r, user, company) default: httplib.MethodNotAllowed(w, r, http.MethodGet) } case "": switch r.Method { case http.MethodGet: serveTypeIndex(w, r, user, company, conn) case http.MethodPost: addType(w, r, user, company, conn) default: httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPost) } default: http.NotFound(w, r) } }) } func serveTypeIndex(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) { types, err := collectTypeEntries(r.Context(), company, conn) if err != nil { panic(err) } page := &typeIndex{ Types: types, } page.MustRender(w, r, user, company) } type typeEntry struct { Slug string Name string } func collectTypeEntries(ctx context.Context, company *auth.Company, conn *database.Conn) ([]*typeEntry, error) { rows, err := conn.Query(ctx, "select slug, name from campsite_type where company_id = $1", company.ID) if err != nil { return nil, err } defer rows.Close() var types []*typeEntry for rows.Next() { entry := &typeEntry{} if err = rows.Scan(&entry.Slug, &entry.Name); err != nil { return nil, err } types = append(types, entry) } return types, nil } type typeIndex struct { Types []*typeEntry } func (page *typeIndex) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) { template.MustRender(w, r, user, company, "campsite/type/index.gohtml", page) } func addType(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) { f := newTypeForm() if err := f.Parse(r); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } if err := user.VerifyCSRFToken(r); err != nil { http.Error(w, err.Error(), http.StatusForbidden) return } if !f.Valid(user.Locale) { if !httplib.IsHTMxRequest(r) { w.WriteHeader(http.StatusUnprocessableEntity) } f.MustRender(w, r, user, company) return } conn.MustExec(r.Context(), "select add_campsite_type($1, $2, $3)", company.ID, f.Name, f.Description) httplib.Redirect(w, r, "/campsites/types", http.StatusSeeOther) } type typeForm struct { Name *form.Input Description *form.Input } func newTypeForm() *typeForm { return &typeForm{ Name: &form.Input{ Name: "name", }, Description: &form.Input{ Name: "description", }, } } func (f *typeForm) Parse(r *http.Request) error { if err := r.ParseForm(); err != nil { return err } f.Name.FillValue(r) f.Description.FillValue(r) return nil } func (f *typeForm) Valid(l *locale.Locale) bool { v := form.NewValidator(l) v.CheckRequired(f.Name, l.GettextNoop("Name can not be empty.")) return v.AllOK } func (f *typeForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) { template.MustRender(w, r, user, company, "campsite/type/new.gohtml", f) }