package announcement import ( "log" "strconv" "strings" "github.com/gofiber/fiber/v2" ) type Handler struct { svc *Service } func NewHandler(svc *Service) *Handler { return &Handler{svc: svc} } // GetAll godoc // @Summary 공지사항 목록 조회 // @Description 공지사항 목록을 조회합니다 // @Tags Announcements // @Produce json // @Param offset query int false "시작 위치" default(0) // @Param limit query int false "조회 수" default(20) // @Success 200 {array} docs.AnnouncementResponse // @Failure 500 {object} docs.ErrorResponse // @Router /api/announcements/ [get] func (h *Handler) GetAll(c *fiber.Ctx) error { offset := c.QueryInt("offset", 0) limit := c.QueryInt("limit", 20) if limit <= 0 || limit > 100 { limit = 20 } if offset < 0 { offset = 0 } list, err := h.svc.GetAll(offset, limit) if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "공지사항을 불러오지 못했습니다"}) } return c.JSON(list) } // Create godoc // @Summary 공지사항 생성 (관리자) // @Description 새 공지사항을 생성합니다 // @Tags Announcements // @Accept json // @Produce json // @Security BearerAuth // @Param body body docs.CreateAnnouncementRequest true "공지사항 내용" // @Success 201 {object} docs.AnnouncementResponse // @Failure 400 {object} docs.ErrorResponse // @Failure 401 {object} docs.ErrorResponse // @Failure 403 {object} docs.ErrorResponse // @Failure 500 {object} docs.ErrorResponse // @Router /api/announcements/ [post] func (h *Handler) Create(c *fiber.Ctx) error { var body struct { Title string `json:"title"` Content string `json:"content"` } if err := c.BodyParser(&body); err != nil || body.Title == "" || body.Content == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "제목과 내용을 입력해주세요"}) } if len(body.Title) > 256 { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "제목은 256자 이하여야 합니다"}) } if len(body.Content) > 10000 { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "내용은 10000자 이하여야 합니다"}) } a, err := h.svc.Create(body.Title, body.Content) if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "공지사항 생성에 실패했습니다"}) } return c.Status(fiber.StatusCreated).JSON(a) } // Update godoc // @Summary 공지사항 수정 (관리자) // @Description 공지사항을 수정합니다 // @Tags Announcements // @Accept json // @Produce json // @Security BearerAuth // @Param id path int true "공지사항 ID" // @Param body body docs.UpdateAnnouncementRequest true "수정할 내용" // @Success 200 {object} docs.AnnouncementResponse // @Failure 400 {object} docs.ErrorResponse // @Failure 401 {object} docs.ErrorResponse // @Failure 403 {object} docs.ErrorResponse // @Failure 404 {object} docs.ErrorResponse // @Failure 500 {object} docs.ErrorResponse // @Router /api/announcements/{id} [put] func (h *Handler) Update(c *fiber.Ctx) error { id, err := strconv.ParseUint(c.Params("id"), 10, 64) if err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "유효하지 않은 공지사항 ID입니다"}) } var body struct { Title string `json:"title"` Content string `json:"content"` } if err := c.BodyParser(&body); err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "잘못된 요청입니다"}) } if body.Title == "" && body.Content == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "수정할 내용을 입력해주세요"}) } if len(body.Title) > 256 { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "제목은 256자 이하여야 합니다"}) } if len(body.Content) > 10000 { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "내용은 10000자 이하여야 합니다"}) } a, err := h.svc.Update(uint(id), body.Title, body.Content) if err != nil { if strings.Contains(err.Error(), "찾을 수 없습니다") { return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": err.Error()}) } log.Printf("공지사항 수정 실패 (id=%d): %v", id, err) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "서버 오류가 발생했습니다"}) } return c.JSON(a) } // Delete godoc // @Summary 공지사항 삭제 (관리자) // @Description 공지사항을 삭제합니다 // @Tags Announcements // @Security BearerAuth // @Param id path int true "공지사항 ID" // @Success 204 // @Failure 400 {object} docs.ErrorResponse // @Failure 401 {object} docs.ErrorResponse // @Failure 403 {object} docs.ErrorResponse // @Failure 404 {object} docs.ErrorResponse // @Failure 500 {object} docs.ErrorResponse // @Router /api/announcements/{id} [delete] func (h *Handler) Delete(c *fiber.Ctx) error { id, err := strconv.ParseUint(c.Params("id"), 10, 64) if err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "유효하지 않은 공지사항 ID입니다"}) } if err := h.svc.Delete(uint(id)); err != nil { if strings.Contains(err.Error(), "찾을 수 없습니다") { return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": err.Error()}) } return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "삭제에 실패했습니다"}) } return c.SendStatus(fiber.StatusNoContent) }