package web import ( "errors" "net/http" "strings" "time" "gardomatic.kleiax.de/lib/client" ) type assignmentForm struct { CSRFToken string `form:"csrf_token"` LocationID int `form:"location_id"` Quantity int `form:"quantity"` PlantedAt string `form:"planted_at"` Notes string `form:"notes"` Errors map[string]string } func (app *application) plantLocationCreate(w http.ResponseWriter, r *http.Request) { app.renderPlantLocationForm(w, r, assignmentForm{Quantity: 1, Errors: map[string]string{}}, http.StatusOK, 0) } func (app *application) plantLocationEdit(w http.ResponseWriter, r *http.Request) { gardenID, err := app.readPathID(r, "gardenID") if err != nil { app.notFound(w) return } plantID, err := app.readPathID(r, "plantID") if err != nil { app.notFound(w) return } assignmentID, err := app.readPathID(r, "assignmentID") if err != nil { app.notFound(w) return } items, _, err := client.FromContext(r.Context()).PlantLocations(r.Context(), gardenID, plantID) if err != nil { app.handleAPIError(w, r, err) return } form := assignmentForm{Errors: map[string]string{}} found := false for _, item := range items { if item.ID == assignmentID { found = true form.LocationID = item.LocationID form.Quantity = item.Quantity form.Notes = item.Notes if item.PlantedAt != nil { form.PlantedAt = item.PlantedAt.Format("2006-01-02") } break } } if !found { app.notFound(w) return } app.renderPlantLocationForm(w, r, form, http.StatusOK, assignmentID) } func (app *application) plantLocationSave(w http.ResponseWriter, r *http.Request) { gardenID, err := app.readPathID(r, "gardenID") if err != nil { app.notFound(w) return } plantID, err := app.readPathID(r, "plantID") if err != nil { app.notFound(w) return } assignmentID, _ := app.readPathID(r, "assignmentID") var form assignmentForm if err = app.decodePostForm(r, &form); err != nil { app.clientError(w, http.StatusBadRequest) return } form.Notes = strings.TrimSpace(form.Notes) form.Errors = map[string]string{} if form.LocationID < 1 { form.Errors["location_id"] = "Ein Ort ist erforderlich." } if form.Quantity < 1 { form.Errors["quantity"] = "Die Anzahl muss mindestens 1 sein." } var plantedAt *time.Time if form.PlantedAt != "" { parsed, parseErr := time.Parse("2006-01-02", form.PlantedAt) if parseErr != nil { form.Errors["planted_at"] = "Das Datum ist ungültig." } else { plantedAt = &parsed } } if len(form.Errors) == 0 { locationID, quantity, notes := form.LocationID, form.Quantity, form.Notes input := client.PlantLocationInput{LocationID: &locationID, Quantity: &quantity, PlantedAt: plantedAt, ClearPlantedAt: plantedAt == nil, Notes: ¬es} apiClient := client.FromContext(r.Context()) if assignmentID > 0 { _, _, err = apiClient.UpdatePlantLocation(r.Context(), gardenID, plantID, assignmentID, input) } else { _, _, err = apiClient.CreatePlantLocation(r.Context(), gardenID, plantID, input) } if err == nil { http.Redirect(w, r, webPath("plants", gardenID), http.StatusSeeOther) return } var apiError *client.APIError if errors.As(err, &apiError) && apiError.StatusCode == http.StatusUnprocessableEntity { form.Errors = apiError.Validation } else { app.handleAPIError(w, r, err) return } } app.renderPlantLocationForm(w, r, form, http.StatusUnprocessableEntity, assignmentID) } func (app *application) plantLocationDeletePost(w http.ResponseWriter, r *http.Request) { gardenID, err := app.readPathID(r, "gardenID") if err != nil { app.notFound(w) return } plantID, err := app.readPathID(r, "plantID") if err != nil { app.notFound(w) return } assignmentID, err := app.readPathID(r, "assignmentID") if err != nil { app.notFound(w) return } if _, err = client.FromContext(r.Context()).DeletePlantLocation(r.Context(), gardenID, plantID, assignmentID); err != nil { app.handleAPIError(w, r, err) return } http.Redirect(w, r, webPath("plants", gardenID), http.StatusSeeOther) } func (app *application) renderPlantLocationForm(w http.ResponseWriter, r *http.Request, form assignmentForm, status, assignmentID int) { gardenID, err := app.readPathID(r, "gardenID") if err != nil { app.notFound(w) return } plantID, err := app.readPathID(r, "plantID") if err != nil { app.notFound(w) return } apiClient := client.FromContext(r.Context()) garden, _, err := apiClient.Garden(r.Context(), gardenID) if err != nil { app.handleAPIError(w, r, err) return } plant, _, err := apiClient.Plant(r.Context(), gardenID, plantID) if err != nil { app.handleAPIError(w, r, err) return } locations, _, err := apiClient.Locations(r.Context(), gardenID) if err != nil { app.handleAPIError(w, r, err) return } data := app.newTemplateData(r) data.Garden = &garden data.Plants = []client.Plant{plant} data.PlantID = plantID data.LocationID = assignmentID data.Locations = locations data.Form = form app.render(w, status, "plant_location_form.tmpl", data) }