package handler import ( "encoding/json" "errors" "net/http" "github.com/go-chi/chi/v5" "github.com/prabhupadasays/spsays-bff/internal/repository" "github.com/prabhupadasays/spsays-bff/internal/service" "github.com/prabhupadasays/spsays-bff/pkg/response" ) // FeedbackCategoryHandler serves the /feedback form's categories: the // public list, and their management in the admin panel. type FeedbackCategoryHandler struct { svc *service.FeedbackCategoryService } func NewFeedbackCategoryHandler(svc *service.FeedbackCategoryService) *FeedbackCategoryHandler { return &FeedbackCategoryHandler{svc: svc} } func writeCategoryError(w http.ResponseWriter, err error) { switch { case errors.Is(err, repository.ErrFeedbackCategoryNotFound): response.Error(w, http.StatusNotFound, err.Error()) case errors.Is(err, repository.ErrFeedbackCategoryInUse), errors.Is(err, repository.ErrFeedbackCategoryExists), errors.Is(err, service.ErrCategoryLastActive): response.Error(w, http.StatusConflict, err.Error()) case errors.Is(err, service.ErrCategoryLabel), errors.Is(err, service.ErrCategoryDescription): response.Error(w, http.StatusBadRequest, err.Error()) default: response.Error(w, http.StatusInternalServerError, "feedback category request failed") } } // Public — GET /feedback/categories: the form's options, in order. func (h *FeedbackCategoryHandler) Public(w http.ResponseWriter, r *http.Request) { list, err := h.svc.Active(r.Context()) if err != nil { writeCategoryError(w, err) return } response.JSON(w, http.StatusOK, list) } // List — GET /admin/feedback/categories: all, with usage counts. func (h *FeedbackCategoryHandler) List(w http.ResponseWriter, r *http.Request) { list, err := h.svc.All(r.Context()) if err != nil { writeCategoryError(w, err) return } response.JSON(w, http.StatusOK, list) } type categoryReq struct { Label string `json:"label"` Description string `json:"description"` Archived bool `json:"archived"` } func (h *FeedbackCategoryHandler) Create(w http.ResponseWriter, r *http.Request) { var req categoryReq if err := json.NewDecoder(r.Body).Decode(&req); err != nil { response.Error(w, http.StatusBadRequest, "invalid request body") return } c, err := h.svc.Create(r.Context(), req.Label, req.Description) if err != nil { writeCategoryError(w, err) return } response.JSON(w, http.StatusCreated, c) } func (h *FeedbackCategoryHandler) Update(w http.ResponseWriter, r *http.Request) { var req categoryReq if err := json.NewDecoder(r.Body).Decode(&req); err != nil { response.Error(w, http.StatusBadRequest, "invalid request body") return } if err := h.svc.Update(r.Context(), chi.URLParam(r, "key"), req.Label, req.Description, req.Archived); err != nil { writeCategoryError(w, err) return } w.WriteHeader(http.StatusNoContent) } func (h *FeedbackCategoryHandler) Delete(w http.ResponseWriter, r *http.Request) { if err := h.svc.Delete(r.Context(), chi.URLParam(r, "key")); err != nil { writeCategoryError(w, err) return } w.WriteHeader(http.StatusNoContent) } // Reorder — PUT /admin/feedback/categories/order {"keys": [...]}. func (h *FeedbackCategoryHandler) Reorder(w http.ResponseWriter, r *http.Request) { var req struct { Keys []string `json:"keys"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil || len(req.Keys) == 0 { response.Error(w, http.StatusBadRequest, "keys are required") return } if err := h.svc.Reorder(r.Context(), req.Keys); err != nil { writeCategoryError(w, err) return } w.WriteHeader(http.StatusNoContent) }