package httpapi import ( "net/http" "github.com/descrybe/descrybe-v2/apps/api/internal/company" ) type brandPutBody struct { VoiceTone *string `json:"voice_tone"` Dos []string `json:"dos"` Donts []string `json:"donts"` PrimaryColor *string `json:"primary_color"` SecondaryColor *string `json:"secondary_color"` LogoURL *string `json:"logo_url"` PreferredTerms []string `json:"preferred_terms"` // Optional nested colors alias Colors *struct { Primary *string `json:"primary"` Secondary *string `json:"secondary"` } `json:"colors"` } func (s *Server) brandResponse(w http.ResponseWriter, r *http.Request, brand company.BrandKit) { cid, _ := CompanyIDFromContext(r.Context()) aiApply := false if s.Billing != nil { aiApply = s.Billing.AIBrandApplyAllowed(r.Context(), cid) } JSON(w, http.StatusOK, map[string]any{ "brand": brand, "ai_apply_allowed": aiApply, "tips": brand.FormulaTips(), }) } func (s *Server) handleGetBrand(w http.ResponseWriter, r *http.Request) { cid, _ := CompanyIDFromContext(r.Context()) brand, err := company.LoadBrand(r.Context(), s.Pool, cid) if err != nil { Error(w, http.StatusInternalServerError, "load brand failed") return } s.brandResponse(w, r, brand) } func (s *Server) handlePutBrand(w http.ResponseWriter, r *http.Request) { cid, _ := CompanyIDFromContext(r.Context()) role, _ := RoleFromContext(r.Context()) if role != "admin" { Error(w, http.StatusForbidden, "admin required") return } var body brandPutBody if err := DecodeJSON(r, &body); err != nil { Error(w, http.StatusBadRequest, "invalid json") return } current, err := company.LoadBrand(r.Context(), s.Pool, cid) if err != nil { Error(w, http.StatusInternalServerError, "load brand failed") return } if body.VoiceTone != nil { current.VoiceTone = *body.VoiceTone } if body.Dos != nil { current.Dos = body.Dos } if body.Donts != nil { current.Donts = body.Donts } if body.PrimaryColor != nil { current.PrimaryColor = *body.PrimaryColor } if body.SecondaryColor != nil { current.SecondaryColor = *body.SecondaryColor } if body.LogoURL != nil { current.LogoURL = *body.LogoURL } if body.PreferredTerms != nil { current.PreferredTerms = body.PreferredTerms } if body.Colors != nil { if body.Colors.Primary != nil { current.PrimaryColor = *body.Colors.Primary } if body.Colors.Secondary != nil { current.SecondaryColor = *body.Colors.Secondary } } saved, err := company.UpsertBrand(r.Context(), s.Pool, cid, current) if err != nil { if isBrandLogoURLError(err) { Error(w, http.StatusBadRequest, "invalid logo_url") return } Error(w, http.StatusInternalServerError, "save brand failed") return } s.brandResponse(w, r, saved) }