Nomad-Wetube : Comment기능

이은지·2023년 3월 13일
0

댓글을 추가했을 때 댓글을 적은 사용자의 이미지, 아이디, 댓글내용, 삭제버튼을 표시하고 싶었다

  1. watch.pug
div.video__comments
    ul
        each comment in comments.reverse()
            li.video__comment(data-id=comment.id)
                div.video__comment-area
                    div.video__comment__owner-img
						//avatarUrl이 "http"로 시작하면
                        if `${(comment.owner.avatarUrl).substring(0,4)}` === "http"
                        	img(src=comment.owner.avatarUrl) //img src를 표시
						//그게 아니면 (서버에 있는 이미지가 아닐 때, 이미지가 없을 때)
                        else 
                        	img(src="/" + comment.owner.avatarUrl, crossorigin) //지금 오류남
                    div.video__comment-info
                    	a.video__comment__owner-name(href=`/users/${comment.owner._id}`)
                    		span #{comment.owner.name}
                    	span #{comment.text}
                //댓글 주인 id, 로그인 id가 같으면 삭제버튼 표시
                if String(comment.owner._id) == String(loggedInUser._id) 
                	span.video__comment-delete(data-id=comment.id) 삭제
        else
        	span No Comments found.
  1. commentSection.js
const videoContainer = document.getElementById("videoContainer");
const form = document.getElementById("commentForm");
const deleteBtn = document.querySelectorAll(".video__comment-delete");

const addComment = (text, id, owner) => {
  const videoComments = document.querySelector(".video__comments ul");
  const newComment = document.createElement("li");
  newComment.dataset.id = id;
  newComment.className = "video__comment";

  //ownerImg추가
  const ownerImg = document.createElement("div");
  ownerImg.className = "video__comment__owner-img";
  const img = document.createElement("img");
  if (owner.avatarUrl.substring(0, 4) === "http") {
    img.src = owner.avatarUrl;
  } else {
    img.src = "/" + owner.avatarUrl;
  }

  //info div 추가
  const info = document.createElement("div");
  info.className = "video__comment-info";
  //ownerName 추가
  const ownerName = document.createElement("a");
  ownerName.href = `/users/${owner._id}`;
  ownerName.className = "video__comment__owner-name";
  const ownerNameSpan = document.createElement("span");
  ownerNameSpan.innerText = `${owner.name}`;

  //text 추가
  const span = document.createElement("span");
  span.innerText = ` ${text}`;
  //remove 추가
  const remove = document.createElement("span");
  remove.innerText = "삭제";
  remove.dataset.id = id;
  remove.addEventListener("click", handleDelete);

  newComment.appendChild(ownerImg);
  ownerImg.appendChild(img);
  newComment.appendChild(info);
  info.appendChild(ownerName);
  ownerName.appendChild(ownerNameSpan);
  info.appendChild(span);
  newComment.appendChild(remove);
  videoComments.prepend(newComment);
};

const handleSubmit = async (event) => {
  event.preventDefault();
  const textarea = form.querySelector("textarea");
  const text = textarea.value;
  const videoId = videoContainer.dataset.id;
  if (text.trim() === "") {
    return;
  }
  const response = await fetch(`/api/videos/${videoId}/comment`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ text }),
  });
  if (response.status === 201) {
    textarea.value = "";
    const { newCommentId, owner } = await response.json();
    addComment(text, newCommentId, owner);
  }
};

if (form) {
  form.addEventListener("submit", handleSubmit);
}

const handleDelete = async (event) => {
  //li의 className을 parent로 지정
  const parent = event.target.closest(".video__comment");
  console.log(parent);
  const commentId = parent.dataset.id;
  await fetch(`/api/comments/${commentId}`, {
    method: "DELETE",
  });
  parent.remove();
};

deleteBtn.forEach((elm) => elm.addEventListener("click", handleDelete));
  1. videoController.js
export const watch = async (req, res) => {
  const { id } = req.params;
  const video = await Video.findById(id).populate("owner").populate("comments");
  const comments = await Comment.find({ video: id }).populate("owner"); //!!!
  if (!video) {
    return res.render("404", { pageTitle: "Video not found." });
  }
  return res.render("watch", { pageTitle: video.title, video, comments });
};
//댓글 생성
export const createComment = async (req, res) => {
  const {
    session: {
      user: { _id },
    },
    body: { text },
    params: { id },
  } = req;
  const video = await Video.findById(id);
  if (!video) {
    return res.sendStatus(404);
  }
  //댓글 생성할 때 : 댓글 내용, 댓글 주인 id, 영상 id
  const comment = await Comment.create({
    text,
    owner: _id,
    video: id,
  });
  //댓글 주인
  const owner = await User.findById(comment.owner); //comment_owner

  owner.comments.push(comment._id);
  owner.save();
  video.comments.push(comment._id);
  video.save();

  return res.status(201).json({ newCommentId: comment._i, owner }); //comment_owner
};

//댓글 삭제
export const deleteComment = async (req, res) => {
  const { id } = req.params;
  const {
    user: { _id },
  } = req.session;
  const comment = await Comment.findById(id);
  if (!comment) {
    return res.sendStatus(404);
  }
  await Comment.findByIdAndDelete(id);
  return res.sendStatus(200);
};
  1. apiRouter.js
import express from "express";
import {
  registerView,
  createComment,
  deleteComment,
} from "../controllers/videoController";

const apiRouter = express.Router();

apiRouter.post("/videos/:id([0-9a-f]{24})/view", registerView);
apiRouter.post("/videos/:id([0-9a-f]{24})/comment", createComment); //댓글 생성
apiRouter.delete("/comments/:id([0-9a-f]{24})", deleteComment); //댓글 삭제

export default apiRouter;

[결과]

[오류 있는거]

  • 로그인 하는 사용자 이미지가 없는 경우 : 댓글을 추가하고 새로고침을 하면 Internal server error가 뜬다

[아직 헷갈리는거]

  • populate 개념

7개의 댓글

comment-user-thumbnail
2023년 12월 25일

I have never tried this minecraftle feature

답글 달기
comment-user-thumbnail
2024년 1월 12일

our Escort in Panaji gallery then you can make advance booking for her fellowship by contacting us. We always available for you to fulfil your sensual needs.

답글 달기
comment-user-thumbnail
2024년 2월 6일

I tried your Drift hunters method, it's really helpful for me. Thank you very much!

답글 달기
comment-user-thumbnail
2024년 2월 8일

The basic reason for considering our agency is that you can book highly professional, smart, and bold girls from here. These girls offer you a great amount of physical as well as mental satisfaction. If you want to book any of our Arab Goa Escorts Service ,

답글 달기
comment-user-thumbnail
2024년 2월 9일

These young beautiful Escorts in Paharganj are well-known for their valuable and real-life experience which every men appreciates.

답글 달기
comment-user-thumbnail
2024년 3월 2일

They don't hesitate to become naked in front of our Call Girls in Noida clients. Confidence and passion are in her blood. You can't even feel this is your first time to meet with them. Their sexy bodies easily catch your attention towards them.

답글 달기
comment-user-thumbnail
2024년 3월 6일

As the most well-known escort agency in Jaipur, we allow our clients to choose Jaipur Escort Service by showcasing escort girl profiles online. Offering clients choice is best achieved by showcasing escort profiles in the form of a gallery.

답글 달기