feat: add post like
This commit is contained in:
@@ -125,6 +125,51 @@ func (h *PostHandler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
response.JSON(w, http.StatusOK, p)
|
||||
}
|
||||
|
||||
// likeResp is returned by Like / Unlike — the new viewer state + effective
|
||||
// total (likes_count + pending Redis delta) so the client can reconcile.
|
||||
type likeResp struct {
|
||||
Liked bool `json:"liked"`
|
||||
LikesCount int `json:"likes_count"`
|
||||
}
|
||||
|
||||
// Like — POST /posts/{id}/like. Idempotent. RequireAuth.
|
||||
func (h *PostHandler) Like(w http.ResponseWriter, r *http.Request) {
|
||||
uid := middleware.UserID(r.Context())
|
||||
id := chi.URLParam(r, "id")
|
||||
count, err := h.svc.Like(r.Context(), uid, id)
|
||||
if err != nil {
|
||||
mapSocialErr(w, err)
|
||||
return
|
||||
}
|
||||
response.JSON(w, http.StatusOK, likeResp{Liked: true, LikesCount: count})
|
||||
}
|
||||
|
||||
// Unlike — DELETE /posts/{id}/like. Idempotent. RequireAuth.
|
||||
func (h *PostHandler) Unlike(w http.ResponseWriter, r *http.Request) {
|
||||
uid := middleware.UserID(r.Context())
|
||||
id := chi.URLParam(r, "id")
|
||||
count, err := h.svc.Unlike(r.Context(), uid, id)
|
||||
if err != nil {
|
||||
mapSocialErr(w, err)
|
||||
return
|
||||
}
|
||||
response.JSON(w, http.StatusOK, likeResp{Liked: false, LikesCount: count})
|
||||
}
|
||||
|
||||
// ListLikes — GET /posts/{id}/likes?limit=&offset=&q=. Paginated "liked by"
|
||||
// users with optional name/handle search. Public (OptionalAuth).
|
||||
func (h *PostHandler) ListLikes(w http.ResponseWriter, r *http.Request) {
|
||||
id := chi.URLParam(r, "id")
|
||||
limit, offset := parseLimitOffset(r)
|
||||
q := strings.TrimSpace(r.URL.Query().Get("q"))
|
||||
users, total, err := h.svc.Likers(r.Context(), id, q, limit, offset)
|
||||
if err != nil {
|
||||
mapSocialErr(w, err)
|
||||
return
|
||||
}
|
||||
response.JSON(w, http.StatusOK, followListResp{Users: users, Total: total})
|
||||
}
|
||||
|
||||
func (h *PostHandler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
uid := middleware.UserID(r.Context())
|
||||
if err := h.svc.Delete(r.Context(), chi.URLParam(r, "id"), uid); err != nil {
|
||||
@@ -443,10 +488,11 @@ type ProfileHandler struct {
|
||||
posts *repository.PostRepo
|
||||
collections *repository.CollectionRepo
|
||||
graph *service.SocialGraphService
|
||||
likes *repository.LikeRepo
|
||||
}
|
||||
|
||||
func NewProfileHandler(users *repository.UserRepo, posts *repository.PostRepo, collections *repository.CollectionRepo, graph *service.SocialGraphService) *ProfileHandler {
|
||||
return &ProfileHandler{users: users, posts: posts, collections: collections, graph: graph}
|
||||
func NewProfileHandler(users *repository.UserRepo, posts *repository.PostRepo, collections *repository.CollectionRepo, graph *service.SocialGraphService, likes *repository.LikeRepo) *ProfileHandler {
|
||||
return &ProfileHandler{users: users, posts: posts, collections: collections, graph: graph, likes: likes}
|
||||
}
|
||||
|
||||
func (h *ProfileHandler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -527,6 +573,17 @@ func (h *ProfileHandler) Feed(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Like counts (effective) + viewer-liked state for every post in the page.
|
||||
if len(posts) > 0 {
|
||||
ptrs := make([]*model.Post, len(posts))
|
||||
for i := range posts {
|
||||
ptrs[i] = &posts[i]
|
||||
}
|
||||
if err := h.likes.Hydrate(r.Context(), viewerID, ptrs); err != nil {
|
||||
mapSocialErr(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
response.JSONWithMeta(w, http.StatusOK, posts, paginationMeta(total, limit, offset))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user