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 개념

0개의 댓글