09009

[Spring] 예제 3 - 댓글 렌더링 본문

Back-End/Spring
[Spring] 예제 3 - 댓글 렌더링
09009

댓글 테이블 설계

댓글 테이블 생성

DROP TABLE fp_comment; 
-- 댓글 T
CREATE TABLE fp_comment(
  id NUMBER PRIMARY KEY,
  board_id NUMBER,
  member_id NUMBER,
  content_text VARCHAR2(4000),
  reg_date DATE
  );

DROP SEQUENCE fp_comment_seq; 
CREATE SEQUENCE fp_comment_seq;

 

 

 

댓글 입력 양식 만들기

readContentPage.jsp

(코드 중복 내용 생략)

<body>
<h1>상세 글보기</h1>

제목: ${data.boardDto.title }<br>
작성자: ${data.memberDto.nickname }<br>
작성일: ${data.boardDto.reg_date }<br>
조회수: ${data.boardDto.read_count }<br>

<br>
<c:forEach items="${data.boardImageDtoList}" var="boardImageDto">
	<img src="/uploadFiles/${boardImageDto.link }"><br>
</c:forEach>




내용: <br>
${data.boardDto.content }<br>

<i id="heartBox" onclick="toggleLike()" class="fs-1 text-danger bi bi-heart"></i><span id="totalLikeCount">3</span>


<div class="container">
	<div class="row">
		<div class="col-7">
			<textarea id="commentTextBox" class="form-control"></textarea>
		</div>
		<div class="col d-grid">
			<input onclick="registerComment()" class="btn btn-primary" type="button" value="댓글 작성">
		</div>
	</div>
</div>

  
<br><br>
<a href="./mainPage">목록으로</a>

<c:if test="${!empty sessionUser && sessionUser.id == data.memberDto.id }">
	<a href="./updatePage?id=${data.boardDto.id }">수정</a>
	<a href="./deleteProcess?id=${data.boardDto.id }">삭제</a>
</c:if>


<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
</body>
</html>

DTO 생성

CommentDto

package com.ja.finalproject.dto;

import java.util.Date;

public class CommentDto {
	private int id;
	private int  board_id;
	private int member_id;
	private String comment_text;
	private Date reg_date;
	public CommentDto() {
		super();
	}
	public CommentDto(int id, int board_id, int member_id, String comment_text, Date reg_date) {
		super();
		this.id = id;
		this.board_id = board_id;
		this.member_id = member_id;
		this.comment_text = comment_text;
		this.reg_date = reg_date;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public int getBoard_id() {
		return board_id;
	}
	public void setBoard_id(int board_id) {
		this.board_id = board_id;
	}
	public int getMember_id() {
		return member_id;
	}
	public void setMember_id(int member_id) {
		this.member_id = member_id;
	}
	public String getComment_text() {
		return comment_text;
	}
	public void setComment_text(String comment_text) {
		this.comment_text = comment_text;
	}
	public Date getReg_date() {
		return reg_date;
	}
	public void setReg_date(Date reg_date) {
		this.reg_date = reg_date;
	}

}

BoardSqlMapper

	// 댓글
	public void insertComment(CommentDto commentDto);
	public void deleteComment(int id);
	public void updateComment(CommentDto commentDto);
	public List<CommentDto> selectCommentAll(int boardId);

BoardSqlMapper.xml

	<insert id="insertComment">
		INSERT INTO fp_comment VALUES(
			fp_comment_seq.nextval,
			#{board_id},
			#{member_id},
			#{comment_text},
			SYSDATE
			)
	</insert>
	
	<delete id="deleteComment">
		DELETE FROM fp_comment WHERE id = #{id}
	</delete>
	
	<update id="updateComment">
		UPDATE fp_comment 
		SET 
			comment_text = #{comment_text}
		WHERE 
			id = #{id}
	</update>
	
	<select id="selectCommentAll" resultType="com.ja.finalproject.dto.CommentDto">
		SELECT * FROM fp_comment WHERE board_id = #{boardId}
		ORDER BY id DESC
	</select>

BoardServiceImpl

		// 댓글
		public void registerComment(CommentDto commentDto) {
			boardSqlMapper.insertComment(commentDto);
		}
		
		public void deleteComment(int id) {
			boardSqlMapper.deleteComment(id);
		}
		
		public void updateComment(CommentDto commentDto) {
			boardSqlMapper.updateComment(commentDto);
		}
		
		public List<Map<String, Object>> getCommentList(int boardId) {
			
			List<Map<String, Object>> list = new ArrayList<>();
			
			List<CommentDto> commentList = boardSqlMapper.selectCommentAll(boardId);
			
			for(CommentDto commentDto : commentList) {
				MemberDto memberDto = memberSqlMapper.selectById(commentDto .getMember_id());
				Map<String, Object> map = new HashMap<>();			
				map.put("memberDto", memberDto);
				map.put("commentDto", commentDto);
				list.add(map);
			}
			return list;				
		}

RestBoardController

// 댓글
 
   @RequestMapping("registerComment")
   public Map<String, Object> registerComment(HttpSession session, CommentDto params) {
	   
	   Map<String, Object> map = new HashMap<>();
	   
	   MemberDto sessionUser = (MemberDto) session.getAttribute("sessionUser");
	   params.setMember_id(sessionUser.getId());
	   
	   boardService.registerComment(params);
	   
	   map.put("result", "success");
	   return map;
   }
   
   @RequestMapping("deleteComment")
   public Map<String, Object> deleteComment(int id) {
	   
	   Map<String, Object> map = new HashMap<>();
	   
	   boardService.deleteComment(id);
	
	   map.put("result", "success");
	   return map;
   }
   
   @RequestMapping("getCommentList")
   public Map<String, Object> getCommentList(int boardId) {
	   
	   Map<String, Object> map = new HashMap<>();
	   
	   map.put("commentList", boardService.getCommentList(boardId));
	
	   map.put("result", "success");
	   return map;
   }
   
   
   @RequestMapping("updateComment")
   public Map<String, Object> updateComment(CommentDto params) {
	   
	   Map<String, Object> map = new HashMap<>();
	   
	   boardService.updateComment(params);
	
	   map.put("result", "success");
	   return map;
   }

readContentPage.jsp

댓글 등록

	function registerComment() {
		if(!mySessionId) {
			// 로그인 안되어있으니까 댓글 등록 불가
			return;
		}
		// ajax에서 insert
		const commentTextBox = document.getElementById("commentTextBox");
		const commentTextValue = commentTextBox.value;
		
		
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
				commentTextBox.value = ""; // 응답하면 댓글 지우기
			}
		}

		//post (insert이므로 post 방식으로)
		xhr.open("post", "./registerComment");
		xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 
		xhr.send("board_id=" + boardId + "&" + "comment_text=" + commentTextValue);

	}
내용: <br>
${data.boardDto.content }<br>

<i id="heartBox" onclick="toggleLike()" class="fs-1 text-danger bi bi-heart"></i><span id="totalLikeCount">3</span>


<div class="container">
	<div class="row">
		<div class="col-7">
			<textarea id="commentTextBox" class="form-control"></textarea>
		</div>
		<div class="col d-grid">
			<input onclick="registerComment()" class="btn btn-primary" type="button" value="댓글 작성">
		</div>
	</div>
	
	<div class="row">
		<div id="commentListBox" class="col">
			<div class="row">
				<div class="commentBox col-8 bg-primary">내용</div>
				<div class="col bg-secondary">닉네임</div>
				<div class="col bg-success">삭제</div>
				<div class="col bg-warning">수정</div>
			</div>
		</div>
	</div>
</div>

  
<br><br>
<a href="./mainPage">목록으로</a>

<c:if test="${!empty sessionUser && sessionUser.id == data.memberDto.id }">
	<a href="./updatePage?id=${data.boardDto.id }">수정</a>
	<a href="./deleteProcess?id=${data.boardDto.id }">삭제</a>
</c:if>


<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
</body>
</html>

 

링크를 통해서 확인하기

중간 코드

댓글 목록 렌더링 작업

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">

<script>

	const boardId = new URLSearchParams(location.search).get("id");

	function ajaxTemplete(){
		
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
			}
		}
		
		//get
		xhr.open("get", "요청 url?파라메터=값");
		xhr.send();
		
		//post
		xhr.open("post", "요청 url");
		xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 
		xhr.send("파라메터=값");
	}

	let mySessionId = null;

	function getSessionId(){
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
				if(response.result == "success"){
					mySessionId = response.id; 
				}
			}
		}
		
		//get
		xhr.open("get", "../member/getMyId", false); // 딱 여기만 쓰세요...false 동기식 호출..! 권장되지 않음
		xhr.send();		
	}

	function refreshTotalLikeCount(){
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
				const totalLikeCountBox = document.getElementById("totalLikeCount");
				totalLikeCountBox.innerText = response.count;
			}
		}
		
		
		
		//get
		xhr.open("get", "./getTotalLikeCount?boardId=" + boardId);
		xhr.send();		
	}
	
	function toggleLike(){
		if(mySessionId == null){
			if(confirm("로그인을 하셔야 이용하실 수 있습니다. 로그인 하시겠습니까?")){
				location.href = "../member/loginPage";
			}
			
			return;
		}
		
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
				refreshTotalLikeCount();
				refreshMyHeart();
			}
		}
		
		//get
		xhr.open("get", "./toggleLike?board_id=" + boardId);
		xhr.send();
		
	}
	
	function refreshMyHeart(){
		
		if(mySessionId == null) return;
		
		
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 렌더링... 작업..
				const heartBox = document.getElementById("heartBox");
				
				if(response.isLiked){
					heartBox.classList.remove("bi-heart");
					heartBox.classList.add("bi-heart-fill");
				}else{
					heartBox.classList.remove("bi-heart-fill");
					heartBox.classList.add("bi-heart");
				}
			}
		}
		
		//get
		xhr.open("get", "./isLiked?board_id=" + boardId);
		xhr.send();
		
	}
	
	function registerComment() {
		if(!mySessionId) {
			// 로그인 안되어있으니까 댓글 등록 불가
			return;
		}
		// ajax에서 insert
		const commentTextBox = document.getElementById("commentTextBox");
		const commentTextValue = commentTextBox.value;
		
		
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
				commentTextBox.value = ""; // 응답하면 댓글 지우기
				reloadCommentList(); // 댓글 등록 후 reload
			}
		}

		//post (insert이므로 post 방식으로)
		xhr.open("post", "./registerComment");
		xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 
		xhr.send("board_id=" + boardId + "&" + "comment_text=" + commentTextValue);

	}
	
	// 댓글 목록
	function reloadCommentList() {
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
				
				<%--<div class="row">
				<div class="commentBox col-8 bg-primary">내용</div>
				<div class="col bg-secondary">닉네임</div>
				<div class="col bg-success">삭제</div>
				<div class="col bg-warning">수정</div>
			</div> --%>
			
				document.getElementById("commentListBox").innerHTML = ""; // 안쪽 초기화 이때만, innerHTML 허용
				
				for(data of response.commentList) {
					const row1 = document.createElement("div"); // 태그 생성
					row1.classList.add("row");
					
					const colCommentBox = document.createElement("div"); // ui 세팅
					colCommentBox.classList.add("colCommentBox");
					colCommentBox.classList.add("col-8");
					colCommentBox.classList.add("bg-primary");
					colCommentBox.innerText = data.commentDto.comment_text; // 데이터 세팅	
					row1.appendChild(colCommentBox);
					
					const colNickname = document.createElement("div");
					colNickname.classList.add("col-2");
					colNickname.classList.add("bg-secondary");
					colNickname.innerText = data.memberDto.nickname; // 데이터세팅
					row1.appendChild(colNickname);
					
					if(mySessionId != null && data.commentDto.member_id) {
						const colDelete = document.createElement("div");
						colDelete.classList.add("col-1");
						colDelete.innerText = "삭제";
						row1.appendChild(colDelete);	
						
						const colUpdate = document.createElement("div");
						colUpdate.classList.add("col-1");
						colUpdate.innerText = "수정";
						row1.appendChild(colUpdate);	
					}
					
					document.getElementById("commentListBox").appendChild(row1);
					
				}
				
			}
		}
		
		//get
		xhr.open("get", "./getCommentList?boardId=" + boardId);
		
		xhr.send();
		
		
	}
	
	
	
	window.addEventListener("DOMContentLoaded", function(){
		//사실상 시작 시점...
		getSessionId();
		refreshTotalLikeCount();
		refreshMyHeart();
		reloadCommentList();
	});
</script>


</head>
<body>
<h1>상세 글보기</h1>

제목: ${data.boardDto.title }<br>
작성자: ${data.memberDto.nickname }<br>
작성일: ${data.boardDto.reg_date }<br>
조회수: ${data.boardDto.read_count }<br>

<br>
<c:forEach items="${data.boardImageDtoList}" var="boardImageDto">
	<img src="/uploadFiles/${boardImageDto.link }"><br>
</c:forEach>




내용: <br>
${data.boardDto.content }<br>

<i id="heartBox" onclick="toggleLike()" class="fs-1 text-danger bi bi-heart"></i><span id="totalLikeCount">3</span>


<div class="container">
	<div class="row">
		<div class="col-7">
			<textarea id="commentTextBox" class="form-control"></textarea>
		</div>
		<div class="col d-grid">
			<input onclick="registerComment()" class="btn btn-primary" type="button" value="댓글 작성">
		</div>
	</div>
	
	<div class="row">
		<div id="commentListBox" class="col">
			<div class="row">
				<div class="commentBox col-8 bg-primary">내용</div>
				<div class="col bg-secondary">닉네임</div>
				<div class="col bg-success">삭제</div>
				<div class="col bg-warning">수정</div>
			</div>
		</div>
	</div>
</div>

  
<br><br>
<a href="./mainPage">목록으로</a>

<c:if test="${!empty sessionUser && sessionUser.id == data.memberDto.id }">
	<a href="./updatePage?id=${data.boardDto.id }">수정</a>
	<a href="./deleteProcess?id=${data.boardDto.id }">삭제</a>
</c:if>


<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
</body>
</html>

삭제 버튼 동작 추가 및 수정

<script>

	const boardId = new URLSearchParams(location.search).get("id");

	function ajaxTemplete(){
		
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
			}
		}
		
		//get
		xhr.open("get", "요청 url?파라메터=값");
		xhr.send();
		
		//post
		xhr.open("post", "요청 url");
		xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 
		xhr.send("파라메터=값");
	}

	let mySessionId = null;

	function getSessionId(){
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
				if(response.result == "success"){
					mySessionId = response.id; 
				}
			}
		}
		
		//get
		xhr.open("get", "../member/getMyId", false); // 딱 여기만 쓰세요...false 동기식 호출..! 권장되지 않음
		xhr.send();		
	}

	function refreshTotalLikeCount(){
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
				const totalLikeCountBox = document.getElementById("totalLikeCount");
				totalLikeCountBox.innerText = response.count;
			}
		}
		
		
		
		//get
		xhr.open("get", "./getTotalLikeCount?boardId=" + boardId);
		xhr.send();		
	}
	
	function toggleLike(){
		if(mySessionId == null){
			if(confirm("로그인을 하셔야 이용하실 수 있습니다. 로그인 하시겠습니까?")){
				location.href = "../member/loginPage";
			}
			
			return;
		}
		
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
				refreshTotalLikeCount();
				refreshMyHeart();
			}
		}
		
		//get
		xhr.open("get", "./toggleLike?board_id=" + boardId);
		xhr.send();
		
	}
	
	function refreshMyHeart(){
		
		if(mySessionId == null) return;
		
		
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 렌더링... 작업..
				const heartBox = document.getElementById("heartBox");
				
				if(response.isLiked){
					heartBox.classList.remove("bi-heart");
					heartBox.classList.add("bi-heart-fill");
				}else{
					heartBox.classList.remove("bi-heart-fill");
					heartBox.classList.add("bi-heart");
				}
			}
		}
		
		//get
		xhr.open("get", "./isLiked?board_id=" + boardId);
		xhr.send();
		
	}
	
	function registerComment() {
		if(!mySessionId) {
			// 로그인 안되어있으니까 댓글 등록 불가
			return;
		}
		// ajax에서 insert
		const commentTextBox = document.getElementById("commentTextBox");
		const commentTextValue = commentTextBox.value;
		
		
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
				commentTextBox.value = ""; // 응답하면 댓글 지우기
				reloadCommentList(); // 댓글 등록 후 reload
			}
		}

		//post (insert이므로 post 방식으로)
		xhr.open("post", "./registerComment");
		xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 
		xhr.send("board_id=" + boardId + "&" + "comment_text=" + commentTextValue);

	}
	
	// 댓글 목록
	function reloadCommentList() {
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
				
				<%--<div class="row">
				<div class="commentBox col-8 bg-primary">내용</div>
				<div class="col bg-secondary">닉네임</div>
				<div class="col bg-success">삭제</div>
				<div class="col bg-warning">수정</div>
			</div> --%>
			
				document.getElementById("commentListBox").innerHTML = ""; // 안쪽 초기화 이때만, innerHTML 허용
				
				for(data of response.commentList) {
					const row1 = document.createElement("div"); // 태그 생성
					row1.classList.add("row");
					
					const colCommentBox = document.createElement("div"); // ui 세팅
					colCommentBox.classList.add("colCommentBox");
					colCommentBox.classList.add("col-8");
					colCommentBox.classList.add("bg-primary");
					colCommentBox.innerText = data.commentDto.comment_text; // 데이터 세팅	
					row1.appendChild(colCommentBox);
					
					const colNickname = document.createElement("div");
					colNickname.classList.add("col-2");
					colNickname.classList.add("bg-secondary");
					colNickname.innerText = data.memberDto.nickname; // 데이터세팅
					row1.appendChild(colNickname);
					
					if(mySessionId != null && data.commentDto.member_id) {
						// 삭제 버튼 생성
						const colDelete = document.createElement("div");
						colDelete.classList.add("col-1");
						colDelete.innerText = "삭제";
						colDelete.setAttribute("onclick", "deleteComment("+ data.commentDto.id +")");
						row1.appendChild(colDelete);	
						
						const colUpdate = document.createElement("div");
						colUpdate.classList.add("col-1");
						colUpdate.innerText = "수정";
						row1.appendChild(colUpdate);	
					}
					
					document.getElementById("commentListBox").appendChild(row1);
					
				}
				
			}
		}
		
		//get
		xhr.open("get", "./getCommentList?boardId=" + boardId);
		
		xhr.send();
		
		
	}
	
	
	
	function deleteComment(id) {
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText); // 사실 이 코드 여기에선 필요 x
				// js 작업..
				reloadCommentList();
			}
		}
		
		//get
		xhr.open("get", "./deleteComment?id=" + id);
		xhr.send();
	}
	

	
	
	window.addEventListener("DOMContentLoaded", function(){
		//사실상 시작 시점...
		getSessionId();
		refreshTotalLikeCount();
		refreshMyHeart();
		reloadCommentList();
	});
</script>

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">

<script>

	const boardId = new URLSearchParams(location.search).get("id");

	function ajaxTemplete(){
		
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
			}
		}
		
		//get
		xhr.open("get", "요청 url?파라메터=값");
		xhr.send();
		
		//post
		xhr.open("post", "요청 url");
		xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 
		xhr.send("파라메터=값");
	}

	let mySessionId = null;

	function getSessionId(){
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
				if(response.result == "success"){
					mySessionId = response.id; 
				}
			}
		}
		
		//get
		xhr.open("get", "../member/getMyId", false); // 딱 여기만 쓰세요...false 동기식 호출..! 권장되지 않음
		xhr.send();		
	}

	function refreshTotalLikeCount(){
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
				const totalLikeCountBox = document.getElementById("totalLikeCount");
				totalLikeCountBox.innerText = response.count;
			}
		}
		
		
		
		//get
		xhr.open("get", "./getTotalLikeCount?boardId=" + boardId);
		xhr.send();		
	}
	
	function toggleLike(){
		if(mySessionId == null){
			if(confirm("로그인을 하셔야 이용하실 수 있습니다. 로그인 하시겠습니까?")){
				location.href = "../member/loginPage";
			}
			
			return;
		}
		
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
				refreshTotalLikeCount();
				refreshMyHeart();
			}
		}
		
		//get
		xhr.open("get", "./toggleLike?board_id=" + boardId);
		xhr.send();
		
	}
	
	function refreshMyHeart(){
		
		if(mySessionId == null) return;
		
		
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 렌더링... 작업..
				const heartBox = document.getElementById("heartBox");
				
				if(response.isLiked){
					heartBox.classList.remove("bi-heart");
					heartBox.classList.add("bi-heart-fill");
				}else{
					heartBox.classList.remove("bi-heart-fill");
					heartBox.classList.add("bi-heart");
				}
			}
		}
		
		//get
		xhr.open("get", "./isLiked?board_id=" + boardId);
		xhr.send();
		
	}
	
	function registerComment(){
		
		if(!mySessionId) {
			// 로그인 안되었있으니까...
			return;
		}
		
		const commentTextBox = document.getElementById("commentTextBox");
		const commentTextValue = commentTextBox.value; 
		
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
				commentTextBox.value = "";
				reloadCommentList();
			}
		}
		
		//post
		xhr.open("post", "./registerComment");
		xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 
		xhr.send("board_id=" + boardId + "&comment_text=" + commentTextValue);
		
	}
	
	function reloadCommentList(){
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업.. 렌더링....
				
				/*
				<div class="row">
					<div class="commentBox col-8 bg-primary">내용..</div>
					<div class="col bg-secondary">닉네임..</div>
					<div class="col bg-success">삭제</div>
					<div class="col bg-warning">수정</div>
				</div>			
				*/
				
				document.getElementById("commentListBox").innerHTML = ""; //초기화 얘만 innerHTML 허용... 
				
				for(data of response.commentList){
					const row1 = document.createElement("div");
					row1.classList.add("row");
					row1.classList.add("commentOuter");
					row1.setAttribute("commentId" , data.commentDto.id);
					
					
					const colCommentBox = document.createElement("div");
					colCommentBox.classList.add("commentBox");
					colCommentBox.classList.add("col-8");
					colCommentBox.classList.add("bg-primary");
					colCommentBox.innerText = data.commentDto.comment_text; // 데이터 세팅
					row1.appendChild(colCommentBox);

					const colNickname = document.createElement("div"); 					
					colNickname.classList.add("col-2");
					colNickname.classList.add("bg-secondary");
					colNickname.innerText = data.memberDto.nickname; // 데이터 세팅
					row1.appendChild(colNickname);
					
					if(mySessionId != null && data.commentDto.member_id){
						const colDelete = document.createElement("div");
						colDelete.classList.add("col-1");
						colDelete.innerText = "삭제";
						colDelete.setAttribute("onclick", "deleteComment("+data.commentDto.id+")");
						row1.appendChild(colDelete);
						
						const colUpdate = document.createElement("div");
						colUpdate.classList.add("col-1");
						colUpdate.innerText = "수정";
						colUpdate.setAttribute("onclick", "changeInputForUpdateComment(this)");
						
						row1.appendChild(colUpdate);
					}
					
					document.getElementById("commentListBox").appendChild(row1);
				}
				
				
			}
		}
		
		//get
		xhr.open("get", "./getCommentList?boardId=" + boardId);
		xhr.send();
	}	
	
	function deleteComment(id){
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
				reloadCommentList();
			}
		}
		
		//get
		xhr.open("get", "./deleteComment?id=" + id);
		xhr.send();
		
	}
	
	
	function changeInputForUpdateComment(targetElement){
		
		const commentOuter = targetElement.closest(".commentOuter"); // 부모중에 css 접근자 문법에 맞는 엘리먼트를 가져온다.
		
		// const commentBox = commentOuter.getElementsByClassName("commentBox")[0];
		const commentBox = commentOuter.querySelector(".commentBox");
		
		const tempValue = commentBox.innerText;
		
		commentBox.innerHTML = "";
		
		const inputTextComment = document.createElement("input");
		inputTextComment.type = "text"
		//inputTextComment.classList.add("form-control");
		inputTextComment.classList.add("commentInputBox");
		inputTextComment.value = tempValue;
		commentBox.appendChild(inputTextComment);
		
		const inputButtonUpdate = document.createElement("button");
		inputButtonUpdate.innerText = "수정 적용";
		inputButtonUpdate.setAttribute("onclick" , "updateComment(this)");
		commentBox.appendChild(inputButtonUpdate);
		
		
		
		targetElement.innerText = "수정취소";
		targetElement.setAttribute("onclick", "cancelUpdate(this)");
	}
	
	function updateComment(targetElement){
		
		const commentOuter = targetElement.closest(".commentOuter");
		
		const commentId = commentOuter.getAttribute("commentId");
		const commentText = commentOuter.querySelector(".commentInputBox").value;
		
		const xhr = new XMLHttpRequest();
		
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4 && xhr.status == 200){
				const response = JSON.parse(xhr.responseText);
				// js 작업..
				reloadCommentList();
			}
		}
		
		//post
		xhr.open("post", "./updateComment");
		xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 
		xhr.send("id=" + commentId + "&comment_text=" + commentText);
				
		
	}
	
	
	function cancelUpdate(targetElement){
		// 구현....
		console.log("....")
	}
	
	
	
	
	window.addEventListener("DOMContentLoaded", function(){
		//사실상 시작 시점...
		getSessionId();
		refreshTotalLikeCount();
		refreshMyHeart();
		reloadCommentList();
		
		setInterval(reloadCommentList, 3000); // 3초마다 한번씩 reload
	});
</script>


</head>
<body>
<h1>상세 글보기</h1>

제목: ${data.boardDto.title }<br>
작성자: ${data.memberDto.nickname }<br>
작성일: ${data.boardDto.reg_date }<br>
조회수: ${data.boardDto.read_count }<br>

<br>
<c:forEach items="${data.boardImageDtoList}" var="boardImageDto">
	<img src="/uploadFiles/${boardImageDto.link }"><br>
</c:forEach>




내용: <br>
${data.boardDto.content }<br>

<i id="heartBox" onclick="toggleLike()" class="fs-1 text-danger bi bi-heart"></i><span id="totalLikeCount">3</span>

<div class="container">
	<div class="row">
		<div class="col-7">
			<textarea id="commentTextBox" class="form-control"></textarea>
		</div>
		<div class="col d-grid">
			<input onclick="registerComment()" class="btn btn-primary" type="button" value="댓글 작성">
		</div>
	</div>
	<div class="row">
		<div id="commentListBox" class="col">
			<div class="row commentOuter">
				<div class="commentBox col-8 bg-primary">내용..</div>
				<div class="col bg-secondary">닉네임..</div>
				<div class="col bg-success">삭제</div>
				<div class="col bg-warning">수정</div>
			</div>			
		</div>
	</div>
</div>




  
<br><br>
<a href="./mainPage">목록으로</a>

<c:if test="${!empty sessionUser && sessionUser.id == data.memberDto.id }">
	<a href="./updatePage?id=${data.boardDto.id }">수정</a>
	<a href="./deleteProcess?id=${data.boardDto.id }">삭제</a>
</c:if>


<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
</body>
</html>