코디잉

21_공동구매 게시물 상세보기 ② 댓글(목록, 등록, 수정, 삭제, 고정) 본문

PROJECT/같이사자(공동구매)

21_공동구매 게시물 상세보기 ② 댓글(목록, 등록, 수정, 삭제, 고정)

yong_ღ'ᴗ'ღ 2022. 9. 6. 01:55

① 공동구매에 관련된 정보들 가져오기

② 참여자목록 (참여자들 프로필사진 및 닉네임)

③ 댓글(등록, 수정, 삭제, 고정 처리)

④ 신고팝업, 신고처리(게시물, 댓글)

⑤ 찜(♡) 

⑥ 버튼 관련

 

댓글 관련 작업 ㄱㄱ!


③ 댓글(목록, 등록, 수정, 삭제, 고정 처리)

 

③-1) 댓글 목록

- 댓글은 모든 회원이 등록할 수 있다.

- 댓글 고정은 해당 공동구매의 진행자만 본인의 댓글 1개를 제일 상단으로 고정시키는 기능으로,

  자신의 댓글을 고정 혹은 고정해제를 할 수 있다.

- 본인이 쓴 댓글은 수정 / 삭제가 가능하고, 타회원이 쓴 댓글은 신고할 수 있다.

 

그래서 회원이 해당 공동구매의 진행자인지, 참여자인지를 구분해야 한다.

세션에 있는 멤버코드와 댓글의 멤버코드, 공동구매 작성자 멤버코드를 비교했다.

 

1) 본인의 댓글이라면,

    1-1) 진행자라면,

        1-1-1) 고정한 댓글 → 고정취소/수정/삭제

        1-1-2) 고정하지 않은 댓글 → 고정/수정/삭제

    1-2) 진행자아닌 다른 회원 → 수정/삭제

2) 본인 댓글 아니라면, → 신고                                         기능을 할 수 있어야 한다.

 

위의 분기 내용을 코드로 작성한 것이다.

<c:forEach var="reply" items="${replyList }">
    <div class="d-flex mb-4 reply-box">
        <div class="buypost_profile_photo reply-profile-photo">
            <img src="img/mannerLevel/${reply.photo_name }" />
        </div>
        <div class="reply">
            <!-- 닉네임 -->
            <c:choose>
                <%-- 진행자 --%>
                <c:when test="${reply.member_code == buypost.member_code }">
                    <span class="pin-nickname">${reply.nickname }</span>
                    <c:if test="${not empty reply.reply_fix }">
                        <i class="bi bi-pin-fill"></i>
                    </c:if>
                </c:when>
                <%-- 그 외 --%>
                <c:otherwise>
                    ${reply.nickname }
                </c:otherwise>
            </c:choose>

            <!-- 댓글 기능 -->
            <div class="fw-bold reply-nickname">
                <c:choose>	
                    <%-- ① 진행자 --%>
                    <c:when test="${member_code == buypost.member_code && member_code == reply.member_code}">
                        <c:choose>
                            <%-- 1) 고정 댓글 --%>
                            <c:when test="${not empty reply.reply_fix }">
                                <div class="reply-control">
                                    <a class="reply-pin-cancel" href="#!">고정취소</a> | <a
                                        class="reply-update" href="#!">수정</a> | <a 
                                        class="reply-delete" href="#!">삭제</a>
                                </div>
                            </c:when>
                            <%-- 2) 고정하지 않은 댓글 --%>
                            <c:otherwise>
                                <div class="reply-control">
                                    <a class="reply-pin-cancel" href="#!">고정하기</a> | <a
                                        class="reply-update" href="#!">수정</a> | <a 
                                        class="reply-delete" href="#!">삭제</a>
                                </div>													
                            </c:otherwise>	
                        </c:choose>										
                    </c:when>

                    <%-- ② 진행자 외 타회원 --%>
                    <c:otherwise>
                        <c:choose>
                            <%-- 1) 본인 댓글 --%>
                            <c:when test="${member_code == reply.member_code }">
                                <div class="reply-control">
                                    <a class="reply-update" href="#!">수정</a> | <a class="reply-delete" href="#!">삭제</a>
                                </div>												
                            </c:when>
                            <%-- 2) 타회원 댓글 --%>
                            <c:otherwise>
                                <div class="reply-control">
                                    <a class="report reply-report" href="javascript:report()">신고</a>
                                </div>												
                            </c:otherwise>
                        </c:choose>
                    </c:otherwise>
                </c:choose>
            </div>

            <!-- 댓글내용 -->
            <div class="reply-content-box">
                <span class="reply-text">${reply.content }</span> 
            </div>
        </div>
    </div>
</c:forEach>

🔥 jsp 변수(여기서는 세션에 저장해놓은 멤버코드) 를 jstl 태그 안에서 그냥 ${member_code} 하면 불러와짐!

 

진행자의 닉네임은 다른 색으로 표시되게 했고, 진행자의 고정댓글에는 닉네임 옆에 핀셋 표시를 했다.

코드 처리를 마친 딸기 공동구매 게시물의 댓글 목록을 보면,

 

1) 진행자 화면 (닉네임: berry)

본인 댓글 중 고정해놓은 댓글에는 고정취소/수정/삭제 처리가 가능하고,

고정하지 않은 댓글은 고정하기/수정/삭제 처리가 가능하게 되어있다.

그리고 타회원의 댓글은 신고할 수 있도록 되어있다. 

 

2) 작성한 댓글이 있는 회원의 화면 (닉네임: 용짱)

본인의 댓글은 수정/삭제할 수 있고, 타회원 댓글은 신고할 수 있게 되어있다.

3) 댓글달지 않은 회원 혹은 비회원

 

③-2) 댓글 등록

댓글 <등록> 버튼을 눌렀을 때, 댓글 내용이 없거나, 공백만 있다면 메세지를 띄우기 위한 JS코드

정상적으로 댓글 입력했으면 폼을 제출한다.

// 댓글 등록
$('.reply-btn').click(function()
{
    $('#replyErrMsg').css('display', 'none');

    let content = $.trim($('.reply-insert-form').val());
    if (content == '')
        $('#replyErrMsg').css('display', 'block');
    else
        $('#replyInsertForm').submit();
});

 

컨트롤러에서는 insert 쿼리 실행 후, 공동구매 게시물을 다시 불러주면서 !공동구매코드를 같이 넘겨준다!

IBuypostDAO dao = sqlSession.getMapper(IBuypostDAO.class);
dao.insertReply(reply);
return "redirect:buypostarticle.lion?code=" + reply.getBuypost_code();

 

비회원은 댓글을 달 수 없으므로, 비회원이 댓글을 등록하려고 하면 로그인폼으로 이동시키고 안내팝업을 띄워준다.

댓글 내용이 없거나, 공백만 있다면 '내용을 입력해주세요'라는 메세지를 띄워준다.

정상적으로 댓글을 달면, 댓글이 등록된 걸 확인할 수 있다.

 

③-3) 댓글 수정

🔥 <a> 태그 눌러도 새로고침 안되게 하기 → href="javascript:return false;" 

🔥 <a> 태그에 value값 주기 → data-value 속성 사용하면된다. jquery 로 값 불러올 때는

     『data-』는 떼고 뒤에 붙인 이름으로 값 가져오면 된다.

--html 코드
<a class="reply-update" href="javascript:return false;" data-value="${reply.code }">수정</a>

--jquery 코드
let id = $(this).data('value');

🔥 jquery 자식 요소 선택하기 → children()

$('.reply').children('.reply-content-update-box').css("display", "block");

🔥 jquery 자손 요소 선택하기 → find()

$('.reply').find('.reply-control').css("display", "none");

<수정> 부분에서 작성한 스크립트 코드는

- 해당 댓글의 [수정]을 클릭하면, 해당 댓글의 수정폼 보여주기

- 수정도 등록과 똑같이 공란이거나 공백만 있다면, 에러메세지를 띄워주기

// <수정>: 댓글 수정폼 뜨게
$(".reply-update").click(function()
{
    // 댓글 에러 메세지 안보이게
    $('#replyErrMsg').css('display', 'none');
    // 댓글 수정폼 안뜨게
    $(".reply-content-box").css("display", "block");
    $('.reply-control').css("display", "block");
    $(".reply-content-update-box").css("display", "none");

    let id = $(this).data('value');
    $('#'+id).children('.reply-content-box').css("display", "none");
    $('#'+id).find('.reply-control').css("display", "none");
    $('#'+id).children('.reply-content-update-box').css("display", "block");
});
// <수정>: form 제출
$(".reply-updateBtn").click(function()
{
    let id = $(this).val();
    let updateContent = $.trim($('#'+id).find('.reply-update-form').val());
    if (updateContent == "" || updateContent == '' || updateContent == null)
        $('#'+id).find('#replyUpdateErrMsg').css('display', 'block');
    else
        $('#'+id).find('#replyUpdateForm').submit();
});

 

수정폼에서 UPDATE 쿼리문에 필요한 해당 댓글코드와 redirect할 때 필요한 공동구매 코드는 hidden type으로 넘겨줬다.

<div class="reply-content-update-box">
    <form class="mb-4" id="replyUpdateForm" action="<%=cp%>/updatebuypostreply.lion">
        <textarea name="content" class="form-control reply-form reply-update-form" rows="3"
            placeholder="댓글을 입력해주세요." >${reply.content }</textarea>
        <button type="button" class="primary-btn reply-btn reply-updateBtn" value="${reply.code }">수정</button>
        <div class="errMsg" id="replyUpdateErrMsg">내용을 입력해주세요.</div>
        <input type="hidden" name="code" value="${reply.code }"/>
        <input type="hidden" name="buypost_code" value="${buypost.code }"/>
    </form>
</div>

 

컨트롤러에서는 INSERT 때와 동일하게 UPDATE 쿼리 실행 후, hidden 값으로 넘겨줘서 받은 공동구매 코드를 사용해서 

공동구매게시물로 redirect 시켜주었다.

IBuypostDAO dao = sqlSession.getMapper(IBuypostDAO.class);
dao.updateReply(reply);
return "redirect:buypostarticle.lion?code=" + reply.getBuypost_code();

 

 

세션에 멤버코드값이 없다면(로그아웃상태 or 비회원), <수정>버튼을 눌렀을 때, 로그인폼으로 안내해주며 로그인 후 사용가능하다는 안내 팝업을 띄워주는건 <등록> 때와 동일하다.

 

[수정 | 삭제] 버튼 위치!

본인 댓글 옆 [수정]을 클릭했을 때 나오는 수정폼이다. 본인이 썼던 내용이 입력되어 있다.

입력 댓글 내용이 없거나, 공백만 있다면 '내용을 입력해주세요'라는 메세지를 띄워준다.

정상적으로 댓글을 수정한 뒤, <수정> 버튼을 클릭했을 때 결과!!

 

 

③-4) 댓글 삭제

DELETE 쿼리에서는 댓글 코드가 필요하고, redirect 해주기 위해서 공동구매 코드가 필요하니 이번에는 주소값으로 그냥 넘겨주는 방식으로 ㄱㄱ!

이미 공동구매 상세보기 페이지 주소값에는 공동구매 코드가 있으므로 그거 가져오고, 댓글코드는 수정에서 했던것처럼 <a>태그의  data-value로 ${reply.code}를 넣어놓은 걸 가져왔다.

<!-- HTML 코드 -->
<a class="reply-delete" href="javascript:return false;" data-value="${reply.code }">삭제</a>
// jQuery 코드
$('.reply-delete').click(function()
{
    let buypost_code = '<%=request.getParameter("code")%>';
    let reply_code = $(this).data('value');

    location.href = 'deletebuypostreply.lion?buypost=' + buypost_code + "&reply=" + reply_code;
});

 

이번에 삭제할 체크!

삭제 버튼을 누르면 정상적으로 삭제된 걸 확인할 수 있다.

 

③-5) 댓글 고정 / 고정취소

댓글에서 마지막,,! 공동구매 진행자가 본인의 댓글을 댓글 목록 최상단으로 고정하기 혹은 고정된 댓글을 고정해제 하는 것이다.

이미 고정된 댓글이 있는데, 본인의 다른 댓글에서 <고정하기>를 누르면, 원래 고정되어 있던 댓글은 고정해제되고, 해당 댓글이 최상단으로 고정되게 처리할 예정!

 

.......

ㅎ...고정하려다 갑자기 목록부터 고치느라 오래걸렸다....

현재 ERD 구성은 댓글테이블 - 댓글고정테이블이 따로 있는 상태이다.

댓글테이블에 고정여부에 관한 컬럼을 놔두면 고정할 때마다 계속 업데이트를 시켜줘야 하니까, 따로 고정 로그를 기록하는 테이블을 생성했다.

그런데 테이블 이렇게 짜놓은거 생각안하고 위에서 댓글 목록 가져올 때 고정여부컬럼을 사용한 것처럼 쿼리를 짜서 수정했다..! 

 

뭔가 쿼리 지저분한 거 같기는 한데,,일단,,!

고정된 걸 상단에 띄워주고 UNION ALL 나머지 목록들 띄우는 방식으로 쿼리를 작성했다.

--댓글 목록 재작성
SELECT *
FROM VIEW_REPLYLIST
WHERE REPLY_FIX = (SELECT MAX(REPLY_FIX) FROM VIEW_REPLYLIST WHERE BUYPOST_CODE = 'BP256')
UNION ALL
SELECT *
FROM VIEW_REPLYLIST
WHERE BUYPOST_CODE = 'BP256'
  AND (NOT REPLY_FIX IN (SELECT MAX(REPLY_FIX) FROM VIEW_REPLYLIST WHERE BUYPOST_CODE = 'BP256')
        OR REPLY_FIX IS NULL)

 

댓글 <고정하기> 를 누르면, 주소값으로 댓글코드와 공동구매코드를 넘겨주었다.

<a class="reply-pin-cancel" href="fixbuypostreply.lion?buypost=${reply.buypost_code}&reply=${reply.code}">고정하기</a>

 

그럼 진행자의 다른 댓글에 <고정하기>를 눌러보자

고정해제 댓글은 썼던 시간 순서대로 목록에 자리잡고, 고정댓글은 최상단으로 가야한다.

새로 댓글 고정 후 화면이다.

 

 

고럼 이제 마지막 <고정취소>

방금 고정해놓은 댓글 <고정취소> 할 경우, 아무것도 고정된 댓글 없이 그냥 작성시간 순서로 목록이 뜨면 된다.

 

고정할 때마다 댓글고정테이블에 insert 시켜주고, 고정할 댓글을 가져올 때 해당 고정테이블 시퀀스의 가장 큰 값을 가져오도록 쿼리를 작성해놨기 때문에

<고정취소>를 눌렀을 때 해당 컬럼만 제거해주면 그 전에 고정했던 댓글이 목록에 고정될 것이다.

그래서 해당 공동구매 고정테이블 기록을 다 지우도록 쿼리를 작성했다.

 

그래서 공동구매 코드만 주소로 넘겨주었다.

고정취소한 결과화면이다!

 

댓글,,, 끄읕,..........!!

 

Comments