/movie

๐ŸŽฌ ์˜ํ™” ์ถ”์ฒœ ํ”„๋กœ์ ํŠธ

Primary LanguageJavaScript

movie

tmdb API๋ฅผ ํ™œ์šฉํ•œ ์˜ํ™” ์ถ”์ฒœ ์‚ฌ์ดํŠธ


โš™ Stack

  • React

    • styled-components
    • react-icons
    • react-responsive
    • react-router-dom
  • Redux-thunk

  • ๋ฐฐํฌ : netlify


๐Ÿ–ผ UI

์ œ๋ชฉ ์—†์Œ2


๐Ÿ“š Features

  • ์˜ค๋Š˜์˜ ์˜ํ™” Top10 ์ถ”์ฒœ

  • ์„ ํƒํ•œ ์žฅ๋ฅด๋ณ„ ์˜ํ™” Top20 ์ถ”์ฒœ

  • ์˜ํ™” ์„ ํƒ ์ €์žฅ

    • ์„ ํƒ์ˆœ, ์ถ”์ฒœ์ˆœ, ์ธ๊ธฐ์ˆœ ์ •๋ ฌ

โœ… ๊ตฌํ˜„์‹œ ๊ณ ๋ฏผํ•œ ๋ถ€๋ถ„

  • ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ๋Š” ๋ถ„๋ฆฌ๋  ์ˆ˜ ์žˆ๋„๋ก ์ปดํฌ๋„ŒํŠธ ๊ตฌ์กฐ๋ฅผ ๋‚˜๋ˆด๋‹ค.
  • container component์™€ presentational component๋ฅผ ๋‚˜๋ˆ„์–ด ์ƒํƒœ, UI๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ตฌ์กฐ๋กœ ๊ตฌ์„ฑํ–ˆ๋‹ค.
  • ์œ ํ‹ธํ•จ์ˆ˜๋กœ refactoringํ•˜์—ฌ api๋ฅผ ๋ฐ›์•„์˜ค๋Š” ๋ถ€๋ถ„์—์„œ ๋ฐ˜๋ณต๋˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ •๋ฆฌํ–ˆ๋‹ค.
  • ๋ถˆํ•„์š”ํ•œ style์€ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•ด ๊ณ ๋ฏผํ–ˆ๋‹ค.

๐Ÿ‘ฉโ€๐Ÿ’ป ๊ธฐ์–ตํ•˜๊ณ  ์‹ถ์€ ์ฃผ์š” ๊ธฐ๋Šฅ Component

  • GenreList Component : ์ฒดํฌ๋ฐ•์Šค ์ปจํŠธ๋กค ์ปดํฌ๋„ŒํŠธ
function GenreListComponent({ data }) {
  const dispatch = useDispatch();
  const userGenre = JSON.parse(localStorage.getItem("genre"))
    ? JSON.parse(localStorage.getItem("genre"))
    : [];

  //์œ ์ €๊ฐ€ ์„ ํƒํ•œ ์žฅ๋ฅด
  const [selectGenres, setselectGenres] = useState(userGenre);
  //"๋ชจ๋“ ์žฅ๋ฅด" input controller
  const [isAllChecked, setIsAllChecked] = useState(
    userGenre.length === 0 ? true : false
  );

  //์ „์ฒดํ•ด์ œ
  const onCancle = () => {
    setIsAllChecked(true);
    setselectGenres([]);
  };

  //"๋ชจ๋“ ์žฅ๋ฅด" ์ปจํŠธ๋กค
  const handleAll = () => {
    setselectGenres([]);
    setIsAllChecked(true);
  };

  //"๋ชจ๋“ ์žฅ๋ฅด" ์ œ์™ธ ์ปจํŠธ๋กค
  const handleCheck = (e, checked, genre) => {
    setIsAllChecked(false);
    if (checked) {
      setselectGenres([...selectGenres, genre]);
    } else {
      setselectGenres(
        selectGenres.filter(
          (genres) => JSON.stringify(genres) !== JSON.stringify(genre)
        )
      );
    }
  };

  //์ฐพ์•„๋ณด๊ธฐ
  const onSearch = () => {
    setGenre(selectGenres);
    dispatch(getGenreMovies(selectGenres.map((genre) => genre.id)));
  };

  return (
    <S.Section>
      <S.Genres>
        <S.Title>์žฅ๋ฅด๋ณ„ ์˜ํ™” ์ฐพ๊ธฐ</S.Title>
        <S.GenreBox>
          <S.GenreList>
            <S.Input
              type="checkbox"
              name="allGenres"
              id="allGenres"
              checked={isAllChecked}
              onChange={(e) => handleAll(e.target.checked)}
            />
            <S.Label htmlFor="allGenres">๋ชจ๋“  ์žฅ๋ฅด</S.Label>
          </S.GenreList>
          {data &&
            data.map((genre) => (
              <S.GenreList key={genre.id}>
                <S.Input
                  type="checkbox"
                  name={genre.name}
                  id={genre.id}
                  checked={
                    JSON.stringify(selectGenres).includes(JSON.stringify(genre))
                      ? true
                      : false
                  }
                  onChange={(e) => handleCheck(e, e.target.checked, genre)}
                />
                <S.Label htmlFor={genre.id}>{genre.name}</S.Label>
              </S.GenreList>
            ))}
        </S.GenreBox>
        <S.ButtonBox>
          <S.Button onClick={onCancle}>์ „์ฒดํ•ด์ œ</S.Button>
          <S.Button onClick={onSearch}>์ฐพ์•„๋ณด๊ธฐ</S.Button>
        </S.ButtonBox>
      </S.Genres>
    </S.Section>
  );
}

export default GenreListComponent;