package main import ( "bytes" "fmt" "net/http" "strconv" "brainminder.speedtech.it/internal/request" "brainminder.speedtech.it/internal/response" "brainminder.speedtech.it/internal/validator" "brainminder.speedtech.it/models" "github.com/alexedwards/flow" ) type categoryForm struct { Id int64 `form:"Id"` Name string `form:"Name"` Validator validator.Validator `form:"-"` } func (form *categoryForm) Validate(w http.ResponseWriter, r *http.Request, app *application, data map[string]any) bool { var fullBuf = new(bytes.Buffer) form.Validator.CheckField(form.Name != "", "Name", "Name is required") if form.Validator.HasErrors() { w.Header().Add("HX-Retarget", "#message") data["messageType"] = "failure" data["messageContent"] = "Impossible to save the type" data["messageFieldErrors"] = form.Validator.FieldErrors buf, err := response.Fragment([]string{"partials/message.tmpl"}, "message", data) if err != nil { app.serverError(w, r, err) } fullBuf.Write(buf.Bytes()) if err != nil { app.serverError(w, r, err) } fullBuf.WriteTo(w) w.WriteHeader(http.StatusUnprocessableEntity) return false } return true } func (app *application) categories(w http.ResponseWriter, r *http.Request) { data := app.newTemplateData(r) categoryModel := &models.CategoryModel{DB: app.db} rows, _, _ := categoryModel.All() data["categories"] = &rows data["messageType"] = "" data["messageContent"] = "" if r.Header.Get("HX-Request") == "true" { var fullBuf = new(bytes.Buffer) err := response.HXFragment(fullBuf, []string{"categories/list.tmpl"}, "categories:list", data) if err != nil { app.serverError(w, r, err) } err = response.HXFragmentOOB(fullBuf, []string{"categories/list_title.tmpl"}, "page:title", data, "page-title") if err != nil { app.serverError(w, r, err) } fullBuf.WriteTo(w) } else { err := response.Page(w, http.StatusOK, data, []string{"categories/index.tmpl", "categories/list.tmpl", "categories/list_title.tmpl"}) if err != nil { app.serverError(w, r, err) } } w.WriteHeader(http.StatusOK) } func (app *application) categoryCreate(w http.ResponseWriter, r *http.Request) { categoryModel := &models.CategoryModel{DB: app.db} var fullBuf = new(bytes.Buffer) var category_id int64 data := app.newTemplateData(r) data["formAction"] = "/category/create" data["formTarget"] = "#page-content" data["messageType"] = "" data["messageContent"] = "" switch r.Method { case http.MethodGet: data["category"] = categoryForm{ Name: "", } if r.Header.Get("HX-Request") == "true" { err := response.HXFragment(fullBuf, []string{"categories/form.tmpl"}, "page:content", data) if err != nil { app.serverError(w, r, err) } err = response.HXFragmentOOB(fullBuf, []string{"categories/create_title.tmpl"}, "page:title", data, "page-title") if err != nil { app.serverError(w, r, err) } fullBuf.WriteTo(w) } else { err := response.Page(w, http.StatusOK, data, []string{"categories/create_title.tmpl", "categories/form.tmpl"}) if err != nil { app.serverError(w, r, err) } } case http.MethodPost: var categoryFromForm categoryForm err := request.DecodePostForm(r, &categoryFromForm) if err != nil { app.serverError(w, r, err) } if !categoryFromForm.Validate(w, r, app, data) { return } category := &models.Category{ Name: categoryFromForm.Name, } category_id, err = categoryModel.Create(category) if err != nil { app.badRequest(w, err) return } data["formAction"] = fmt.Sprint("/category/update/", category_id) data["formTarget"] = "#message" data["category"] = categoryForm{ Id: category_id, Name: category.Name, } err = response.HXFragment(fullBuf, []string{"categories/form.tmpl"}, "page:content", data) if err != nil { app.serverError(w, r, err) } err = response.HXFragmentOOB(fullBuf, []string{"categories/update_title.tmpl"}, "page:title", data, "page-title") if err != nil { app.serverError(w, r, err) } dataMessage := make(map[string]string) dataMessage["messageType"] = "success" dataMessage["messageContent"] = "Category created successfully" err = response.HXFragmentOOB(fullBuf, []string{"partials/message.tmpl"}, "message", dataMessage, "message") if err != nil { app.serverError(w, r, err) } w.Header().Add("HX-Replace-Url", fmt.Sprint("/type/update/", category_id)) fullBuf.WriteTo(w) w.WriteHeader(http.StatusUnprocessableEntity) } } func (app *application) categoryUpdate(w http.ResponseWriter, r *http.Request) { categoryModel := &models.CategoryModel{DB: app.db} category_id_str := flow.Param(r.Context(), "category_id") category_id, _ := strconv.Atoi(category_id_str) category, _, _ := categoryModel.One(category_id) data := app.newTemplateData(r) data["formAction"] = "/category/update/" + category_id_str data["formTarget"] = "#message" data["messageType"] = "" data["messageContent"] = "" var fullBuf = new(bytes.Buffer) switch r.Method { case http.MethodGet: data["category"] = categoryForm{ Id: category.Id, Name: category.Name, } if r.Header.Get("HX-Request") == "true" { err := response.HXFragment(fullBuf, []string{"categories/form.tmpl"}, "page:content", data) if err != nil { app.serverError(w, r, err) } err = response.HXFragmentOOB(fullBuf, []string{"categories/update_title.tmpl"}, "page:title", data, "page-title") if err != nil { app.serverError(w, r, err) } fullBuf.WriteTo(w) } else { err := response.Page(w, http.StatusOK, data, []string{"categories/update_title.tmpl", "categories/form.tmpl"}) if err != nil { app.serverError(w, r, err) } } case http.MethodPost: var categoryFromForm categoryForm err := request.DecodePostForm(r, &categoryFromForm) if err != nil { app.serverError(w, r, err) } if !categoryFromForm.Validate(w, r, app, data) { return } category.Name = categoryFromForm.Name err = categoryModel.Update(category) if err != nil { app.badRequest(w, err) return } data["category"] = categoryForm{ Id: category.Id, Name: category.Name, } dataMessage := make(map[string]string) dataMessage["messageType"] = "success" dataMessage["messageContent"] = "Category saved successfully" err = response.HXFragment(fullBuf, []string{"partials/message.tmpl"}, "message", dataMessage) if err != nil { app.serverError(w, r, err) } err = response.HXFragmentOOB(fullBuf, []string{"categories/update_title.tmpl"}, "page:title", data, "page-title") if err != nil { app.serverError(w, r, err) } fullBuf.WriteTo(w) w.WriteHeader(http.StatusUnprocessableEntity) } } func (app *application) categoryDelete(w http.ResponseWriter, r *http.Request) { categoryModel := &models.CategoryModel{DB: app.db} category_id_str := flow.Param(r.Context(), "category_id") category_id, _ := strconv.Atoi(category_id_str) _, err := categoryModel.Delete(category_id) if err != nil { app.serverError(w, r, err) } }