Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user