b9f68b5dcb
renamed: "serv_nginx/api_bb/internal/handlers/training_plan_handler\321\216\320\277\321\211" -> serv_nginx/api_bb/internal/handlers/training_plan_handler.go modified: serv_nginx/api_bb/internal/handlers/user_achievement_handler.go modified: serv_nginx/api_bb/internal/routes/routes.go add routing, handlers for trainingPlan object
619 lines
21 KiB
Go
619 lines
21 KiB
Go
// handlers/user_achievement_handler.go
|
|
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"api_bb/internal/models"
|
|
"api_bb/internal/service"
|
|
"api_bb/pkg/logger"
|
|
"api_bb/pkg/middleware"
|
|
"api_bb/pkg/utils"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type UserAchievementHandler struct {
|
|
logger logger.LoggerInterface
|
|
achievementService service.AchievementService
|
|
}
|
|
|
|
func NewUserAchievementHandler(achievementService service.AchievementService) *UserAchievementHandler {
|
|
return &UserAchievementHandler{
|
|
logger: logger.NewWrapper(logger.Get().With(zap.String("handler", "user_achievement"))),
|
|
achievementService: achievementService,
|
|
}
|
|
}
|
|
|
|
// GetAchievementsByType возвращает достижения по типу
|
|
func (h *UserAchievementHandler) GetAchievementsByType(w http.ResponseWriter, r *http.Request) {
|
|
h.logger.Info("handling get achievements by type request",
|
|
zap.String("method", r.Method),
|
|
zap.String("path", r.URL.Path),
|
|
zap.String("remote_addr", r.RemoteAddr),
|
|
)
|
|
|
|
// Получаем пользователя из контекста
|
|
user, ok := middleware.GetUserFromContext(r.Context())
|
|
if !ok {
|
|
h.logger.Warn("get achievements by type failed - authentication required")
|
|
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
|
return
|
|
}
|
|
|
|
// Получаем тип из URL параметров
|
|
achievementType := chi.URLParam(r, "type")
|
|
if achievementType == "" {
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Achievement type is required")
|
|
return
|
|
}
|
|
|
|
// Валидируем тип достижения
|
|
validType := models.AchievementType(achievementType)
|
|
switch validType {
|
|
case models.AchievementTypeDistance, models.AchievementTypeSpeed,
|
|
models.AchievementTypeConsistency, models.AchievementTypeEvent,
|
|
models.AchievementTypeSpecial:
|
|
// valid type
|
|
default:
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Invalid achievement type")
|
|
return
|
|
}
|
|
|
|
achievements, err := h.achievementService.GetAchievementsByType(user.ID, validType)
|
|
if err != nil {
|
|
h.logger.Error("failed to get achievements by type",
|
|
zap.Uint("user_id", user.ID),
|
|
zap.String("type", achievementType),
|
|
zap.Error(err),
|
|
)
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get achievements: "+err.Error())
|
|
return
|
|
}
|
|
|
|
h.logger.Info("achievements by type retrieved successfully",
|
|
zap.Uint("user_id", user.ID),
|
|
zap.String("type", achievementType),
|
|
zap.Int("achievements_count", len(achievements)),
|
|
)
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, achievements)
|
|
}
|
|
|
|
// GetAchievementByID возвращает достижение по ID
|
|
func (h *UserAchievementHandler) GetAchievementByID(w http.ResponseWriter, r *http.Request) {
|
|
h.logger.Info("handling get achievement by ID request",
|
|
zap.String("method", r.Method),
|
|
zap.String("path", r.URL.Path),
|
|
zap.String("remote_addr", r.RemoteAddr),
|
|
)
|
|
|
|
// Получаем пользователя из контекста
|
|
user, ok := middleware.GetUserFromContext(r.Context())
|
|
if !ok {
|
|
h.logger.Warn("get achievement by ID failed - authentication required")
|
|
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
|
return
|
|
}
|
|
|
|
// Получаем ID достижения из URL параметров
|
|
achievementIDStr := chi.URLParam(r, "id")
|
|
if achievementIDStr == "" {
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Achievement ID is required")
|
|
return
|
|
}
|
|
|
|
achievementID, err := strconv.ParseUint(achievementIDStr, 10, 32)
|
|
if err != nil {
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Invalid achievement ID")
|
|
return
|
|
}
|
|
|
|
achievement, err := h.achievementService.GetAchievementByID(uint(achievementID), user.ID)
|
|
if err != nil {
|
|
h.logger.Error("failed to get achievement by ID",
|
|
zap.Uint("user_id", user.ID),
|
|
zap.Uint("achievement_id", uint(achievementID)),
|
|
zap.Error(err),
|
|
)
|
|
if err == service.ErrAchievementNotFound {
|
|
utils.RespondWithError(w, http.StatusNotFound, "Achievement not found")
|
|
} else {
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get achievement: "+err.Error())
|
|
}
|
|
return
|
|
}
|
|
|
|
h.logger.Info("achievement retrieved successfully",
|
|
zap.Uint("user_id", user.ID),
|
|
zap.Uint("achievement_id", uint(achievementID)),
|
|
)
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, achievement)
|
|
}
|
|
|
|
// UpdateAchievement обновляет достижение
|
|
func (h *UserAchievementHandler) UpdateAchievement(w http.ResponseWriter, r *http.Request) {
|
|
h.logger.Info("handling update achievement request",
|
|
zap.String("method", r.Method),
|
|
zap.String("path", r.URL.Path),
|
|
zap.String("remote_addr", r.RemoteAddr),
|
|
)
|
|
|
|
// Получаем пользователя из контекста
|
|
user, ok := middleware.GetUserFromContext(r.Context())
|
|
if !ok {
|
|
h.logger.Warn("update achievement failed - authentication required")
|
|
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
|
return
|
|
}
|
|
|
|
// Получаем ID достижения из URL параметров
|
|
achievementIDStr := chi.URLParam(r, "id")
|
|
if achievementIDStr == "" {
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Achievement ID is required")
|
|
return
|
|
}
|
|
|
|
achievementID, err := strconv.ParseUint(achievementIDStr, 10, 32)
|
|
if err != nil {
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Invalid achievement ID")
|
|
return
|
|
}
|
|
|
|
var req models.AchievementCreateRequest
|
|
if err := utils.DecodeJSONBody(w, r, &req); err != nil {
|
|
h.logger.Error("failed to decode achievement update request", zap.Error(err))
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Invalid request payload: "+err.Error())
|
|
return
|
|
}
|
|
|
|
// Валидация запроса
|
|
if err := utils.ValidateStruct(req); err != nil {
|
|
h.logger.Warn("achievement update validation failed", zap.Error(err))
|
|
utils.RespondWithValidationError(w, err)
|
|
return
|
|
}
|
|
|
|
// Обновляем достижение через сервис
|
|
achievement, err := h.achievementService.UpdateAchievement(uint(achievementID), user.ID, req)
|
|
if err != nil {
|
|
h.logger.Error("failed to update achievement",
|
|
zap.Uint("user_id", user.ID),
|
|
zap.Uint("achievement_id", uint(achievementID)),
|
|
zap.Error(err),
|
|
)
|
|
switch err {
|
|
case service.ErrAchievementNotFound:
|
|
utils.RespondWithError(w, http.StatusNotFound, "Achievement not found")
|
|
case service.ErrAchievementAlreadyExists:
|
|
utils.RespondWithError(w, http.StatusConflict, "Achievement with this title already exists")
|
|
default:
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to update achievement: "+err.Error())
|
|
}
|
|
return
|
|
}
|
|
|
|
h.logger.Info("achievement updated successfully",
|
|
zap.Uint("user_id", user.ID),
|
|
zap.Uint("achievement_id", uint(achievementID)),
|
|
)
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, map[string]interface{}{
|
|
"message": "Achievement updated successfully",
|
|
"achievement": achievement,
|
|
})
|
|
}
|
|
|
|
// GetPublicUserAchievements возвращает достижения пользователя для публичного просмотра
|
|
func (h *UserAchievementHandler) GetPublicUserAchievements(w http.ResponseWriter, r *http.Request) {
|
|
h.logger.Info("handling get public user achievements request",
|
|
zap.String("method", r.Method),
|
|
zap.String("path", r.URL.Path),
|
|
zap.String("remote_addr", r.RemoteAddr),
|
|
)
|
|
|
|
// Получаем userID из URL параметров
|
|
userIDStr := r.URL.Query().Get("userID")
|
|
if userIDStr == "" {
|
|
utils.RespondWithError(w, http.StatusBadRequest, "User ID is required")
|
|
return
|
|
}
|
|
|
|
userID, err := strconv.ParseUint(userIDStr, 10, 32)
|
|
if err != nil {
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Invalid user ID")
|
|
return
|
|
}
|
|
|
|
// Получаем только подтвержденные достижения для публичного просмотра
|
|
achievements, err := h.achievementService.GetVerifiedAchievements(uint(userID))
|
|
if err != nil {
|
|
h.logger.Error("failed to get public user achievements",
|
|
zap.Uint("user_id", uint(userID)),
|
|
zap.Error(err),
|
|
)
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get achievements: "+err.Error())
|
|
return
|
|
}
|
|
|
|
h.logger.Info("public user achievements retrieved successfully",
|
|
zap.Uint("user_id", uint(userID)),
|
|
zap.Int("achievements_count", len(achievements)),
|
|
)
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, achievements)
|
|
}
|
|
|
|
// GetPublicUserAchievementsSummary возвращает сводку по достижениям пользователя для публичного просмотра
|
|
func (h *UserAchievementHandler) GetPublicUserAchievementsSummary(w http.ResponseWriter, r *http.Request) {
|
|
h.logger.Info("handling get public user achievements summary request",
|
|
zap.String("method", r.Method),
|
|
zap.String("path", r.URL.Path),
|
|
zap.String("remote_addr", r.RemoteAddr),
|
|
)
|
|
|
|
// Получаем userID из URL параметров
|
|
userIDStr := r.URL.Query().Get("userID")
|
|
if userIDStr == "" {
|
|
utils.RespondWithError(w, http.StatusBadRequest, "User ID is required")
|
|
return
|
|
}
|
|
|
|
userID, err := strconv.ParseUint(userIDStr, 10, 32)
|
|
if err != nil {
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Invalid user ID")
|
|
return
|
|
}
|
|
|
|
summary, err := h.achievementService.GetUserAchievementsSummary(uint(userID))
|
|
if err != nil {
|
|
h.logger.Error("failed to get public user achievements summary",
|
|
zap.Uint("user_id", uint(userID)),
|
|
zap.Error(err),
|
|
)
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get achievements summary: "+err.Error())
|
|
return
|
|
}
|
|
|
|
h.logger.Info("public user achievements summary retrieved successfully",
|
|
zap.Uint("user_id", uint(userID)),
|
|
zap.Int("total_achievements", summary.TotalAchievements),
|
|
zap.Int("completed", summary.Completed),
|
|
)
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, summary)
|
|
}
|
|
|
|
// GetPublicRecentAchievements возвращает последние достижения пользователя для публичного просмотра
|
|
func (h *UserAchievementHandler) GetPublicRecentAchievements(w http.ResponseWriter, r *http.Request) {
|
|
h.logger.Info("handling get public recent achievements request",
|
|
zap.String("method", r.Method),
|
|
zap.String("path", r.URL.Path),
|
|
zap.String("remote_addr", r.RemoteAddr),
|
|
)
|
|
|
|
// Получаем userID из URL параметров
|
|
userIDStr := r.URL.Query().Get("userID")
|
|
if userIDStr == "" {
|
|
utils.RespondWithError(w, http.StatusBadRequest, "User ID is required")
|
|
return
|
|
}
|
|
|
|
userID, err := strconv.ParseUint(userIDStr, 10, 32)
|
|
if err != nil {
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Invalid user ID")
|
|
return
|
|
}
|
|
|
|
// Получаем параметр limit из query string (по умолчанию 10)
|
|
limit := 10
|
|
limitStr := r.URL.Query().Get("limit")
|
|
if limitStr != "" {
|
|
if parsedLimit, err := strconv.Atoi(limitStr); err == nil && parsedLimit > 0 {
|
|
limit = parsedLimit
|
|
}
|
|
}
|
|
|
|
// Получаем только подтвержденные достижения
|
|
achievements, err := h.achievementService.GetVerifiedRecentAchievements(uint(userID), limit)
|
|
if err != nil {
|
|
h.logger.Error("failed to get public recent achievements",
|
|
zap.Uint("user_id", uint(userID)),
|
|
zap.Int("limit", limit),
|
|
zap.Error(err),
|
|
)
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get recent achievements: "+err.Error())
|
|
return
|
|
}
|
|
|
|
h.logger.Info("public recent achievements retrieved successfully",
|
|
zap.Uint("user_id", uint(userID)),
|
|
zap.Int("achievements_count", len(achievements)),
|
|
)
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, achievements)
|
|
}
|
|
|
|
// CreateAchievement создает новое достижение для пользователя
|
|
func (h *UserAchievementHandler) CreateAchievement(w http.ResponseWriter, r *http.Request) {
|
|
h.logger.Info("handling create achievement request",
|
|
zap.String("method", r.Method),
|
|
zap.String("path", r.URL.Path),
|
|
zap.String("remote_addr", r.RemoteAddr),
|
|
)
|
|
|
|
// Получаем пользователя из контекста
|
|
user, ok := middleware.GetUserFromContext(r.Context())
|
|
if !ok {
|
|
h.logger.Warn("create achievement failed - authentication required")
|
|
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
|
return
|
|
}
|
|
|
|
var req models.AchievementCreateRequest
|
|
if err := utils.DecodeJSONBody(w, r, &req); err != nil {
|
|
h.logger.Error("failed to decode achievement request", zap.Error(err))
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Invalid request payload: "+err.Error())
|
|
return
|
|
}
|
|
|
|
// Валидация запроса
|
|
if err := utils.ValidateStruct(req); err != nil {
|
|
h.logger.Warn("achievement validation failed", zap.Error(err))
|
|
utils.RespondWithValidationError(w, err)
|
|
return
|
|
}
|
|
|
|
// Создаем достижение через сервис
|
|
achievement, err := h.achievementService.CreateAchievement(user.ID, req)
|
|
if err != nil {
|
|
h.logger.Error("failed to create achievement",
|
|
zap.Uint("user_id", user.ID),
|
|
zap.Error(err),
|
|
)
|
|
if err == service.ErrAchievementAlreadyExists {
|
|
utils.RespondWithError(w, http.StatusConflict, "Achievement with this title already exists")
|
|
} else {
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to create achievement: "+err.Error())
|
|
}
|
|
return
|
|
}
|
|
|
|
h.logger.Info("achievement created successfully",
|
|
zap.Uint("user_id", user.ID),
|
|
zap.Uint("achievement_id", achievement.ID),
|
|
zap.String("title", achievement.Title),
|
|
)
|
|
|
|
utils.RespondWithJSON(w, http.StatusCreated, map[string]interface{}{
|
|
"message": "Achievement created successfully",
|
|
"achievement": achievement,
|
|
})
|
|
}
|
|
|
|
// GetUserAchievements возвращает все достижения пользователя
|
|
func (h *UserAchievementHandler) GetUserAchievements(w http.ResponseWriter, r *http.Request) {
|
|
h.logger.Info("handling get user achievements request",
|
|
zap.String("method", r.Method),
|
|
zap.String("path", r.URL.Path),
|
|
zap.String("remote_addr", r.RemoteAddr),
|
|
)
|
|
|
|
// Получаем пользователя из контекста
|
|
user, ok := middleware.GetUserFromContext(r.Context())
|
|
if !ok {
|
|
h.logger.Warn("get achievements failed - authentication required")
|
|
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
|
return
|
|
}
|
|
|
|
achievements, err := h.achievementService.GetUserAchievements(user.ID)
|
|
if err != nil {
|
|
h.logger.Error("failed to get user achievements",
|
|
zap.Uint("user_id", user.ID),
|
|
zap.Error(err),
|
|
)
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get achievements: "+err.Error())
|
|
return
|
|
}
|
|
|
|
h.logger.Info("user achievements retrieved successfully",
|
|
zap.Uint("user_id", user.ID),
|
|
zap.Int("achievements_count", len(achievements)),
|
|
)
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, achievements)
|
|
}
|
|
|
|
// GetUserAchievementsSummary возвращает сводку по достижениям пользователя
|
|
func (h *UserAchievementHandler) GetUserAchievementsSummary(w http.ResponseWriter, r *http.Request) {
|
|
h.logger.Info("handling get user achievements summary request",
|
|
zap.String("method", r.Method),
|
|
zap.String("path", r.URL.Path),
|
|
zap.String("remote_addr", r.RemoteAddr),
|
|
)
|
|
|
|
// Получаем пользователя из контекста
|
|
user, ok := middleware.GetUserFromContext(r.Context())
|
|
if !ok {
|
|
h.logger.Warn("get achievements summary failed - authentication required")
|
|
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
|
return
|
|
}
|
|
|
|
summary, err := h.achievementService.GetUserAchievementsSummary(user.ID)
|
|
if err != nil {
|
|
h.logger.Error("failed to get user achievements summary",
|
|
zap.Uint("user_id", user.ID),
|
|
zap.Error(err),
|
|
)
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get achievements summary: "+err.Error())
|
|
return
|
|
}
|
|
|
|
h.logger.Info("user achievements summary retrieved successfully",
|
|
zap.Uint("user_id", user.ID),
|
|
zap.Int("total_achievements", summary.TotalAchievements),
|
|
zap.Int("completed", summary.Completed),
|
|
zap.Float64("progress_percent", summary.ProgressPercent),
|
|
)
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, summary)
|
|
}
|
|
|
|
// GetRecentAchievements возвращает последние достижения пользователя
|
|
func (h *UserAchievementHandler) GetRecentAchievements(w http.ResponseWriter, r *http.Request) {
|
|
h.logger.Info("handling get recent achievements request",
|
|
zap.String("method", r.Method),
|
|
zap.String("path", r.URL.Path),
|
|
zap.String("remote_addr", r.RemoteAddr),
|
|
)
|
|
|
|
// Получаем пользователя из контекста
|
|
user, ok := middleware.GetUserFromContext(r.Context())
|
|
if !ok {
|
|
h.logger.Warn("get recent achievements failed - authentication required")
|
|
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
|
return
|
|
}
|
|
|
|
// Получаем параметр limit из query string (по умолчанию 10)
|
|
limit := 10
|
|
limitStr := r.URL.Query().Get("limit")
|
|
if limitStr != "" {
|
|
if parsedLimit, err := strconv.Atoi(limitStr); err == nil && parsedLimit > 0 {
|
|
limit = parsedLimit
|
|
}
|
|
}
|
|
|
|
achievements, err := h.achievementService.GetRecentAchievements(user.ID, limit)
|
|
if err != nil {
|
|
h.logger.Error("failed to get recent achievements",
|
|
zap.Uint("user_id", user.ID),
|
|
zap.Int("limit", limit),
|
|
zap.Error(err),
|
|
)
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get recent achievements: "+err.Error())
|
|
return
|
|
}
|
|
|
|
h.logger.Info("recent achievements retrieved successfully",
|
|
zap.Uint("user_id", user.ID),
|
|
zap.Int("achievements_count", len(achievements)),
|
|
zap.Int("limit", limit),
|
|
)
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, achievements)
|
|
}
|
|
|
|
// VerifyAchievement подтверждает достижение пользователя
|
|
func (h *UserAchievementHandler) VerifyAchievement(w http.ResponseWriter, r *http.Request) {
|
|
h.logger.Info("handling verify achievement request",
|
|
zap.String("method", r.Method),
|
|
zap.String("path", r.URL.Path),
|
|
zap.String("remote_addr", r.RemoteAddr),
|
|
)
|
|
|
|
// Получаем пользователя из контекста
|
|
user, ok := middleware.GetUserFromContext(r.Context())
|
|
if !ok {
|
|
h.logger.Warn("verify achievement failed - authentication required")
|
|
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
|
return
|
|
}
|
|
|
|
// Получаем ID достижения из URL параметров
|
|
achievementIDStr := r.URL.Query().Get("id")
|
|
if achievementIDStr == "" {
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Achievement ID is required")
|
|
return
|
|
}
|
|
|
|
achievementID, err := strconv.ParseUint(achievementIDStr, 10, 32)
|
|
if err != nil {
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Invalid achievement ID")
|
|
return
|
|
}
|
|
|
|
err = h.achievementService.VerifyAchievement(uint(achievementID), user.ID)
|
|
if err != nil {
|
|
h.logger.Error("failed to verify achievement",
|
|
zap.Uint("user_id", user.ID),
|
|
zap.Uint("achievement_id", uint(achievementID)),
|
|
zap.Error(err),
|
|
)
|
|
if err == service.ErrAchievementNotFound {
|
|
utils.RespondWithError(w, http.StatusNotFound, "Achievement not found")
|
|
} else {
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to verify achievement: "+err.Error())
|
|
}
|
|
return
|
|
}
|
|
|
|
h.logger.Info("achievement verified successfully",
|
|
zap.Uint("user_id", user.ID),
|
|
zap.Uint("achievement_id", uint(achievementID)),
|
|
)
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, map[string]string{
|
|
"message": "Achievement verified successfully",
|
|
})
|
|
}
|
|
|
|
// DeleteAchievement удаляет достижение пользователя
|
|
func (h *UserAchievementHandler) DeleteAchievement(w http.ResponseWriter, r *http.Request) {
|
|
h.logger.Info("handling delete achievement request",
|
|
zap.String("method", r.Method),
|
|
zap.String("path", r.URL.Path),
|
|
zap.String("remote_addr", r.RemoteAddr),
|
|
)
|
|
|
|
// Получаем пользователя из контекста
|
|
user, ok := middleware.GetUserFromContext(r.Context())
|
|
if !ok {
|
|
h.logger.Warn("delete achievement failed - authentication required")
|
|
utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
|
|
return
|
|
}
|
|
|
|
// Получаем ID достижения из URL параметров
|
|
achievementIDStr := r.URL.Query().Get("id")
|
|
if achievementIDStr == "" {
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Achievement ID is required")
|
|
return
|
|
}
|
|
|
|
achievementID, err := strconv.ParseUint(achievementIDStr, 10, 32)
|
|
if err != nil {
|
|
utils.RespondWithError(w, http.StatusBadRequest, "Invalid achievement ID")
|
|
return
|
|
}
|
|
|
|
err = h.achievementService.DeleteAchievement(uint(achievementID), user.ID)
|
|
if err != nil {
|
|
h.logger.Error("failed to delete achievement",
|
|
zap.Uint("user_id", user.ID),
|
|
zap.Uint("achievement_id", uint(achievementID)),
|
|
zap.Error(err),
|
|
)
|
|
if err == service.ErrAchievementNotFound {
|
|
utils.RespondWithError(w, http.StatusNotFound, "Achievement not found")
|
|
} else {
|
|
utils.RespondWithError(w, http.StatusInternalServerError, "Failed to delete achievement: "+err.Error())
|
|
}
|
|
return
|
|
}
|
|
|
|
h.logger.Info("achievement deleted successfully",
|
|
zap.Uint("user_id", user.ID),
|
|
zap.Uint("achievement_id", uint(achievementID)),
|
|
)
|
|
|
|
utils.RespondWithJSON(w, http.StatusOK, map[string]string{
|
|
"message": "Achievement deleted successfully",
|
|
})
|
|
}
|