좋아요, 추천 기능을 구현할 수 있다.
‘추천’ 기능을 구현하려면 질문이나 답변을 추천한 사용자(SiteUser)가 DB에 저장될 수 있도록 관련 속성을 질문, 답변 엔티티에 추가해야 한다.
voter: 추천인에 대한 속성. 한 사람이 여러 개의 질문을 추천할 수 있도록 @ManyToMany를 사용해야 한다.
//Question, Answer에 voter 속성 추가
import java.util.Set;
import jakarta.persistence.ManyToMany;
@ManyToMany
Set<SiteUser> voter;
H2 콘솔에 voter 속성이 추가된 것을 확인할 수 있다.
@ManyToMany 애너테이션을 사용해 다대다 관계로 속성이 생성이 되어 새로운 테이블이 만들어진 것을 확인할 수 있다.
<!-- question_detail.html 의 게시글, 답변 부분 추가 -->
<a href="javascript:void(0);" class="recommend btn btn-sm btn-outline-secondary"
th:data-uri="@{|/question/vote/${question.id}|}">
추천
<span class="badge rounded-pill bg-success" th:text="${#lists.size(question.voter)}"></span>
</a>
<a href="javascript:void(0);" class="recommend btn btn-sm btn-outline-secondary"
th:data-uri="@{|/answer/vote/${answer.id}|}">
추천
<span class="badge rounded-pill bg-success" th:text="${#lists.size(answer.voter)}"></span>
</a>
<!-- script 부분에 추가-->
const recommend_elements = document.getElementsByClassName("recommend");
Array.from(recommend_elements).forEach(function (element) {
element.addEventListener('click', function () {
if (confirm("정말로 추천하시겠습니까?")) {
location.href = this.dataset.uri;
};
});
});
//QuestionService.java 에 추가
public void vote(Question question, SiteUser siteUser) {
question.getVoter().add(siteUser);
this.questionRepository.save(question);
}
//QuestionController.java 에 추가
@PreAuthorize("isAuthenticated()")
@GetMapping("/vote/{id}")
public String questionVote(Principal principal, @PathVariable("id") Integer id) {
Question question = this.questionService.getQuestion(id);
SiteUser siteUser = this.userService.getUser(principal.getName());
this.questionService.vote(question, siteUser);
return String.format("redirect:/question/detail/%s", id);
}
//AnswerService.java 에 추가
public void vote(Answer answer, SiteUser siteUser) {
answer.getVoter().add(siteUser);
this.answerRepository.save(answer);
}
//AnswerController.java 에 추가
@PreAuthorize("isAuthenticated()")
@GetMapping("/vote/{id}")
public String answerVote(Principal principal, @PathVariable("id") Integer id) {
Answer answer = this.answerService.getAnswer(id);
SiteUser siteUser = this.userService.getUser(principal.getName());
this.answerService.vote(answer, siteUser);
return String.format("redirect:/question/detail/%s", answer.getQuestion().getId());
}
앵커(anchor): URL 호출 시 원하는 위치로 이동해 주는 <a> 태그 기능.
답변을 작성하거나 수정할 때 redirect가 되면서 페이지가 상단으로 올라가지는 현상을 보완하기 위한 기능.
<!-- question_detail.html 에 추가-->
<!-- 답변 반복 시작 -->
<div class="card my-3" th:each="answer : ${question.answerList}">
<a th:id="|answer_${answer.id}|"></a>
<div class="card-body">