Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions backend/api/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ func Router(mux *mux.Router, db *sql.DB) {

// Likes & dislikes for comments and posts ... the getPosts and getComments methods return the number of likes and dislikes with each post/comment
mux.HandleFunc("/vote", voteHandler.VotePostOrCommentHandler).Methods("POST")
mux.HandleFunc("/vote", voteHandler.GetItemVotesHandler).Methods("GET")
//mux.HandleFunc("/user/vote", voteHandler.GetUserVoteActionHandler).Methods("GET")

// Groups
groupHandler := handler.NewGroupHandler(groupRepository, sessionRepository, groupMemberRepository, notificationHandler, userRepository, friendsRepository)
Expand Down
Binary file modified backend/pkg/db/database.db
Binary file not shown.
111 changes: 90 additions & 21 deletions backend/pkg/handler/voteHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import (
"backend/util"
"encoding/json"
"fmt"
"log"
"net/http"
"strconv"
)

type VoteHandler struct {
voteRepo *repository.VoteRepository
voteRepo *repository.VoteRepository
sessionRepo *repository.SessionRepository
}

Expand Down Expand Up @@ -45,22 +47,24 @@ func (h *VoteHandler) VotePostOrCommentHandler(w http.ResponseWriter, r *http.Re
return
}

err = h.voteRepo.VoteItem(voteData, userID); if err != nil {
err = h.voteRepo.VoteItem(voteData, userID)
if err != nil {
errmsg := fmt.Sprintf("Failed to vote %s: %s", voteData.Item, err.Error())
http.Error(w, errmsg, http.StatusInternalServerError)
}

var likes, dislikes, getVoteError = h.voteRepo.GetItemVotes(voteData.Item, voteData.ItemID); if getVoteError != nil {
http.Error(w, "Failed to fetch updated votes: " + err.Error(), http.StatusInternalServerError)

var likes, dislikes, getVoteError = h.voteRepo.GetItemVotes(voteData.Item, voteData.ItemID)
if getVoteError != nil {
http.Error(w, "Failed to fetch updated votes: "+err.Error(), http.StatusInternalServerError)
return
}

// Create a response struct for the votes
response := struct {
Likes int `json:"likes"`
Likes int `json:"likes"`
Dislikes int `json:"dislikes"`
}{
Likes: likes,
Likes: likes,
Dislikes: dislikes,
}

Expand All @@ -78,25 +82,90 @@ func (h *VoteHandler) VotePostOrCommentHandler(w http.ResponseWriter, r *http.Re
}
}

func (h *VoteHandler) GetItemVotesHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
return
}

// Extract item type and item ID from request parameters
itemType := r.URL.Query().Get("itemType")
itemIDStr := r.URL.Query().Get("itemID")
itemID, err := strconv.Atoi(itemIDStr)
if err != nil {
http.Error(w, "Invalid item ID", http.StatusBadRequest)
return
}

// Retrieve the user ID from the session token
userID, err := h.sessionRepo.GetUserIDFromSessionToken(util.GetSessionToken(r))
if err != nil {
http.Error(w, "User not authenticated", http.StatusUnauthorized)
return
}

// Call the GetItemVotes function from the repository to get the total likes and dislikes
likes, dislikes, err := h.voteRepo.GetItemVotes(itemType, itemID)
if err != nil {
http.Error(w, "Failed to fetch item votes: "+err.Error(), http.StatusInternalServerError)
return
}

// Get the user's vote action
userAction, err := h.voteRepo.GetUserVoteAction(userID, itemType, itemID)
if err != nil {
http.Error(w, "Failed to fetch user vote action", http.StatusInternalServerError)
return
}

// Construct a response containing the retrieved vote information and user action
response := struct {
Likes int `json:"likes"`
Dislikes int `json:"dislikes"`
UserAction string `json:"userAction"`
}{
Likes: likes,
Dislikes: dislikes,
UserAction: userAction,
}

// Serialize the response to JSON
responseData, err := json.Marshal(response)
if err != nil {
http.Error(w, "Failed to marshal response data", http.StatusInternalServerError)
return
}

// Set the content type header and write the response
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_, err = w.Write(responseData)
if err != nil {
// Handle error writing response here
http.Error(w, "Failed to write response data", http.StatusInternalServerError)
return
}
}

func (h *VoteHandler) AppendVotesToPostsResponse(posts []model.Post) ([]model.PostsResponse, error) {
postsResponse := make([]model.PostsResponse, len(posts))
for i, post := range posts {
likes, dislikes, err := h.voteRepo.GetItemVotes("post", post.Id)
if err != nil {
return nil, err
log.Fatal(err)
}
postsResponse[i] = model.PostsResponse{
Id: post.Id,
UserID: post.UserID,
GroupID: post.GroupID,
Title: post.Title,
Content: post.Content,
ImageURL: post.ImageURL,
PrivacySetting: post.PrivacySetting,
CreatedAt: post.CreatedAt,
Likes: likes,
Dislikes: dislikes,
}
Id: post.Id,
UserID: post.UserID,
GroupID: post.GroupID,
Title: post.Title,
Content: post.Content,
ImageURL: post.ImageURL,
PrivacySetting: post.PrivacySetting,
CreatedAt: post.CreatedAt,
Likes: likes,
Dislikes: dislikes,
}
}
return postsResponse, nil
}
Expand All @@ -106,7 +175,7 @@ func (h *VoteHandler) AppendVotesToCommentsResponse(comments []model.Comment) ([
for i, comment := range comments {
likes, dislikes, err := h.voteRepo.GetItemVotes("comment", comment.Id)
if err != nil {
return nil, err
log.Fatal(err)
}
commentsResponse[i] = model.CommentsResponse{
Id: comment.Id,
Expand All @@ -120,4 +189,4 @@ func (h *VoteHandler) AppendVotesToCommentsResponse(comments []model.Comment) ([
}
}
return commentsResponse, nil
}
}
1 change: 1 addition & 0 deletions backend/pkg/model/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,4 +261,5 @@ type VoteData struct {
Item string `json:"item"` // 'comment' or 'post'
ItemID int `json:"item_id"` // comment or post id
Action string `json:"action"` // 'like' or 'dislike'
UserId int `json:"user_id"`
}
38 changes: 34 additions & 4 deletions backend/pkg/repository/voteRepository.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"backend/pkg/model"
"database/sql"
"fmt"
"log" // Import the log package for logging
)

type VoteRepository struct {
Expand Down Expand Up @@ -38,16 +39,45 @@ func (r *VoteRepository) VoteItem(vote model.VoteData, userID int) error {
return err
}

func (r *VoteRepository) GetItemVotes(itemType string, itemID int) (int, int, error){
func (r *VoteRepository) GetItemVotes(itemType string, itemID int) (int, int, error) {
var likes, dislikes int
query := fmt.Sprintf("SELECT COUNT(*) FROM votes WHERE %sID = ? AND type = ?", itemType)
err := r.db.QueryRow(query, itemID, "upvote").Scan(&likes)
err := r.db.QueryRow(query, itemID, "like").Scan(&likes)
if err != nil {
log.Printf("Error retrieving upvotes for %s ID %d: %v\n", itemType, itemID, err)
return 0, 0, err
}
err = r.db.QueryRow(query, itemID, "downvote").Scan(&dislikes)
err = r.db.QueryRow(query, itemID, "dislike").Scan(&dislikes)
if err != nil {
log.Printf("Error retrieving downvotes for %s ID %d: %v\n", itemType, itemID, err)
return 0, 0, err
}
return likes, dislikes, nil
}
}

func (r *VoteRepository) GetUserVoteAction(userID int, itemType string, itemID int) (string, error) {
var action string
query := fmt.Sprintf("SELECT type FROM votes WHERE %sID = ? AND userID = ?", itemType)
err := r.db.QueryRow(query, itemID, userID).Scan(&action)
if err != nil {
if err == sql.ErrNoRows {
// If no vote action found for the user and item, return an empty string
return "", nil
}
log.Printf("Error retrieving user vote action for %s ID %d: %v\n", itemType, itemID, err)
return "", err
}
return action, nil
}

/* func (r *VoteRepository) HasUserVoted(itemType string, itemID, userID int) bool {
// Check if the user has voted for the given item
var voteCount int
query := fmt.Sprintf("SELECT COUNT(*) FROM votes WHERE %sID = ? AND userID = ?", itemType)
err := r.db.QueryRow(query, itemID, userID).Scan(&voteCount)
if err != nil {
log.Printf("Error checking user vote for %s ID %d: %v\n", itemType, itemID, err)
return false // Assume no vote has been cast in case of an error
}
return voteCount > 0 // Return true if the user has voted (voteCount > 0), false otherwise
} */
Loading