<오늘 한 일>
- 리뷰 조회
백엔드와 통신하는 리뷰 조회 함수 생성(api.js)
- 리뷰를 조회하는 방법이 백엔드에 2가지로 구현되어 있다
- 139번째줄은 해당 전시회에 달린 리뷰를 모두 보여주고 140번째 줄은 해당 전시회에 달린 리뷰를 9개씩 페이지네이션 해서 보여준다
- 실질적으로 140번째 줄을 사용할 예정인데 일단 혹시 몰라 두 fetch를 쓰고 하나는 주석 처리 해놨다
전시 상세페이지에 리뷰 버튼 클릭 함수 생성(exhibition-detail.js)
- 빨간 네모 표시된 버튼을 클릭했을 때 review(exhibition_id) 함수가 실행된다
리뷰 목록 렌더(review.js)
import { payload, payloadParse, getReviewAPI, backendBaseURL } from "./api.js";
- 먼저 필요한 함수들을 다른 js 파일에서 import 한다
let isReviewsRendered = false;
- 이 변수없이 코드를 짰더니 리뷰보기 버튼을 눌렀을 때마다 리뷰 목록이 계속 생성되는 이슈가 있어서 추가했다
// 이용후기 버튼 눌렀을 때 실행되는 함수
export function review(exhibition_id) {
// 동행글 안 보이게 하기
var acAllItemsOrganizer = document.querySelector(".ac-all-items-organizer");
acAllItemsOrganizer.style.display = "none";
var rvAllItemsOrganizer = document.querySelector(".rv-all-items-organizer");
if (rvAllItemsOrganizer.style.display === "none") {
rvAllItemsOrganizer.style.display = "flex";
- review(exhibition_id) 함수가 exhibition-detail.js에서 사용되기 때문에 앞에 export를 붙였다
- 4~5번째줄은 아래 동행글 조회할 때도 리뷰 버전으로 들어갈 건데 동행글 보기 버튼을 눌러서 동행글이 렌더된 상태에서 리뷰 보기를 눌렀을 때 동행글 목록이 안 보이게 하는 코드다
- 7~9번째줄은 리뷰 목록 전체를 감싸는 태그를 선택해서 display가 none이면(리뷰 목록이 보이지 않는 상태라면) flex로 바꿔준다
- 반대로 보이는 경우라면(display === "flex") none으로 바꿔줘서(아래 작성되어 있음) 리뷰 목록을 닫을 수 있다
if (!isReviewsRendered) {
getReviewAPI(exhibition_id).then(({ responseJson }) => {
const reviewsDATA = responseJson.reviews.results
// 후기 목록
reviewsDATA.forEach(review => {
const grayBox = document.createElement("div")
grayBox.setAttribute("class", "rv-gray-box")
// 이미지
const imgBox = document.createElement("div")
imgBox.setAttribute("class", "rv-img-box")
const reviewImg = document.createElement("img")
reviewImg.setAttribute("class", "rv-review-img")
reviewImg.setAttribute("onerror", "this.src='/static/img/default-img.jpg'")
if (review.image) {
reviewImg.setAttribute("src", `${backendBaseURL.split('/api')[0]}${review.image}`);
} else {
reviewImg.setAttribute("src", "/static/img/default-img.jpg")
}
imgBox.appendChild(reviewImg)
grayBox.appendChild(imgBox)
const purpleBox = document.createElement("div")
purpleBox.setAttribute("class", "rv-purple-box")
const row1InPurple = document.createElement("div")
row1InPurple.setAttribute("class", "rv-row1-in-purple")
// 닉네임
const nicknameBox = document.createElement("div")
nicknameBox.setAttribute("class", "rv-nickname-box")
nicknameBox.innerText = review.nickname
row1InPurple.appendChild(nicknameBox)
// 별점
const stars = document.createElement("div")
stars.setAttribute("class", "rv-stars")
for (let i = 1; i <= 5; i++) {
if (i <= review.rating) {
let star = document.createElement("img")
star.setAttribute("class", "rv-star")
star.setAttribute("src", "/static/img/filled-star.png")
stars.appendChild(star)
} else {
let star = document.createElement("img")
star.setAttribute("class", "rv-star")
star.setAttribute("src", "/static/img/empty-star.png")
stars.appendChild(star)
}
}
row1InPurple.appendChild(stars)
purpleBox.appendChild(row1InPurple)
const row2InPurple = document.createElement("div")
row2InPurple.setAttribute("class", "rv-row2-in-purple")
// 후기 내용
const reviewContent = document.createElement("div")
reviewContent.setAttribute("class", "rv-review-content")
reviewContent.innerText = review.content
row2InPurple.appendChild(reviewContent)
purpleBox.appendChild(row2InPurple)
const row3InPurple = document.createElement("div")
row3InPurple.setAttribute("class", "rv-row3-in-purple")
// 후기 날짜
const dateInfo = document.createElement("div")
dateInfo.setAttribute("class", "rv-date-info")
const span1 = document.createElement("span")
span1.innerText = "최종 수정일"
dateInfo.appendChild(span1)
const span2 = document.createElement("span")
span2.innerText = review.updated_at.split("T")[0]
dateInfo.appendChild(span2)
row3InPurple.appendChild(dateInfo)
// 수정, 삭제 버튼
if (payload) {
if (payloadParse.user_id == review.user){
// 수정 버튼
const reviewUpdateBtn = document.createElement("button")
reviewUpdateBtn.setAttribute("type", "button")
reviewUpdateBtn.setAttribute("class", "rv-review-update-btn")
reviewUpdateBtn.innerText = "수정"
row3InPurple.appendChild(reviewUpdateBtn)
// 삭제 버튼
const reviewDeleteBtn = document.createElement("button")
reviewDeleteBtn.setAttribute("type", "button")
reviewDeleteBtn.setAttribute("class", "rv-review-delete-btn")
reviewDeleteBtn.innerText = "삭제"
row3InPurple.appendChild(reviewDeleteBtn)
}
}
purpleBox.appendChild(row3InPurple)
grayBox.appendChild(purpleBox)
reviewList.appendChild(grayBox)
})
})
isReviewsRendered = true;
}
- 길지만.. 별 거 없다
- 이미지로 먼저 보자면 아래 달리는 저 카드들을 리뷰 개수만큼 붙여준다
- 중요한 건 104번째 줄에 있는 isReviewsRendered = true; 이 코드다
- 해당 변수를 처음에 false라고 선언해서 위 if문이 실행된다 if문이 실행된 후 해당 변수를 true로 바꿔주면 다음에 또 리뷰 보기를 눌렀을 때 if문이 실행되지 않는다
} else {
rvAllItemsOrganizer.style.display = "none";
}
}
- 이 else문은 if (rvAllItemsOrganizer.style.display === "none") { 이 코드의 else문이다
- 위에서 말했 듯 리뷰 목록이 보이는 상태라면 안 보이게 만들어 준다
- 동행글 조회
- 동행글도 리뷰와 생김새, 변수명만 다를 뿐 똑같은 로직으로 구현되어 있다
- 추천바 구현
<느낀 점>
- 프론트엔드 구현을 어떻게 해야할지 모를 때는 여유가 있었는데 이제 하는 방법을 알고 나니 여유가 없어졌다..
- 오늘 새롭게 알게된 건 다 프론트엔드 내용이다
- 버튼 클릭 시 내용이 보였다가 사라졌다가 하는 기능
- 스크롤의 위치에 따라 내용이 보였다가 안 보였다가 하는 기능
- 아마 정리는 주말에 해야 하지 않을까 싶다..!
<내일 목표>
- 프론트엔드 리뷰/동행글 작성, 수정, 삭제 구현하기
- 추천바에 추천 게시글 연결하기