[TIL] 영화 검색 사이트 만들기 (3)

·2023년 10월 26일
1

TIL

목록 보기
15/85
post-thumbnail

어제 상세페이지로 이동해서 포스터이미지 불러오는 것 까지는 완성했고, 나머지는 다른 조원들이. 나는 localStorage를 활용한 리뷰 작성 기능을 담당했다. 예전에 localStorage를 활용하여 to-do list를 만들어 본 경험이 있어서 코드를 작성하는데 도움이 되었다.

0. review 작성을 위한 Form 만들기

아직 CSS 작업을 거의 하지 않은 상태라 디자인 끔찍 그잡채🫠
감안하고 봐주시길ㅎ

유효성 검사

리뷰 작성 시 validation check(유효성 검사)를 위해 각 태그에 minlength, required 를 넣어주었다.
별점 선택을 위해 select 태그를 사용했는데 required를 넣었음에도 불구하고 별점 선택을 하지 않고 제출해도 계속 저장이 되어버리는 현상이 발생했다.
열심히 검색해서 별점 선택 optionvalue="" 를 해주면 되는 걸 알아냄.ㅎ 별거 아닌데 찾는데 시간걸렸다. 😇

<select class="review__star" id="star" required>
  <option selected value="">별점 선택</option>
  <option value="⭐️">⭐️</option>
  <option value="⭐️⭐️">⭐️⭐️</option>
  <option value="⭐️⭐️⭐️">⭐️⭐️⭐️</option>
  <option value="⭐️⭐️⭐️⭐️">⭐️⭐️⭐️⭐️</option>
  <option value="⭐️⭐️⭐️⭐️⭐️">⭐️⭐️⭐️⭐️⭐️</option>
</select>

그리고.. 엔터키만 쳐도 등록 버튼을 누른 것처럼 동작하게 하고 싶었는데 리뷰 칸이 textarea라 엔터키를 치면 개행이 되는 것이었다.... textarea에 required 를 주었지만 textarea를 제외한 나머지 요소만 입력하고 등록해도 제출이 되어버리는 현상이..!!! 그래서 textaraa에서 엔터키를 입력했을 때에도 등록버튼을 클릭한 것 처럼 동작하게 하기 위해 다음과 같은 코드를 추가했다.

function handleTextareaEnter(e) {
  if (e.key == "Enter") {
    reviewSubmitBtn.click();
  }
}

reviewTextarea.addEventListener("keyup", handleTextareaEnter);

폼의 입력 값에 대한 유효성 검사는 얼추 완성이 되었다.
이제 폼이 submit 되었을 때는 다음과 같은 코드를 실행한다.

1. review 제출 및 localStorage에 저장

let reviewStorage = [];

function saveReview() {
  localStorage.setItem("review", JSON.stringify(reviewStorage));
}

function submitReview(e) {
  e.preventDefault();

  const reviewObj = {
    name: reviewUsername.value,
    password: reviewPassword.value,
    star: reviewStar.value,
    review: reviewTextarea.value,
    id: Date.now(),
    movieid: parseInt(id),
  };

  reviewStorage.push(reviewObj);
  reviewForm.reset();

  paintReview(reviewObj);
  saveReview();
}

reviewForm.addEventListener("submit", submitReview);
  1. 우선 제출되었을 때 새로고침하는 것을 방지하기 위해 e.preventDefault() 를 실행.
  2. 폼에 제출된 각각의 값들을 가지고 객체를 생성한다. 그리고 폼에 작성된 값은 아니지만, 각각의 리뷰에 id 값과 movieid 값도 주었다. (나중에 특정 리뷰만 선택해서 삭제하기 위해 id 값 Date.now() 로 할당 / 그 영화에 해당하는 리뷰만 그려주기 위해 movieid 값 할당)
  3. 그리고 reviewStorage 라는 빈 배열을 만들고, 생성된 reviewObj 객체를 reviewStorage에 push 해 주었다.
  4. 제출하고 나서 폼을 다시 비우기 위해 폼을 리셋.
  5. saveReview() 함수를 통해 localStorage 에 배열을 저장. 그러나 localStorage의 value 로 배열은 들어갈 수 없기 때문에 JSON.stringify를 통해 string으로 바꿔서 저장.

2. review 그려주기

function paintReview(reviewObj) {
  const li = document.createElement("li");
  li.id = reviewObj.id;
  li.classList.add("review__list");
  li.innerHTML = ``
 
  // 생략

  reviewLists.append(li);
}

(여전히 디자인 끔찍스.🫠 계속 말하지만 기능 구현이 우선이라 디자인 작업 아직 안함)

  1. li 태그에 새롭게 생성될 리뷰 내용을 담는다.
  2. ul 태그(reviewLists) 에 append 한다.
  3. 한장의 카드는 잘 붙는다!

3. localStorage에서 review 꺼내오기

초기 버전

const saveReviews = localStorage.getItem("review");

if (saveReviews !== null) {
  //만약 reviewStorage가 localStorage에 존재하면 실행할 코드
  const parsedReviews = JSON.parse(saveReviews);
  reviewStorage = parsedReviews;
  parsedReviews.forEach(paintReview); 
}
  1. 이제 localStorage에 있는 배열을 꺼내와야 한다.
  2. localStorage에는 현재 string 형태로 들어있기 때문에 JSON.parse 를 통해 다시 객체배열 형태로 사용할 수 있게 바꿔주었다.
  3. 그리고 그 배열을 돌면서 배열 요소 갯수만큼 paintReview 함수를 실행하며 리뷰들을 그려준다.

마주한 에러

localStorage에 저장할 때 "review"라는 키로, 영화 상관없이 하나의 배열에 객체들을 저장하기 때문에 작성한 리뷰가 모든 영화의 상세페이지에서 동잃하게 보이는 문제가 발생했다. (예를 들어 '쏘우' 라는 영화의 상세페이지에 리뷰를 달았는데 '발레리나' 라는 영화의 상세페이지에도 '쏘우'에 대한 리뷰가 같이 보여짐)

이를 위해 어제 진행된 특강 내용에 배열 메서드들을 엮는 배열 체이닝이 생각났다. parsedReviews라는 배열을 filter 메서드를 통해 객체에 저장된 movieid와 현재 상세페이지의 id가 일치하는 요소들만 걸러내고, 걸러진 배열 요소들만 가지고 forEach메서드를 통해 paintReview 함수를 실행해야지!

수정 버전

const saveReviews = localStorage.getItem("review");

if (saveReviews !== null) {
  //만약 reviewStorage가 localStorage에 존재하면 실행할 코드
  const parsedReviews = JSON.parse(saveReviews);
  reviewStorage = parsedReviews;
  parsedReviews.filter((obj) => obj.movieid == id).forEach(paintReview); // 배열체이닝
}

배운 것 바로 써먹기~


삭제 기능도 구현은 했는데, 삭제버튼을 클릭했을 때 바로 삭제되는 것이 아니라 버튼을 클릭하면 모달 창이 생성되고, 거기서 비밀번호를 입력했을 때 해당 리뷰의 비밀번호와 일치할 경우에만 삭제하고 싶어서 이것 저것 시도해보는 중이다. 내일 다시 츄라이 해봐야지.

느낀점

  • 오늘 거의 하루종일 코딩만 한 듯.. 밥도 한끼만 먹었다..
  • 그래도 조금씩 진전되어가고 있어서 생각보다는(?) 힘들지 않다.
  • 아침에 몸무게를 쟀는데 굉장히 오랜만에 보는 숫자가 나왔다.
  • 이것이 바로 코딩 다이어트...
  • 리뷰 삭제 기능에 대한 validation check를 해보고 싶은데.. 잘 안되는 중 😇
profile
느리더라도 조금씩, 꾸준히

0개의 댓글