6d8e179f90
modified: serv_nginx/api_bb/internal/handlers/handlers.go new file: serv_nginx/api_bb/internal/handlers/review_handler.go new file: serv_nginx/api_bb/internal/models/review.go new file: serv_nginx/api_bb/internal/repository/review_repository.go modified: serv_nginx/api_bb/internal/routes/routes.go new file: serv_nginx/api_bb/internal/service/review_service.go set reviews router, handler, service, repository
218 lines
6.5 KiB
Go
218 lines
6.5 KiB
Go
// handlers/review_handler.go
|
|
package handlers
|
|
|
|
import (
|
|
"api_bb/internal/models"
|
|
"api_bb/internal/service"
|
|
"api_bb/pkg/logger"
|
|
"api_bb/pkg/utils"
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type ReviewHandler struct {
|
|
reviewService service.ReviewService
|
|
logger logger.LoggerInterface
|
|
}
|
|
|
|
func NewReviewHandler(reviewService service.ReviewService, logger logger.LoggerInterface) *ReviewHandler {
|
|
return &ReviewHandler{
|
|
reviewService: reviewService,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
func (h *ReviewHandler) Routes() chi.Router {
|
|
r := chi.NewRouter()
|
|
|
|
r.Get("/", h.GetReviews)
|
|
r.Get("/stats", h.GetReviewsStats)
|
|
r.Get("/my", h.GetMyReviews)
|
|
r.Post("/", h.CreateReview)
|
|
|
|
r.Route("/{id}", func(r chi.Router) {
|
|
r.Get("/", h.GetReviewByID)
|
|
r.Put("/", h.UpdateReview)
|
|
r.Delete("/", h.DeleteReview)
|
|
})
|
|
|
|
return r
|
|
}
|
|
|
|
// GetReviews возвращает список отзывов с пагинацией и фильтрацией
|
|
func (h *ReviewHandler) GetReviews(w http.ResponseWriter, r *http.Request) {
|
|
page, _ := strconv.Atoi(r.URL.Query().Get("page"))
|
|
limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
|
|
sortBy := r.URL.Query().Get("sort")
|
|
filter := r.URL.Query().Get("filter")
|
|
|
|
if page < 1 {
|
|
page = 1
|
|
}
|
|
if limit < 1 {
|
|
limit = 6
|
|
}
|
|
|
|
reviews, totalPages, err := h.reviewService.GetAllReviews(page, limit, sortBy, filter)
|
|
if err != nil {
|
|
h.logger.Error("Failed to get reviews", zap.Error(err))
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get reviews")
|
|
return
|
|
}
|
|
|
|
response := map[string]interface{}{
|
|
"reviews": reviews,
|
|
"current_page": page,
|
|
"total_pages": totalPages,
|
|
"total_items": len(reviews),
|
|
}
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, response)
|
|
}
|
|
|
|
// GetReviewsStats возвращает статистику отзывов
|
|
func (h *ReviewHandler) GetReviewsStats(w http.ResponseWriter, r *http.Request) {
|
|
stats, err := h.reviewService.GetReviewsStats()
|
|
if err != nil {
|
|
h.logger.Error("Failed to get reviews stats", zap.Error(err))
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get reviews statistics")
|
|
return
|
|
}
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, stats)
|
|
}
|
|
|
|
// GetMyReviews возвращает отзывы текущего пользователя
|
|
func (h *ReviewHandler) GetMyReviews(w http.ResponseWriter, r *http.Request) {
|
|
userID, ok := r.Context().Value("userID").(uint)
|
|
if !ok {
|
|
utils.RespondWithError(w, http.StatusUnauthorized, "User not authenticated")
|
|
return
|
|
}
|
|
|
|
reviews, err := h.reviewService.GetUserReviews(userID)
|
|
if err != nil {
|
|
h.logger.With(zap.String("userID", string(userID))).Error("Failed to get user reviews", zap.Error(err))
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get your reviews")
|
|
return
|
|
}
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, reviews)
|
|
}
|
|
|
|
// CreateReview создает новый отзыв
|
|
func (h *ReviewHandler) CreateReview(w http.ResponseWriter, r *http.Request) {
|
|
userID, ok := r.Context().Value("userID").(uint)
|
|
if !ok {
|
|
utils.RespondWithError(w, http.StatusUnauthorized, "User not authenticated")
|
|
return
|
|
}
|
|
|
|
var req models.CreateReviewRequest
|
|
if err := utils.DecodeJSONBody(w, r, &req); err != nil {
|
|
h.logger.Error("Failed to decode review request", zap.Error(err))
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Invalid request body")
|
|
return
|
|
}
|
|
|
|
review, err := h.reviewService.CreateReview(&req, userID)
|
|
if err != nil {
|
|
h.logger.With(zap.String("userID", string(userID))).Error("Failed to create review", zap.Error(err))
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to create review")
|
|
return
|
|
}
|
|
|
|
utils.RespondWithJSON(w, http.StatusCreated, review)
|
|
}
|
|
|
|
// GetReviewByID возвращает отзыв по ID
|
|
func (h *ReviewHandler) GetReviewByID(w http.ResponseWriter, r *http.Request) {
|
|
idStr := chi.URLParam(r, "id")
|
|
id, err := strconv.ParseUint(idStr, 10, 32)
|
|
if err != nil {
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Invalid review ID")
|
|
return
|
|
}
|
|
|
|
review, err := h.reviewService.GetReviewByID(uint(id))
|
|
if err != nil {
|
|
h.logger.With(zap.String("id", string(id))).Error("Failed to get review", zap.Error(err))
|
|
utils.RespondWithError(w, http.StatusNotFound, "Review not found")
|
|
return
|
|
}
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, review)
|
|
}
|
|
|
|
// UpdateReview обновляет отзыв
|
|
func (h *ReviewHandler) UpdateReview(w http.ResponseWriter, r *http.Request) {
|
|
userID, ok := r.Context().Value("userID").(uint)
|
|
if !ok {
|
|
utils.RespondWithError(w, http.StatusUnauthorized, "User not authenticated")
|
|
return
|
|
}
|
|
|
|
isAdmin, _ := r.Context().Value("isAdmin").(bool)
|
|
|
|
idStr := chi.URLParam(r, "id")
|
|
id, err := strconv.ParseUint(idStr, 10, 32)
|
|
if err != nil {
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Invalid review ID")
|
|
return
|
|
}
|
|
|
|
var req models.UpdateReviewRequest
|
|
if err := utils.DecodeJSONBody(w, r, &req); err != nil {
|
|
h.logger.Error("Failed to decode update review request", zap.Error(err))
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Invalid request body")
|
|
return
|
|
}
|
|
|
|
review, err := h.reviewService.UpdateReview(uint(id), &req, userID, isAdmin)
|
|
if err != nil {
|
|
h.logger.With(zap.Int("id", int(id))).With(zap.Int("userID", int(userID))).Error("Failed to update review", zap.Error(err))
|
|
if err.Error() == "unauthorized" {
|
|
utils.RespondWithError(w, http.StatusForbidden, "You can only update your own reviews")
|
|
return
|
|
}
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to update review")
|
|
return
|
|
}
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, review)
|
|
}
|
|
|
|
// DeleteReview удаляет отзыв
|
|
func (h *ReviewHandler) DeleteReview(w http.ResponseWriter, r *http.Request) {
|
|
userID, ok := r.Context().Value("userID").(uint)
|
|
if !ok {
|
|
utils.RespondWithError(w, http.StatusUnauthorized, "User not authenticated")
|
|
return
|
|
}
|
|
|
|
isAdmin, _ := r.Context().Value("isAdmin").(bool)
|
|
|
|
idStr := chi.URLParam(r, "id")
|
|
id, err := strconv.ParseUint(idStr, 10, 32)
|
|
if err != nil {
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Invalid review ID")
|
|
return
|
|
}
|
|
|
|
err = h.reviewService.DeleteReview(uint(id), userID, isAdmin)
|
|
if err != nil {
|
|
h.logger.With(zap.Int("id", int(id))).With(zap.Int("userID", int(userID))).Error("Failed to delete review", zap.Error(err))
|
|
if err.Error() == "unauthorized" {
|
|
utils.RespondWithError(w, http.StatusForbidden, "You can only delete your own reviews")
|
|
return
|
|
}
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to delete review")
|
|
return
|
|
}
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, map[string]string{"message": "Review deleted successfully"})
|
|
}
|