Skip to content

Commit 8791900

Browse files
add new enpoints
1 parent c87fed4 commit 8791900

File tree

3 files changed

+245
-0
lines changed

3 files changed

+245
-0
lines changed

internal/handlers/post.go

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,4 +474,170 @@ func (h *PostHandler) GetReviewsByBook(c *gin.Context) {
474474
}
475475

476476
c.JSON(http.StatusOK, gin.H{"reviews": reviews})
477+
}
478+
479+
// @Summary Get posts by type
480+
// @Description Get posts filtered by type with pagination
481+
// @Tags Posts
482+
// @Produce json
483+
// @Param type query string true "Post type (e.g., 'announcement', 'discussion', 'poll', 'review')"
484+
// @Param limit query int true "Number of posts to return"
485+
// @Param offset query int true "Number of posts to skip"
486+
// @Success 200 {array} models.PostResponse "Posts retrieved successfully"
487+
// @Failure 400 {object} map[string]interface{} "Bad request"
488+
// @Failure 500 {object} models.ErrorResponse
489+
// @Router /posts/by-type [get]
490+
func (h *PostHandler) GetPostsByType(c *gin.Context) {
491+
postType := c.Query("type")
492+
if postType == "" {
493+
c.JSON(http.StatusBadRequest, gin.H{"error": "type is required"})
494+
return
495+
}
496+
limitStr := c.Query("limit")
497+
if limitStr == "" {
498+
c.JSON(http.StatusBadRequest, gin.H{"error": "limit is required"})
499+
return
500+
}
501+
limit, err := strconv.Atoi(limitStr)
502+
if err != nil {
503+
c.JSON(http.StatusBadRequest, gin.H{"error": "limit must be an integer"})
504+
return
505+
}
506+
507+
offsetStr := c.Query("offset")
508+
if offsetStr == "" {
509+
c.JSON(http.StatusBadRequest, gin.H{"error": "offset is required"})
510+
return
511+
}
512+
offset, err := strconv.Atoi(offsetStr)
513+
if err != nil {
514+
c.JSON(http.StatusBadRequest, gin.H{"error": "offset must be an integer"})
515+
return
516+
}
517+
518+
posts, err := h.postService.GetPostsByType(postType, limit, offset)
519+
if err != nil {
520+
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
521+
return
522+
}
523+
524+
c.JSON(http.StatusOK, gin.H{"posts": posts})
525+
}
526+
527+
// @Summary Get poll posts by club ID
528+
// @Description Retrieve all poll posts associated with a specific club
529+
// @Tags Posts
530+
// @Accept json
531+
// @Produce json
532+
// @Param id path int true "Club ID"
533+
// @Param include_expired query bool false "Include expired polls"
534+
// @Success 200 {array} models.Post "Poll posts retrieved successfully"
535+
// @Failure 400 {object} map[string]interface{} "Bad request"
536+
// @Failure 500 {object} models.ErrorResponse
537+
// @Router /clubs/{id}/posts/polls [get]
538+
func (h *PostHandler) GetPollPostsByClubID(c *gin.Context) {
539+
clubIDParam := c.Param("id")
540+
clubID, err := strconv.ParseUint(clubIDParam, 10, 32)
541+
if err != nil {
542+
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid club ID"})
543+
return
544+
}
545+
includeExpired := c.Query("include_expired") == "true"
546+
547+
posts, err := h.postService.GetPollPostsByClubID(uint(clubID), includeExpired)
548+
if err != nil {
549+
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
550+
return
551+
}
552+
553+
c.JSON(http.StatusOK, gin.H{"posts": posts})
554+
}
555+
556+
// @Summary Get user poll votes
557+
// @Description Retrieve the poll votes made by the authenticated user for a specific poll post
558+
// @Tags Posts
559+
// @Produce json
560+
// @Param id path int true "Post ID"
561+
// @Success 200 {object} map[string]interface{} "User poll votes retrieved successfully"
562+
// @Failure 400 {object} map[string]interface{} "Bad request"
563+
// @Failure 401 {object} map[string]interface{} "Unauthorized"
564+
// @Failure 500 {object} models.ErrorResponse
565+
// @Router /posts/{id}/poll/votes [get]
566+
func (h *PostHandler) GetUserPollVotes(c *gin.Context) {
567+
postIDParam := c.Param("id")
568+
postID, err := strconv.ParseUint(postIDParam, 10, 32)
569+
if err != nil {
570+
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid post ID"})
571+
return
572+
}
573+
574+
useridRaw, exists := c.Get("user_id")
575+
if !exists {
576+
c.JSON(http.StatusUnauthorized, gin.H{"error": "user not authenticated"})
577+
return
578+
}
579+
580+
userID, ok := useridRaw.(uint)
581+
if !ok {
582+
c.JSON(http.StatusInternalServerError, gin.H{"error": "invalid user ID"})
583+
return
584+
}
585+
586+
votes, err := h.postService.GetUserPollVotes(uint(postID), userID)
587+
if err != nil {
588+
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
589+
return
590+
}
591+
592+
c.JSON(http.StatusOK, gin.H{"votes": votes})
593+
}
594+
595+
// @Summary Remove vote from poll
596+
// @Description Remove a user's vote from a poll post
597+
// @Tags Posts
598+
// @Accept json
599+
// @Produce json
600+
// @Param id path int true "Post ID"
601+
// @Param vote body models.PollVoteRequest true "Vote data"
602+
// @Success 200 {object} map[string]interface{} "Vote removed successfully"
603+
// @Failure 400 {object} map[string]interface{} "Bad request"
604+
// @Failure 401 {object} map[string]interface{} "Unauthorized"
605+
// @Failure 500 {object} models.ErrorResponse
606+
// @Router /posts/{id}/unvote [post]
607+
func (h *PostHandler) RemoveVoteFromPoll(c *gin.Context) {
608+
postIDParam := c.Param("id")
609+
postID, err := strconv.ParseUint(postIDParam, 10, 32)
610+
if err != nil {
611+
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid post ID"})
612+
return
613+
}
614+
615+
useridRaw, exists := c.Get("user_id")
616+
if !exists {
617+
c.JSON(http.StatusUnauthorized, gin.H{"error": "user not authenticated"})
618+
return
619+
}
620+
621+
userID, ok := useridRaw.(uint)
622+
if !ok {
623+
c.JSON(http.StatusInternalServerError, gin.H{"error": "invalid user ID"})
624+
return
625+
}
626+
627+
var req models.PollVoteRequest
628+
if err := c.ShouldBindJSON(&req); err != nil {
629+
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid body"})
630+
return
631+
}
632+
if err := h.validator.Struct(req); err != nil {
633+
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
634+
return
635+
}
636+
637+
if err := h.postService.RemoveVoteFromPoll(uint(postID), userID, req.OptionIDs[0]); err != nil {
638+
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
639+
return
640+
}
641+
642+
c.JSON(http.StatusOK, gin.H{"message": "vote removed successfully"})
477643
}

internal/handlers/server.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ func (s *Server) setupRoutes() {
150150
protected.POST("/clubs", clubHandler.CreateClub)
151151
protected.PUT("/clubs/:id", middleware.RequireClubMembershipWithRoles(clubRepo, "club_admin"), clubHandler.UpdateClub)
152152
protected.DELETE("/clubs/:id", middleware.RequireClubMembershipWithRoles(clubRepo, "club_admin"), clubHandler.DeleteClub)
153+
protected.GET("/clubs/:id/poll", postHandler.GetPollPostsByClubID)
153154

154155
protected.POST("/clubs/:id/join", clubHandler.JoinClub)
155156
protected.POST("/clubs/:id/leave", middleware.RequireClubMembership(clubRepo), clubHandler.LeaveClub)
@@ -176,7 +177,11 @@ func (s *Server) setupRoutes() {
176177
protected.PUT("/posts/:id", middleware.RequireClubMembership(clubRepo), postHandler.UpdatePost)
177178
protected.DELETE("/posts/:id", middleware.RequireClubMembership(clubRepo), postHandler.DeletePost)
178179
protected.GET("/posts/reviews", middleware.RequireClubMembership(clubRepo), postHandler.GetReviewsByBook)
180+
protected.GET("/posts/filter", middleware.RequireClubMembership(clubRepo), postHandler.GetPostsByType)
181+
179182
protected.POST("/posts/:id/vote", middleware.RequireClubMembership(clubRepo), postHandler.VoteOnPoll)
183+
protected.POST("/posts/:id/unvote", middleware.RequireClubMembership(clubRepo), postHandler.RemoveVoteFromPoll)
184+
protected.GET("/posts/:id/poll/votes", middleware.RequireClubMembership(clubRepo), postHandler.GetUserPollVotes)
180185

181186
protected.POST("/posts/:id/like", middleware.RequireClubMembership(clubRepo), postHandler.LikePost)
182187
protected.POST("/posts/:id/unlike", middleware.RequireClubMembership(clubRepo), postHandler.UnlikePost)

internal/services/post.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,4 +498,78 @@ func (s *PostService) GetReviewsByBook(bookID uint) ([]models.PostResponse, erro
498498
responses = append(responses, post.ToResponse())
499499
}
500500
return responses, nil
501+
}
502+
503+
func (s *PostService) GetPostsByType(postType string, limit, offset int) ([]models.PostResponse, error) {
504+
posts, err := s.postRepo.GetPostsByType(postType, limit, offset)
505+
if err != nil {
506+
return nil, err
507+
}
508+
509+
var responses []models.PostResponse
510+
for _, post := range posts {
511+
responses = append(responses, post.ToResponse())
512+
}
513+
return responses, nil
514+
}
515+
516+
func (s *PostService) GetPollPostsByClubID(clubID uint, includeExpired bool) ([]models.PostResponse, error) {
517+
_, err := s.clubRepo.GetByID(clubID)
518+
if err != nil {
519+
if errors.Is(err, gorm.ErrRecordNotFound) {
520+
return nil, errors.New("club not found")
521+
}
522+
return nil, err
523+
}
524+
525+
posts, err := s.postRepo.GetPollPostsByClubID(clubID, includeExpired)
526+
if err != nil {
527+
return nil, err
528+
}
529+
530+
var responses []models.PostResponse
531+
for _, post := range posts {
532+
responses = append(responses, post.ToResponse())
533+
}
534+
return responses, nil
535+
}
536+
537+
func (s *PostService) RemoveVoteFromPoll(postID, userID uint, optionID string) error {
538+
_, err := s.postRepo.GetByID(postID)
539+
if err != nil {
540+
if errors.Is(err, gorm.ErrRecordNotFound) {
541+
return errors.New("post not found")
542+
}
543+
return err
544+
}
545+
546+
_, err = s.userRepo.GetByID(userID)
547+
if err != nil {
548+
if errors.Is(err, gorm.ErrRecordNotFound) {
549+
return errors.New("user not found")
550+
}
551+
return err
552+
}
553+
554+
return s.postRepo.RemoveVoteFromPoll(postID, userID, optionID)
555+
}
556+
557+
func (s *PostService) GetUserPollVotes(postID, userID uint) ([]models.PollVote, error) {
558+
_, err := s.postRepo.GetByID(postID)
559+
if err != nil {
560+
if errors.Is(err, gorm.ErrRecordNotFound) {
561+
return nil, errors.New("post not found")
562+
}
563+
return nil, err
564+
}
565+
566+
_, err = s.userRepo.GetByID(userID)
567+
if err != nil {
568+
if errors.Is(err, gorm.ErrRecordNotFound) {
569+
return nil, errors.New("user not found")
570+
}
571+
return nil, err
572+
}
573+
574+
return s.postRepo.GetUserPollVotes(postID, userID)
501575
}

0 commit comments

Comments
 (0)