108 lines
2.7 KiB
Go
108 lines
2.7 KiB
Go
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)
|
||
|
|
}
|