package announcement import ( "log" "strconv" "strings" "a301_server/pkg/apperror" "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 apperror.Internal("공지사항을 불러오지 못했습니다") } 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 apperror.BadRequest("제목과 내용을 입력해주세요") } if len([]rune(body.Title)) > 256 { return apperror.BadRequest("제목은 256자 이하여야 합니다") } if len([]rune(body.Content)) > 10000 { return apperror.BadRequest("내용은 10000자 이하여야 합니다") } a, err := h.svc.Create(body.Title, body.Content) if err != nil { return apperror.Internal("공지사항 생성에 실패했습니다") } 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 apperror.BadRequest("유효하지 않은 공지사항 ID입니다") } var body struct { Title string `json:"title"` Content string `json:"content"` } if err := c.BodyParser(&body); err != nil { return apperror.ErrBadRequest } if body.Title == "" && body.Content == "" { return apperror.BadRequest("수정할 내용을 입력해주세요") } if len([]rune(body.Title)) > 256 { return apperror.BadRequest("제목은 256자 이하여야 합니다") } if len([]rune(body.Content)) > 10000 { return apperror.BadRequest("내용은 10000자 이하여야 합니다") } a, err := h.svc.Update(uint(id), body.Title, body.Content) if err != nil { if strings.Contains(err.Error(), "찾을 수 없습니다") { return apperror.NotFound(err.Error()) } log.Printf("공지사항 수정 실패 (id=%d): %v", id, err) return apperror.ErrInternal } 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 apperror.BadRequest("유효하지 않은 공지사항 ID입니다") } if err := h.svc.Delete(uint(id)); err != nil { if strings.Contains(err.Error(), "찾을 수 없습니다") { return apperror.NotFound(err.Error()) } return apperror.Internal("삭제에 실패했습니다") } return c.SendStatus(fiber.StatusNoContent) }