제품 상세보기에 댓글을 달고 관리자 계정으로 대댓글을 달아보자.
먼저 제품 댓글 데이터를 담을 shopanswer 테이블을 만들어준다.
create table shopanswer(idx smallint auto_increment primary key,
shopnum smallint,
myid varchar(30),
content varchar(1000),
shopanswer varchar(1000) default 'no',
writeday date,
foreign key(shopnum) references shop(shopnum) on delete cascade);
idx: 시퀀스
shopnum: shop의 외부키
myid: 댓글 단 아이디
content: 댓글 내용
shopanswer: 관리자 대댓글 (insert 할 때 NULL값으로 들어가지 않게 default 값으로 'no'를 줬다.)
writeday: 댓글 단 날짜
이제 Dto를 만들어주고, ShopAnswerDao.java에 insert를 만들어준다.
//insert
public void insertAnswer(ShopAnswerDto dto) {
Connection conn = db.getConnection();
PreparedStatement pstmt= null;
String sql = "insert into shopanswer (shopnum, myid, content, writeday) values (?,?,?,now()) ";
try {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, dto.getShopnum());
pstmt.setString(2, dto.getMyid());
pstmt.setString(3, dto.getContent());
pstmt.execute();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
db.dbClose(pstmt, conn);
}
}
<!-- 상품 댓글 -->
<%
if(loginok!=null){%>
<div id="answer">
<form id="answerfrm">
<input type="hidden" name="shopnum" id="shopnum" value=<%=dto.getShopnum()%>>
<input type="hidden" name="myid" id="myid" value="<%=myid%>">
<textarea class="form-control" name="content" id="content"></textarea>
<button type="button" id="addanswer" class="btn btn-success">추가</button>
</form>
</div>
<%}
%>
사이트에 로그인한 사람만 댓글 작성 칸을 볼 수 있도록 loginok!=null 조건을 줘야 한다.
그리고 상품 댓글을 작성할 수 있는 form을 만들 때 hidden으로 상품번호(shopnum), 로그인된 아이디(myid)를 넣어줘야 한다.
<input type="hidden" name="shopnum" id="shopnum" value=<%=dto.getShopnum()%>>
<input type="hidden" name="myid" id="myid" value="<%=myid%>">
이제 댓글창에 댓글을 입력하고 '추가'를 누르면 댓글이 DB에 추가되게 하자.
$("#addanswer").click(function(){
var myid=$("#myid").val();
var shopnum = $("#shopnum").val();
var content = $("#content").val();
console.log(myid,shopnum,content);
댓글창에서 추가를 눌렀을 때 myid, shopnum, content가 넘어오는지 확인해보자. 넘어오는걸 확인했으면 insert하기 위한 jsp를 만들어준다.
<%
request.setCharacterEncoding("utf-8");
String shopnum = request.getParameter("shopnum");
String myid = request.getParameter("myid");
String content = request.getParameter("content");
ShopAnswerDto dto = new ShopAnswerDto();
dto.setShopnum(shopnum);
dto.setMyid(myid);
dto.setContent(content);
ShopAnswerDao dao = new ShopAnswerDao();
dao.insertAnswer(dto);
%>
shopnum, myid, content를 넘겨서 ShopAnswerDto에 담고 dao로 insertAnswer을 호출한다.
$(function(){
//디테일 페이지 출력시 기존 댓글도 출력
answerlist();
//추가 버튼 누르면 댓글 추가
//ajax 함수로 처리(readanswer.jsp로 myid, shopnum, content 3개 보내서 해당 jsp에서 db에 인서트)
//shopnum,myid 넘어오는지 확인
$("#addanswer").click(function(){
var myid=$("#myid").val();
var shopnum = $("#shopnum").val();
var content = $("#content").val();
console.log(myid,shopnum,content);
$.ajax({
type:"post",
dataType:"html",
url:"shop/readanswer.jsp",
data:{"myid":myid,"shopnum":shopnum, "content":content},
success:function(){
//기존입력값 지우기
$("#content").val("");
alert("success");
answerlist();
}, statutsCode:{
404:function(){
alert("파일을 찾을 수 없습니다.");
},500:function(){
alert("서버오류, 오타");
}
}
});
});
ajax로 readanswer을 불러오면 DB 추가를 할 수 있다!!
이제 추가한 댓글들을 상세보기 화면에서 보이게 해보자.
<div id="answerlist">
댓글 목록
</div>
간단하게 목록을 보여줄 div를 만들어준다.
댓글 목록은 뭘 클릭해서 나오는게 아니고 상세보기 눌렀을 때 바로 나오는 거니까 사용자함수를 만들어준 후 위에 스크립트에서 함수를 호출해주면 바로 댓글 목록을 볼 수 있다.
ShopAnswerDao.java에서 list 메서드를 만들어준다.
//list
public List<ShopAnswerDto> getAllAnswerlist(String shopnum) {
List<ShopAnswerDto> list = new Vector<>();
Connection conn = db.getConnection();
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = "select * from shopanswer where shopnum=? order by shopnum desc"; //최신글이 맨 위로 올라오도록 desc로 설정
try {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, shopnum);
rs = pstmt.executeQuery();
while(rs.next()) {
ShopAnswerDto dto = new ShopAnswerDto();
dto.setIdx(rs.getString("idx"));
dto.setShopnum(rs.getString("shopnum"));
dto.setMyid(rs.getString("myid"));
dto.setContent(rs.getString("content"));
dto.setShopanswer(rs.getString("shopanswer"));
dto.setWriteday(rs.getTimestamp("writeday"));
//리스트에 추가
list.add(dto);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
db.dbClose(rs, pstmt, conn);
}
return list;
}
전체출력 메서드를 만들어줬으니 dao를 처리하는 JSON 파일을 만들어줘야 한다.
<%@page import="org.json.simple.JSONObject"%>
<%@page import="data.dao.MemberDao"%>
<%@page import="org.json.simple.JSONArray"%>
<%@page import="java.text.SimpleDateFormat"%>
<%@page import="data.dto.ShopAnswerDto"%>
<%@page import="java.util.List"%>
<%@page import="data.dao.ShopAnswerDao"%>
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%
String shopnum = request.getParameter("shopnum");
ShopAnswerDao dao = new ShopAnswerDao();
List<ShopAnswerDto> list = dao.getAllAnswerlist(shopnum);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
//member에서 id를 통해 이름도 가져오기
MemberDao mdao = new MemberDao();
JSONArray arr = new JSONArray();
for(ShopAnswerDto dto:list){
JSONObject ob = new JSONObject();
ob.put("idx",dto.getIdx());
ob.put("myid", dto.getMyid());
ob.put("name", mdao.getName(dto.getMyid()));
ob.put("content", dto.getContent());
ob.put("shopanswer", dto.getShopanswer());
ob.put("writeday", sdf.format(dto.getWriteday()));
arr.add(ob);
}
%>
<%=arr.toString()%>
shopnum에 따른 댓글 리스트니까 shopnum을 읽어와야 한다. 그리고 dao를 통해 getAllAnswerList(shopnum)을 불러오고 JSON을 반환하기 위한 JSONArray를 만들어준다.
function answerlist(){
var loginid = $("#myid").val(); //로그인 한 아이디
var shopnum = $("#shopnum").val(); //현재 상품 번호
$.ajax({
type:"get",
url:"shop/answerlist.jsp",
data:{"shopnum":shopnum},
dataType:"json",
success:function(res){
//출력할 변수
var s = "";
$.each(res,function(i,ele){
s+="<b>"+ele.name+"</b>";
//삭제 표시는 본인만 보이게
var myid = ele.myid;
if(loginid==myid){
s+="<span class='adel glyphicon glyphicon-trash' idx='"+ele.idx+"'></span>";
}
//날짜
s+="<span class='aday'>"+ele.writeday+"</span>";
//내용
s+="<pre class='acontent'>"+ele.content+"</pre>";
});
$("#answerlist").html(s);
}
});
}
//삭제 표시는 본인만 보이게
var myid = ele.myid;
if(loginid==myid){
s+="<span class='adel glyphicon glyphicon-trash' idx='"+ele.idx+"'></span>";
}
var loginid는 로그인 세션에 저장된 myid 값이다, 즉 로그인 된 아이디.
var myid=ele.myid는 JSON에서 key 값으로 넘긴 myid 값이다.
loginid와 myid가 일치한다는 것은 현재 로그인 된 아이디와 댓글을 작성했던 아이디가 일치한다는 것으로, 댓글 작성자의 화면에만 쓰레기통 모양이 보이도록 했다.
이제 댓글 list 출력까지 했으니 쓰레기통 모양을 눌렀을 때 삭제가 되도록 해보자
//삭제
public void deleteShopAnswer(String idx) {
Connection conn = db.getConnection();
PreparedStatement pstmt = null;
String sql= "delete from shopanswer where idx=?";
try {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, idx);
pstmt.execute();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
db.dbClose(pstmt, conn);
}
}
<span class='adel glyphicon glyphicon-trash' idx='"+ele.idx+"'></span>
아까 댓글을 출력할 때 로그인 아이디=댓글 작성 아이디인 경우 쓰레기통 글리파이콘을 보이게 하면서 adel이라는 class를 넣어주고, idx 값을 넣어주었다.
//삭제
$(document).on("click","span.adel",function(){
var idx = $(this).attr("idx");
console.log(idx);
쓰레기통을 클릭했을 때 idx 값이 잘 넘어오는지 확인을 해주고 delete를 처리할 jsp를 만들어준다.
<%
String idx = request.getParameter("idx");
ShopAnswerDao sdao = new ShopAnswerDao();
sdao.deleteShopAnswer(idx);
%>
idx 값을 넘겨서 idx에 해당하는 댓글을 삭제시켜준다.
//삭제
$(document).on("click","span.adel",function(){
var idx = $(this).attr("idx");
console.log(idx);
var a = confirm("삭제하시겠습니까?");
if(!a){
return;
}
//삭제
$.ajax({
type:"get",
url:"shop/answerdelete.jsp",
data:{"idx":idx},
dataType:"html",
success:function(){
answerlist();
}
});
});
이제 admin으로 들어갔을 때 댓글에 대댓글을 달고, 사용자들이 확인할 수 있게 해보자.
먼저 상품 댓글에 관리자가 대댓글을 달 수 있는 대댓글 창을 만들어줘야 하는데
관리자 계정으로 들어갔을 때 '답글달기'를 눌러서 대댓글 창을 볼 수 있어야 하면서,
관리자 계정이 아닌 경우 '답글달기'가 보이면 안되면서,
이미 관리자가 단 대댓글이 있는 경우 관리자의 대댓글을 함께 출력해줘야 한다.
function answerlist(){
var loginid = $("#myid").val(); //로그인 한 아이디
var shopnum = $("#shopnum").val(); //현재 상품 번호
$.ajax({
type:"get",
url:"shop/answerlist.jsp",
data:{"shopnum":shopnum},
dataType:"json",
success:function(res){
//출력할 변수
var s = "";
$.each(res,function(i,ele){
s+="<b>"+ele.name+"</b>";
//삭제 표시는 본인만 보이게
var myid = ele.myid;
if(loginid==myid){
s+="<span class='adel glyphicon glyphicon-trash' idx='"+ele.idx+"'></span>";
}
//날짜
s+="<span class='aday'>"+ele.writeday+"</span>";
//내용
s+="<pre class='acontent'>"+ele.content+"</pre>";
//관리자 답글
var answer = ele.shopanswer;
//현재는 디폴트값 no만 들어가있음
if(loginid=="admin" && answer=="no"){
s+="<span class='abtn' idx='"+ele.idx+"'>답글달기</span><br>";
}else if(loginid!="admin" && answer=="no"){
s+="";
}else{
s+="<pre class='aanswer'>[관리자]<br>"+answer+"</pre>";
}
s+="<hr>";
});
$("#answerlist").html(s);
}
});
}
//관리자 답글
var answer = ele.shopanswer;
//현재는 디폴트값 no만 들어가있음
if(loginid=="admin" && answer=="no"){
s+="<span class='abtn' idx='"+ele.idx+"'>답글달기</span><br>";
}else if(loginid!="admin" && answer=="no"){
s+="";
}else{
s+="<pre class='aanswer'>[관리자]<br>"+answer+"</pre>";
}
s+="<hr>";
사용자 함수의 answerlist( )에서 관리자 대댓글이 나오게 해주면 된다.
처음 사용자가 댓글을 작성할 때 관리자 대댓글(shopanswer)은 NULL값이 되지 않도록 default='no'를 넣어줬기 때문에 ele.shopanswer의 값이 'no'라면 관리자 댓글이 달리지 않은 것이다.
따라서 로그인 아이디가 admin이고 answer 값이 no라면 admin이 대댓글을 달 수 있도록 '답글달기' span이 뜬다.
로그인 아이디가 admin이 아니라 다른 아이디, 즉 사용자 아이디면서 answer이 no로 되어있으면(=관리자 대댓글이 아직 없는 상태) 다른 사용자가 댓글창을 보고 있는 것이기 때문에 '답글달기' 표시도, 관리자의 대댓글값(no)도 나오면 안되기 때문에 공백을 준다.
그 외의 경우, 로그인 아이디가 admin이 아니면서 answer이 no도 아닌 경우에는 사용자가 로그인 한 상태에서 관리자의 대댓글을 볼 수 있어야 하기 때문에 [관리자] 이름과 함께 answer 댓글 값이 들어가면 된다.
조건에 따른 코드를 작성해놓았으니, '답글달기'가 떴을 때 입력창이 나오게 하고 작성한 대댓글을 insert 해주자.
//답글 달기
$(document).on("click","span.abtn",function(){
var idx = $(this).attr("idx");
console.log("idx");
var tag = "<div class='shoptag'>";
tag +="<textarea class='form-control acontent' id='acontent'></textarea>";
tag +="<button class='shopsave btn btn-danger btn-xs' idx='"+idx+"'>저장</button>";
$(this).after(tag); //답글 달기 바로 아래에 추가하기
$(this).hide(); // '답글 달기' 버튼 안보이게
});
'답글달기'를 눌렀을 때 사용자가 달아놓은 댓글의 idx값이 잘 넘어오는지 확인한다.
var tag에 div를 주고 textarea와 idx값이 담긴 저장 버튼을 추가한다.
$(this).after(tag);는 $(this), 즉 '답글달기' 바로 아래에 tag를 넣는다는 의미이다.
'답글달기' 바로 아래에 tag가 실행되면(=입력창이 뜨면) $(this).hide()로 '답글달기'를 숨겨준다.
이제 admin이 대댓글을 입력하고 '저장' 버튼을 눌렀을 때 shopanswer 테이블의 shopanswer에 대댓글 내용이 들어가게 해보자.
처음에 shopanswer 테이블을 만들 때 댓글은 content로, 관리자 대댓글은 shopanswer로 넣으면서 shopanswer이 null값이 되지 않으려고(사용자가 댓글 입력할 때 관리자 대댓글은 없는 상황이니까) default 값으로 'no'를 넣어놨기 때문에, 대댓글은 insert가 아니라 update를 해줘야 한다.
//샵 관리자 댓글, 이미 answer에 no값이 들어가 있으니까 update
public void updateShopAnswer(String idx, String answer) {
Connection conn = db.getConnection();
PreparedStatement pstmt = null;
String sql = "update shopanswer set shopanswer=? where idx=?";
try {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, answer);
pstmt.setString(2, idx);
pstmt.execute();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
db.dbClose(pstmt, conn);
}
}
사용자 댓글 idx에 해당하는 shopanswer의 값을 update해주는 sql문을 작성했다.
이제 이걸 처리해줄 jsp를 만들어준다.
<%
request.setCharacterEncoding("utf-8");
String idx = request.getParameter("idx");
String acontent = request.getParameter("acontent");
ShopAnswerDao sdao = new ShopAnswerDao();
sdao.updateShopAnswer(idx, acontent);
%>
//관리자 댓글 저장하기
$(document).on("click","button.shopsave",function(){
var idx = $(this).attr("idx");
console.log(idx);
//var acontent = $(this).prev('.acontent').val(); //id='acontent'를 안줬을 때
var acontent = $("#acontent").val();
if(acontent.legth==0){
alert("답글을 입력하세요");
return;
}else{
$.ajax({
type:"post",
url:"shop/answerupdate.jsp",
data:{"idx":idx,"acontent":acontent},
dataType:"html",
success:function(){
answerlist();
}
});
}
});
대댓글을 작성하고 나면
이렇게 shopanswer 테이블의 shopanswer에 대댓글이 잘 들어간 것을 볼 수 있따!!