package app import ( "net/http" "strconv" "strings" "archi_folio/internal/store" ) func (s *Server) adminUpdateContent(w http.ResponseWriter, r *http.Request) { if err := parseAdminForm(w, r, maxFormBytes); err != nil { s.redirectAdmin(w, r, "main", "content form failed") return } current, err := s.store.SiteContent(r.Context()) if err != nil { s.redirectAdmin(w, r, "main", "content could not be loaded") return } content := store.SiteContent{ HeroTitle: formValueOr(r, "hero_title", current.HeroTitle), HeroSubtitle: formValueOr(r, "hero_subtitle", current.HeroSubtitle), Positioning: formValueOr(r, "positioning", current.Positioning), HeroCTALabel: formValueOr(r, "hero_cta_label", current.HeroCTALabel), HeroCTAURL: formValueOr(r, "hero_cta_url", current.HeroCTAURL), SecondaryCTALabel: formValueOr(r, "secondary_cta_label", current.SecondaryCTALabel), SecondaryCTAURL: formValueOr(r, "secondary_cta_url", current.SecondaryCTAURL), IntroTitle: formValueOr(r, "intro_title", current.IntroTitle), IntroText: formValueOr(r, "intro_text", current.IntroText), ServiceOneTitle: formValueOr(r, "service_one_title", current.ServiceOneTitle), ServiceOneText: formValueOr(r, "service_one_text", current.ServiceOneText), ServiceTwoTitle: formValueOr(r, "service_two_title", current.ServiceTwoTitle), ServiceTwoText: formValueOr(r, "service_two_text", current.ServiceTwoText), ServiceThreeTitle: formValueOr(r, "service_three_title", current.ServiceThreeTitle), ServiceThreeText: formValueOr(r, "service_three_text", current.ServiceThreeText), ProcessOneTitle: formValueOr(r, "process_one_title", current.ProcessOneTitle), ProcessOneText: formValueOr(r, "process_one_text", current.ProcessOneText), ProcessTwoTitle: formValueOr(r, "process_two_title", current.ProcessTwoTitle), ProcessTwoText: formValueOr(r, "process_two_text", current.ProcessTwoText), ProcessThreeTitle: formValueOr(r, "process_three_title", current.ProcessThreeTitle), ProcessThreeText: formValueOr(r, "process_three_text", current.ProcessThreeText), AboutName: formValueOr(r, "about_name", current.AboutName), AboutRole: formValueOr(r, "about_role", current.AboutRole), AboutBio: formValueOr(r, "about_bio", current.AboutBio), StudioPhilosophy: formValueOr(r, "studio_philosophy", current.StudioPhilosophy), StudioApproach: formValueOr(r, "studio_approach", current.StudioApproach), StudioCredentials: formValueOr(r, "studio_credentials", current.StudioCredentials), ServiceArea: formValueOr(r, "service_area", current.ServiceArea), Email: current.Email, Phone: current.Phone, Location: current.Location, HeroImage: formValueOr(r, "hero_image_current", current.HeroImage), AboutImage: formValueOr(r, "about_image_current", current.AboutImage), } if err := validateContent(content); err != nil { s.redirectAdmin(w, r, "main", err.Error()) return } if path, ok, err := s.saveUpload(r, "hero_image"); err != nil { s.redirectAdmin(w, r, "main", "hero image "+err.Error()) return } else if ok { content.HeroImage = path } if path, ok, err := s.saveUpload(r, "about_image"); err != nil { s.redirectAdmin(w, r, "main", "about image "+err.Error()) return } else if ok { content.AboutImage = path } if err := s.store.UpdateSiteContent(r.Context(), content); err != nil { s.redirectAdmin(w, r, "main", "content could not be saved") return } s.redirectAdmin(w, r, "main", "content saved") } func (s *Server) adminUpdateContactDetails(w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { s.redirectAdmin(w, r, "contact-details", "contact details form failed") return } content, err := s.store.SiteContent(r.Context()) if err != nil { s.redirectAdmin(w, r, "contact-details", "contact details could not be loaded") return } content.Email = strings.TrimSpace(r.FormValue("email")) content.Phone = strings.TrimSpace(r.FormValue("phone")) content.Location = strings.TrimSpace(r.FormValue("location")) if err := validateContactDetails(content); err != nil { s.redirectAdmin(w, r, "contact-details", err.Error()) return } if err := s.store.UpdateSiteContent(r.Context(), content); err != nil { s.redirectAdmin(w, r, "contact-details", "contact details could not be saved") return } s.redirectAdmin(w, r, "contact-details", "contact details saved") } func (s *Server) adminCreateProject(w http.ResponseWriter, r *http.Request) { if err := parseAdminForm(w, r, maxFormBytes); err != nil { s.redirectAdmin(w, r, "projects", "project form failed") return } cover := "/static/placeholders/project-1.svg" if path, ok, err := s.saveUpload(r, "cover_image"); err != nil { s.redirectAdmin(w, r, "projects", "cover upload "+err.Error()) return } else if ok { cover = path } slug := strings.TrimSpace(r.FormValue("slug")) if slug == "" { slug = store.SlugFromTitle(r.FormValue("title")) } else { slug = store.SlugFromTitle(slug) } project := store.Project{ Slug: slug, Title: strings.TrimSpace(r.FormValue("title")), Location: strings.TrimSpace(r.FormValue("location")), Year: strings.TrimSpace(r.FormValue("year")), Category: strings.TrimSpace(r.FormValue("category")), Summary: strings.TrimSpace(r.FormValue("summary")), Scope: strings.TrimSpace(r.FormValue("scope")), Status: strings.TrimSpace(r.FormValue("status")), Position: formInt(r, "position"), Description: strings.TrimSpace(r.FormValue("description")), CoverImage: cover, Featured: r.FormValue("featured") == "on", } if err := validateProject(project); err != nil { s.redirectAdmin(w, r, "projects", err.Error()) return } id, err := s.store.CreateProject(r.Context(), project) if err != nil { s.redirectAdmin(w, r, "projects", "project could not be created") return } _ = s.store.AddProjectImage(r.Context(), id, cover, r.FormValue("title")) s.redirectAdmin(w, r, "projects", "project created") } func (s *Server) adminUpdateProject(w http.ResponseWriter, r *http.Request) { id, err := strconv.ParseInt(r.PathValue("id"), 10, 64) if err != nil { http.NotFound(w, r) return } if err := parseAdminForm(w, r, maxFormBytes); err != nil { s.redirectAdmin(w, r, "projects", "project form failed") return } cover := r.FormValue("cover_image_current") if path, ok, err := s.saveUpload(r, "cover_image"); err != nil { s.redirectAdmin(w, r, "projects", "cover upload "+err.Error()) return } else if ok { cover = path } slug := strings.TrimSpace(r.FormValue("slug")) if slug == "" { slug = store.SlugFromTitle(r.FormValue("title")) } else { slug = store.SlugFromTitle(slug) } project := store.Project{ ID: id, Slug: slug, Title: strings.TrimSpace(r.FormValue("title")), Location: strings.TrimSpace(r.FormValue("location")), Year: strings.TrimSpace(r.FormValue("year")), Category: strings.TrimSpace(r.FormValue("category")), Summary: strings.TrimSpace(r.FormValue("summary")), Scope: strings.TrimSpace(r.FormValue("scope")), Status: strings.TrimSpace(r.FormValue("status")), Position: formInt(r, "position"), Description: strings.TrimSpace(r.FormValue("description")), CoverImage: cover, Featured: r.FormValue("featured") == "on", } if err := validateProject(project); err != nil { s.redirectAdmin(w, r, "projects", err.Error()) return } err = s.store.UpdateProject(r.Context(), project) if err != nil { s.redirectAdmin(w, r, "projects", "project could not be saved") return } s.redirectAdmin(w, r, "projects", "project saved") } func (s *Server) adminDeleteProject(w http.ResponseWriter, r *http.Request) { id, err := strconv.ParseInt(r.PathValue("id"), 10, 64) if err == nil { err = s.store.DeleteProject(r.Context(), id) } if err != nil { s.redirectAdmin(w, r, "projects", "project could not be deleted") return } s.redirectAdmin(w, r, "projects", "project deleted") } func (s *Server) adminAddProjectImage(w http.ResponseWriter, r *http.Request) { projectID, err := strconv.ParseInt(r.PathValue("id"), 10, 64) if err != nil { http.NotFound(w, r) return } if err := parseAdminForm(w, r, maxFormBytes); err != nil { s.redirectAdmin(w, r, "projects", "image form failed") return } path, ok, err := s.saveUpload(r, "image") if err != nil || !ok { if err != nil { s.redirectAdmin(w, r, "projects", "image upload "+err.Error()) return } s.redirectAdmin(w, r, "projects", "image upload failed") return } if err := s.store.AddProjectImage(r.Context(), projectID, path, r.FormValue("caption")); err != nil { s.redirectAdmin(w, r, "projects", "image could not be added") return } s.redirectAdmin(w, r, "projects", "image added") } func (s *Server) adminDeleteProjectImage(w http.ResponseWriter, r *http.Request) { id, err := strconv.ParseInt(r.PathValue("id"), 10, 64) if err == nil { err = s.store.DeleteProjectImage(r.Context(), id) } if err != nil { s.redirectAdmin(w, r, "projects", "image could not be deleted") return } s.redirectAdmin(w, r, "projects", "image deleted") } func (s *Server) adminCreateService(w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { s.redirectAdmin(w, r, "services", "service form failed") return } service := serviceFromForm(r, 0) if err := validateService(service); err != nil { s.redirectAdmin(w, r, "services", err.Error()) return } if err := s.store.CreateService(r.Context(), service); err != nil { s.redirectAdmin(w, r, "services", "service could not be created") return } s.redirectAdmin(w, r, "services", "service created") } func (s *Server) adminUpdateService(w http.ResponseWriter, r *http.Request) { id, err := strconv.ParseInt(r.PathValue("id"), 10, 64) if err != nil { http.NotFound(w, r) return } if err := r.ParseForm(); err != nil { s.redirectAdmin(w, r, "services", "service form failed") return } service := serviceFromForm(r, id) if err := validateService(service); err != nil { s.redirectAdmin(w, r, "services", err.Error()) return } if err := s.store.UpdateService(r.Context(), service); err != nil { s.redirectAdmin(w, r, "services", "service could not be saved") return } s.redirectAdmin(w, r, "services", "service saved") } func (s *Server) adminDeleteService(w http.ResponseWriter, r *http.Request) { id, err := strconv.ParseInt(r.PathValue("id"), 10, 64) if err == nil { err = s.store.DeleteService(r.Context(), id) } if err != nil { s.redirectAdmin(w, r, "services", "service could not be deleted") return } s.redirectAdmin(w, r, "services", "service deleted") } func (s *Server) adminCreateFAQ(w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { s.redirectAdmin(w, r, "services", "FAQ form failed") return } faq := faqFromForm(r, 0) if err := validateFAQ(faq); err != nil { s.redirectAdmin(w, r, "services", err.Error()) return } if err := s.store.CreateFAQ(r.Context(), faq); err != nil { s.redirectAdmin(w, r, "services", "FAQ could not be created") return } s.redirectAdmin(w, r, "services", "FAQ created") } func (s *Server) adminUpdateFAQ(w http.ResponseWriter, r *http.Request) { id, err := strconv.ParseInt(r.PathValue("id"), 10, 64) if err != nil { http.NotFound(w, r) return } if err := r.ParseForm(); err != nil { s.redirectAdmin(w, r, "services", "FAQ form failed") return } faq := faqFromForm(r, id) if err := validateFAQ(faq); err != nil { s.redirectAdmin(w, r, "services", err.Error()) return } if err := s.store.UpdateFAQ(r.Context(), faq); err != nil { s.redirectAdmin(w, r, "services", "FAQ could not be saved") return } s.redirectAdmin(w, r, "services", "FAQ saved") } func (s *Server) adminDeleteFAQ(w http.ResponseWriter, r *http.Request) { id, err := strconv.ParseInt(r.PathValue("id"), 10, 64) if err == nil { err = s.store.DeleteFAQ(r.Context(), id) } if err != nil { s.redirectAdmin(w, r, "services", "FAQ could not be deleted") return } s.redirectAdmin(w, r, "services", "FAQ deleted") } func serviceFromForm(r *http.Request, id int64) store.Service { return store.Service{ ID: id, Title: strings.TrimSpace(r.FormValue("title")), Summary: strings.TrimSpace(r.FormValue("summary")), Details: strings.TrimSpace(r.FormValue("details")), Position: formInt(r, "position"), Active: r.FormValue("active") == "on", } } func faqFromForm(r *http.Request, id int64) store.FAQ { return store.FAQ{ ID: id, Question: strings.TrimSpace(r.FormValue("question")), Answer: strings.TrimSpace(r.FormValue("answer")), Position: formInt(r, "position"), Active: r.FormValue("active") == "on", } } func formInt(r *http.Request, name string) int { value, _ := strconv.Atoi(strings.TrimSpace(r.FormValue(name))) return value } func formValueOr(r *http.Request, name, fallback string) string { if _, ok := r.Form[name]; !ok { return fallback } return strings.TrimSpace(r.FormValue(name)) }