티스토리 뷰

<!DOCTYPE html>
<html lang="ko">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>movie project</title>
  <link rel="stylesheet" href="movie.css">
  <script src="movie.js" type="module"></script>
</head>

<body>
  <div class="container">
    <header>
      <img src="img/title.png" alt="Spasta Movie" onclick="location.reload();">
     <p id="logoText">로고를 클릭하면 새로고침됩니다. &#8634;</p>
    </header>
    <form id="searchForm">
      <label for="search">영화 검색</label>
      <input type="text" id="search" placeholder="영화 제목을 검색하세요">
      <button id="btn" type="submit">검색하기</button>
    </form>
    <div id="moviesBox">
    </div>
  </div>
</body>

</html>
/* CSS */

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  width: 100%;
  background-color: black;
}

header {
  height: 140px;
  margin: 2%;
  color: white;
}
header img:hover{
  cursor: pointer;
  transform: scale(1.05);
}

form {
  width: 100%;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;

  font-size: 25px;
  color: white;
}

form>input {
  padding: 10px;
  width: 15%;
  margin: 0 1%;
  border: none;

  color: white;
  font-size: 20px;
  background-color: transparent;
  border-bottom: 1px solid white;
}

form>button {
  padding: 10px;

  font-size: 20px;
  background-color: transparent;
  color: white;
  border: 3px solid white;
  border-radius: 5px;
}

input:hover {
  border-bottom: 1px solid red;
}

button:hover {
  cursor: pointer;
  border: 3px solid red;
  color: red;
}

#moviesBox {
  width: 100%;
  margin-top: 5%;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-evenly;

}

.card {
  width: 20%;
  height: 80vh;
  padding: 1%;
  margin: 3%;
  display: flex;
  flex-direction: column;
  justify-content: space-evenly;
  align-items: center;

  color: white;
  background-color: #171717;
  border-radius: 10px;
}

.card>.poster {
  width: 60%;
  border-radius: 10px;
}

.card:hover {
  filter: invert(10%);
  /* filter: brightness(150%); */
  transform: scale(1.1);
}​
// Javascript

const options = {
  method: 'GET',
  headers: {
    accept: 'application/json',
    Authorization: 'Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJjOTI3MDJhMzJkMmRjODkyZmY0MWVkNDUyY2FkNzlmNSIsInN1YiI6IjY1OWE2NjgwODc0MWM0MDE0OWNmZThhOSIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.YP6AFRBzCxXt71iiMIveA22dxWAIxInrzwPri1QfSqg'
  }
};
fetch('https://api.themoviedb.org/3/movie/top_rated?language=en-US&page=1', options)
  .then(response => response.json())
  .then(response => {
    // console.log(response);
    const result = response.results;
    // console.log("result",result);

    // 배열 형태의 api문서를 배열 반복문을 사용하여 addMovie 이벤트에 인자로 전달
    result.forEach(movie => {
      // console.log("movie", movie)
      addMovie(movie);
    });
  })
  .catch(err => console.error(err));

function addMovie(movie) {
  const moviesBox = document.getElementById("moviesBox");

  // 인자로 받은 객체 데이터를 구조분해 할당으로 원하는 값만 추출
  const { title, overview, poster_path, vote_average, id } = movie;
  // console.log(movie)

  // html문서에 영화 카드 만들기
  const card = document.createElement("div");
  const poster = document.createElement("img");
  const mvTitle = document.createElement("h2");
  const mvOverview = document.createElement("p");
  const mvVote_average = document.createElement("p");

  // html 요소에 클래스네임 부여
  card.className = 'card';
  poster.className = 'poster';
  mvTitle.className = 'mvTitle';
  mvOverview.className = 'mvOverview';
  mvVote_average.className = 'vote-mvVote_average';

  // 이미지 경로
  poster.src = `https://image.tmdb.org/t/p/w500${poster_path}`;

  // 제목 등 요소에 내용 삽입
  mvTitle.innerText = title;
  mvOverview.innerText = overview;
  mvVote_average.innerText = `Vote Average: ${vote_average}`;

  // 만들어진 카드 내용들은 카드div에 추가
  card.appendChild(poster);
  card.appendChild(mvTitle);
  card.appendChild(mvOverview);
  card.appendChild(mvVote_average);

  // 컨테이너에 카드 추가
  moviesBox.appendChild(card);

  // console.log(card);

  card.addEventListener("click", () => {
    alert("영화 ID : " + id);
  });
  return card;

};

// 제목 검색 시 결과 띄우기
// form을 사용할 경우, Enter이벤트를 따로 작성하지않아도 적용된다.
let searchForm = document.getElementById("searchForm");

// 새로고침 안내 문구
let logoText = document.getElementById("logoText");
logoText.style.display = "none"

searchForm.addEventListener("submit", (e) => {
  // preventDefault 기본행동을 막는 함수 form은 기본적으로 새로고침을한다
  // e - 이벤트 대상
  e.preventDefault();

  // 인풋값을 소문자로 변환하여 가져오기
  // 영화 카드 가져오기 (카드 제목으로 검색 키워드랑 비교해야 하니까)
  const searchInput = document.getElementById("search").value.toLowerCase();
  const movieCards = document.querySelectorAll(".card");

  movieCards.forEach(card => {
    const title = card.querySelector(".mvTitle").textContent.toLowerCase();
    // textContent - value는 사용자가 입력하는 텍스트에서만 사용.

    if (title.includes(searchInput)) {
      card.style.display = "flex"; // 제목이 일치하면 카드 띄우기
      logoText.style.display = "flex";
    } else {
      card.style.display = "none"; // 일치하지 않으면 카드를 숨기기
      logoText.style.display = "flex";
    }
  });
});

 

 

첫 개인 과제를 마무리했다. 구글이랑 튜터님들이 없었다면 하나도 못했을 결과물.

겨우 필수 요구사항만 맞춘 수준이다,

받아온 API는 배열이었고, 요소가 객체로 되어있었다 foreach를 이용해 배열을 하나씩 매개변수로 전달하고, 구조분해 할당을 통해 원하는 값을 추출하였다 이 과정도 엄청 헤매고 헤매다 구글과 튜터님 덕분에 성공했다

그리고 검색 이벤트 구현시, title의 value를 가져와서 사용하려 했으나 이벤트 수행이 안되고 오류...

console에서 title에 문제가 있다는 건 알았지만 뭐가, 왜 문제인지를 몰라서 제목을 가져오고, 값을 따로 추출하고, 소문자 변환을 각각 작성해보기도 하고, 아예 value를 생략하기도 해 봤는데 value는 당연히 값을 가져와야 비교를 하니까, 거기서 오류가 난다는 걸 알면서도 다른 곳 때문에 문제일 거라며 엄한 데만 계속 수정하다 튜터님께 물어봤다

 

결론은 사용자가 입력한 텍스트만 value로 가져와야 했다는 거. 허무하긴 했지만 이렇게 배우는 거겠지, 그 외에도

검색 이벤트 구현시 form을 사용하면 Enter 함수를 따로 작성하지 않아도 된다는 것,

form은 기본적으로 새로고침을 한다는 것들을 알았다.

 

첫 과제부터 많이 부족하단 생각이 들었다 그만큼 내가 어떤 것에 얼마큼 이해도가 떨어지는지 다시 돌아볼 수 있는 계기가 되기도 했으니, 나름 얻은 게 있다면 있는 거겠지, 그리고 지난번 미니 프로젝트에서 flex 사용을 좀 어려워했었는데 이번엔 css를 막힘없이 완성해서 살짝 뿌듯하기도 하다.

TIL을 적으면서 코드를 보는데  가독성이 좀 떨어지는 거 같다. 다음에는 이벤트별로 js파일을 나누도록 하자, 그리고 혼자 하는 과제라 해도 변수명 꼭 신경 써야겠다 내가 봐도 직관성이 안 좋다는 걸 느낀다

 

* 이후 할 일

객체, 배열 메서드에 대해 이해도가 많이 떨어지는 거 같으니 조만간 튜터님 강의를 다시 보고 정리할 것

Git, Github 강의 보면서 계속 연습하기 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함