과거 프로그래밍 자료들/프로젝트

SNS서비스 좋아요 버튼 및 좋아요 취소 버튼 만들기

평부 2022. 9. 7. 13:27

 

* 결과

- mysql에서 좋아요 누르기 전에는 Like 테이블이 빈칸

- 자신이 작성한 글에 좋아요를 누르면 Like 테이블에 입력되지 않음

- 좋아요 버튼을 누르면 Like 테이블에 값이 들어감

- 좋아요 취소 버튼을 누르면 Like 테이블에서 사라짐

01234
좋아요, 좋아요 취소 누른 후 mysql 차이 비교

 

* 매우매우매우 도움된 참고글

https://www.inflearn.com/questions/539697

 

게시글 좋아요 누르기 및 좋아요 취소하기 질문입니다 - 인프런 | 질문 & 답변

계속 고민하다 이렇게 질문을 남깁니다. 우선 제가 시도한 방법부터 알려드리자면 db.User.belongsToMany(db.Post, { through: 'Like'}); db.Post.belongsToMany(db.User, { through: 'Like', as: '...

www.inflearn.com

 

* 모델(Model) 부분

- post.js (as를 통해 시퀄라이즈 사용 : https://ba-gotocode131.tistory.com/196)

 

db.Post.belongsToMany(db.User, { through: "Like", as: "Liker" });

 

- user.js

 

 db.User.belongsToMany(db.Post, { through: "Like" });

 

 

* router 부분

 

- page.js(메인 화면)

 

router.get("/main", async (req, res, next) => {
  //post 결과 보려면 이 부분 넣어야 함
  try {
    if (req.user) {
      const posts = await Post.findAll({
        include: [
          {
            model: User,
            attributes: ["id", "nickname"],
          },
          //추가할 부분 1
          { 
            model: User,
            attributes: ["id", "nickname"],
            as: "Liker",
          },
        ],
        order: [["createdAt", "DESC"]],
      });
	//추가할 부분 2
      posts.forEach((post) => {
        //post.User.id와 post.Liker.id가 같을 경우 true, 아니면 false
        post.liked = !!post.Liker.find((v) => v.id === req.user?.id);
      });
      res.render("main", {
        title: "engWordSNS",
        twits: posts,
      });
    } else {
      const posts = await Post.findAll({
        include: [
          {
            model: User,
            attributes: ["id", "nickname"],
          },
          {
            model: User,
            attributes: ["id", "nickname"],
            as: "Liker",
          },
        ],
        order: [["createdAt", "DESC"]],
      });
      res.render("main", {
        title: "engWordSNS",
        twits: posts, //프론트단에서는 twits으로 값을 출력
      });
    }
  } catch (error) {
    console.error(error);
    next(error);
  }
});

 

- user.js

 

router.post("/:id/like", async (req, res, next) => {
  try {
    //작성된 글을 찾음
    const posts = await Post.findOne({ where: { id: req.params.id } });
    if (posts) {
      await posts.addLiker(req.user.id); //추가하기
      res.json(posts);
    } else {
      res.status(404).send("작성된 글을 찾을 수 없습니다.");
    }
  } catch (error) {
    console.log(error);
    next(error);
  }
});

router.post("/:id/unlike", async (req, res, next) => {
  try {
    const post = await Post.findOne({ where: { id: req.params.id } });
    await post.removeLiker(req.user.id); //삭제하기
    res.send("success");
  } catch (error) {
    console.log(error);
    next(error);
  }
});

 

* 화면 부분

 

- main.html

 

 {% for twit in twits %}
        <div class="twit">
            //<input type="hidden" value="{{twit.id}}" class="twit-id">
            //twit.id로 값을 찾을 경우 본인 아이디에서 작성한 가장 최근 작성글만 찾아옴
            //따라서 twit.id를 dataset을 이용함
            <!-- 좋아요, 좋아요 취소 -->
            {% if twit.liked %}
            <button class="unlike" data-id="{{twit.id}}">좋아요취소</button>
            {% else %}
            <div>{{twit.id}}</div>
            <button class="like" data-id="{{twit.id}}">좋아요</button>
            {% endif %}
        </div>
        {% endfor %}

 

- main.html 내 javascript

 

//좋아요 버튼
    document.querySelectorAll(".like").forEach(function (tag) {
        tag.addEventListener("click", function (event) {
            const myId = document.querySelector("#my-id").value;
            const userId = tag.parentNode.querySelector('.twit-user-id').value;
            if (myId !== userId) {
                const twitId = event.target.dataset.id;
                console.log("twitId", twitId)
                //게시물 번호, 자신의번호, 게시글 작성자 번호
                axios.post(`/user/${twitId}/like`).then(() => {
                    location.reload();
                }).catch((err) => {
                    console.log(err);
                })
            } else {
                alert("자신이 작성한 게시글에는 좋아요를 누를 수 없습니다.");
            }
        })
    })
//좋아요 취소
    document.querySelectorAll(".unlike").forEach(function (tag) {
        tag.addEventListener("click", function (event) {
            const myId = document.querySelector("#my-id").value;
            const userId = tag.parentNode.querySelector('.twit-user-id').value;
            if (myId !== userId) {
                const twitId = event.target.dataset.id;
                console.log("twitId", twitId)
                //게시물 번호, 자신의번호, 게시글 작성자 번호
                axios.post(`/user/${twitId}/unlike`).then(() => {
                    location.reload();
                }).catch((err) => {
                    console.log(err);
                })
            }
        })
    })