Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] 댓글 생성 수정 삭제 프론트 작업 #79

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

import org.programmers.signalbuddy.domain.comment.entity.Comment;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

@Repository
public interface CommentRepository extends JpaRepository<Comment, Long>, CustomCommentRepository {

@Modifying
@Query("DELETE FROM comments c WHERE c.feedback.feedbackId = :feedbackId")
void deleteAllByFeedbackId(@Param("feedbackId") Long feedbackId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.time.LocalDate;
import lombok.RequiredArgsConstructor;
import org.programmers.signalbuddy.domain.comment.repository.CommentRepository;
import org.programmers.signalbuddy.domain.feedback.dto.FeedbackMapper;
import org.programmers.signalbuddy.domain.feedback.dto.FeedbackResponse;
import org.programmers.signalbuddy.domain.feedback.dto.FeedbackWriteRequest;
Expand All @@ -28,6 +29,7 @@ public class FeedbackService {
private final FeedbackRepository feedbackRepository;
private final MemberRepository memberRepository;
private final FeedbackJdbcRepository feedbackJdbcRepository;
private final CommentRepository commentRepository;

public PageResponse<FeedbackResponse> searchFeedbackList(Pageable pageable, Long answerStatus) {
Page<FeedbackResponse> responsePage = feedbackRepository.findAllByActiveMembers(pageable,
Expand Down Expand Up @@ -92,6 +94,7 @@ public void deleteFeedback(Long feedbackId, User user) {
throw new BusinessException(FeedbackErrorCode.FEEDBACK_ELIMINATOR_NOT_AUTHORIZED);
}

commentRepository.deleteAllByFeedbackId(feedbackId);
feedbackRepository.deleteById(feedbackId);
}

Expand Down
11 changes: 11 additions & 0 deletions src/main/resources/static/css/feedback/info.css
Original file line number Diff line number Diff line change
Expand Up @@ -601,4 +601,15 @@ video {

#menu-box {
display: none;
}

.hidden {
display: none;
}

.comment-edit-textarea {
width: 100%;
height: 100px;
padding: 8px;
margin-top: 8px;
}
156 changes: 150 additions & 6 deletions src/main/resources/templates/feedback/info.html
Original file line number Diff line number Diff line change
Expand Up @@ -79,26 +79,50 @@ <h2 class="text-lg font-bold text-neutral-950" th:text="${feedback.getSubject()}
<!-- 댓글 부분 -->
<section class="bg-neutral-50 rounded-lg p-4 text-sm mb-4"
th:each="comment : ${commentPage.getSearchResults()}">
<div class="flex justify-between items-center mb-1">
<div class="flex justify-between items-center mb-1"
id="comment-box"
th:attrappend="data-comment-id=${comment.getCommentId()}">
<div class="text-neutral-600"
th:text="${comment.getMember().getNickname()} + ' | ' +
${feedback.getUpdatedAt().toString().replace('T', ' ').substring(0, 16)}">
nick | 2024-12-12 16:20:45
</div>
<div class="flex gap-2">
<button
class="py-1 px-3 bg-neutral-200 text-neutral-700 rounded-md hover:bg-neutral-300">
class="py-1 px-3 bg-neutral-200 text-neutral-700 rounded-md hover:bg-neutral-300"
id="comment-edit-btn"
th:onclick="'showEditBox(' + ${comment.getCommentId()} + ')'">
수정
</button>
<button
class="py-1 px-3 bg-neutral-200 text-neutral-700 rounded-md hover:bg-neutral-300">
class="py-1 px-3 bg-neutral-200 text-neutral-700 rounded-md hover:bg-neutral-300"
id="comment-delete-btn"
th:onclick="'deleteComment(' + ${comment.getCommentId()} + ')'">
삭제
</button>
</div>
</div>
<p class="text-neutral-900 break-words" th:text="${comment.getContent()}">

<!-- 댓글 내용이 p로 표시되지만, 수정 버튼을 클릭하면 textarea로 바뀐다. -->
<p class="text-neutral-900 break-words"
th:id="'comment-content-' + ${comment.getCommentId()}"
th:text="${comment.getContent()}">
이건인정;;;;;;;;;;;;;;;;;;;;;;;;
</p>
<!-- 댓글 수정 textarea (초기에는 숨겨짐) -->
<textarea class="hidden comment-edit-textarea"
th:id="'comment-edit-textarea-' + ${comment.getCommentId()}"
th:text="${comment.getContent()}"></textarea>
<button class="hidden py-1 px-4 bg-primary-500 text-primary-50 rounded-md hover:bg-primary-600"
th:id="'comment-edit-cancel-btn-' + ${comment.getCommentId()}"
th:onclick="'hideEditBox(' + ${comment.getCommentId()} + ')'">
수정 취소
</button>
<button class="hidden py-1 px-4 bg-primary-500 text-primary-50 rounded-md hover:bg-primary-600"
th:id="'comment-edit-complete-btn-' + ${comment.getCommentId()}"
th:onclick="'editComment(' + ${comment.getCommentId()} + ')'">
수정 완료
</button>
</section>

<!-- 댓글 작성 부분 -->
Expand All @@ -109,9 +133,11 @@ <h2 class="text-lg font-bold text-neutral-950" th:text="${feedback.getSubject()}
<textarea
class="w-full h-[100px] bg-neutral-50 rounded-md p-2 border border-neutral-300 focus:outline-none focus:ring-2 focus:ring-primary-500"
placeholder="댓글을 입력하세요."
id="comment-write-box"
></textarea>
<div class="text-right mt-2">
<button class="py-1 px-4 bg-primary-500 text-primary-50 rounded-md hover:bg-primary-600">
<button class="py-1 px-4 bg-primary-500 text-primary-50 rounded-md hover:bg-primary-600"
id="comment-write-btn">
등록
</button>
</div>
Expand All @@ -125,6 +151,10 @@ <h2 class="text-lg font-bold text-neutral-950" th:text="${feedback.getSubject()}
const menuBtn = document.getElementById("feedback-menu-btn");
const menu = document.getElementById("menu-box");
const deleteBtn = document.getElementById("delete-btn");
const commentBox = document.getElementById("comment-box");
const commentWriteBtn = document.getElementById("comment-write-btn");
const commentDeleteBtn = document.getElementById("comment-delete-btn");
const commentEditeBtn = document.getElementById("comment-edit-complete-btn");

menuBtn.addEventListener("click", (event) => {
event.stopPropagation();
Expand All @@ -144,7 +174,7 @@ <h2 class="text-lg font-bold text-neutral-950" th:text="${feedback.getSubject()}
event.stopPropagation();
});

// 삭제 요청
// 피드백 삭제 요청
deleteBtn.addEventListener("click", (event) => {
const feedbackId = menu.getAttribute('data-feedback-id');

Expand All @@ -167,4 +197,118 @@ <h2 class="text-lg font-bold text-neutral-950" th:text="${feedback.getSubject()}
console.error('삭제 요청 중 오류 발생:', error);
});
});

// 댓글 작성 요청
commentWriteBtn.addEventListener("click", (event) => {
const feedbackId = menu.getAttribute('data-feedback-id');
const comment = document.getElementById("comment-write-box").value;

fetch(`/api/comments/write`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'feedbackId': feedbackId,
'content': comment
})
})
.then(response => {
if (response.ok) {
window.location.href = location.href; // 페이지 새로고침
} else {
alert('댓글 작성에 실패했습니다.');
response.json()
.then(data => console.log(data.message));
}
})
.catch(error => {
console.error('댓글 작성 요청 중 오류 발생:', error);
});
});

// 댓글 삭제 요청
function deleteComment(commentId) {
fetch(`/api/comments/${commentId}`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json'
}
})
.then(response => {
if (response.ok) {
window.location.href = location.href; // 페이지 새로고침
} else {
alert('삭제에 실패했습니다.');
response.json()
.then(data => console.log(data.message));
}
})
.catch(error => {
console.error('삭제 요청 중 오류 발생:', error);
});
}

// 댓글 수정 박스 보이게 하기
function showEditBox(commentId) {
const commentContent = document.getElementById('comment-content-' + commentId);
const commentTextarea = document.getElementById('comment-edit-textarea-' + commentId);
const cancelButton = document.getElementById('comment-edit-cancel-btn-' + commentId);
const completeButton = document.getElementById('comment-edit-complete-btn-' + commentId);

// 댓글을 textarea로 변환
commentContent.classList.add('hidden'); // 기존 댓글 텍스트 숨기기
commentTextarea.classList.remove('hidden'); // textarea 보이기
cancelButton.classList.remove('hidden'); // 취소 버튼 보이기
completeButton.classList.remove('hidden'); // 완료 버튼 보이기
}

// 댓글 수정 박스 숨기기
function hideEditBox(commentId) {
const commentContent = document.getElementById('comment-content-' + commentId);
const commentTextarea = document.getElementById('comment-edit-textarea-' + commentId);
const cancelButton = document.getElementById('comment-edit-cancel-btn-' + commentId);
const completeButton = document.getElementById('comment-edit-complete-btn-' + commentId);

// 댓글을 p로 변환
commentContent.classList.remove('hidden'); // 기존 댓글 텍스트 보이기
commentTextarea.classList.add('hidden'); // textarea 숨기기
cancelButton.classList.add('hidden'); // 취소 버튼 숨기기
completeButton.classList.add('hidden'); // 완료 버튼 숨기기
}

// 댓글 수정 요청
function editComment(commentId) {
const feedbackId = menu.getAttribute('data-feedback-id');
const commentEditBox = document.getElementById('comment-edit-textarea-' + commentId);
const commentContent = document.getElementById('comment-content-' + commentId);

const updatedComment = commentEditBox.value;

fetch(`/api/comments/${commentId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'feedbackId': feedbackId,
'content': updatedComment
})
})
.then(response => {
if (response.ok) {
// 서버 응답 후 댓글 내용 업데이트
commentContent.innerText = updatedComment;

hideEditBox(commentId);
} else {
alert('댓글 수정에 실패했습니다.');
response.json()
.then(data => console.log(data.message));
}
})
.catch(error => {
console.error('댓글 수정 요청 중 오류 발생:', error);
});
}
</script>
Loading