From 9dba4f5646c56845e7d955519fa608bb4910250d Mon Sep 17 00:00:00 2001 From: Loi Phan Date: Thu, 12 Oct 2023 17:36:19 +0700 Subject: [PATCH] Update sample code --- sample/use-popcorn/index.html | 4 +- sample/use-popcorn/src/App.jsx | 206 +++++++++++++++++++++----- sample/use-popcorn/src/StarRating.jsx | 2 +- 3 files changed, 171 insertions(+), 41 deletions(-) diff --git a/sample/use-popcorn/index.html b/sample/use-popcorn/index.html index 0c589ec..9af1cd1 100644 --- a/sample/use-popcorn/index.html +++ b/sample/use-popcorn/index.html @@ -1,10 +1,10 @@ - + - Vite + React + usePopcorn
diff --git a/sample/use-popcorn/src/App.jsx b/sample/use-popcorn/src/App.jsx index 4143daa..b0b2f89 100644 --- a/sample/use-popcorn/src/App.jsx +++ b/sample/use-popcorn/src/App.jsx @@ -1,5 +1,6 @@ import { useEffect } from "react"; import { useState } from "react"; +import StarRating from "./StarRating"; const average = (arr) => arr.reduce((acc, cur, i, arr) => acc + cur / arr.length, 0); @@ -23,13 +24,25 @@ export default function App() { setSelectedId(null); }; + const handleAddWatched = (movie) => { + setWatched((watched) => [...watched, movie]); + }; + + const handleDeleteWatched = (id) => { + setWatched((watched) => watched.filter((movie) => movie.imdbID !== id)); + }; + useEffect(() => { + const controller = new AbortController(); + const fetchMovies = async () => { try { setIsLoading(true); setError(""); - const res = await fetch(BASE_URL + `?apikey=${KEY}&s=${query}`); + const res = await fetch(BASE_URL + `?apikey=${KEY}&s=${query}`, { + signal: controller.signal, + }); if (!res.ok) throw new Error("Something went wrong with fetching movies"); @@ -39,8 +52,9 @@ export default function App() { if (data.Response === "False") throw new Error("Movie not found!"); setMovies(data.Search); + setError(""); } catch (err) { - setError(err.message); + if (err.name !== "AbortError") setError(err.message); } finally { setIsLoading(false); } @@ -53,6 +67,10 @@ export default function App() { } fetchMovies(); + + return () => { + controller.abort(); + }; }, [query]); return ( @@ -77,11 +95,16 @@ export default function App() { ) : ( <> - + )} @@ -153,28 +176,6 @@ function Box({ children }) { ); } -// function WatchedBox() { -// const [watched, setWatched] = useState(tempWatchedData); -// const [isOpen2, setIsOpen2] = useState(true); - -// return ( -//
-// -// {isOpen2 && ( -// <> -// -// -// -// )} -//
-// ); -// } - function MovieList({ movies, onSelectMovie }) { return (
    @@ -200,13 +201,132 @@ function Movie({ movie, onSelectMovie }) { ); } -function MovieDetails({ selectedId, onCloseMovie }) { +function MovieDetails({ selectedId, onCloseMovie, onAddWatched, watched }) { + const [movie, setMovie] = useState({}); + const [isLoading, setIsLoading] = useState(false); + const [userRating, setUserRating] = useState(0); + + const isWatched = watched.map((movie) => movie.imdbID).includes(selectedId); + const watchedUserRating = watched.find( + (movie) => movie.imdbID === selectedId + )?.userRating; + + const { + Title: title, + Year: year, + Poster: poster, + Runtime: runtime, + imdbRating, + Plot: plot, + Released: released, + Actors: actors, + Director: director, + Genre: genre, + } = movie; + + const handleAdd = () => { + const newWatchedMovie = { + imdbID: selectedId, + title, + year, + poster, + imdbRating: Number(imdbRating), + runtime: Number(runtime.split(" ").at(0)), + userRating, + }; + + onAddWatched(newWatchedMovie); + onCloseMovie(); + }; + + useEffect(() => { + if (!title) return; + document.title = `Movie | ${title}`; + + return () => { + document.title = "usePopcorn"; + }; + }, [title]); + + useEffect(() => { + async function getMovieDetails() { + setIsLoading(true); + const res = await fetch(BASE_URL + `?apikey=${KEY}&i=${selectedId}`); + + const data = await res.json(); + setMovie(data); + setIsLoading(false); + } + + getMovieDetails(); + }, [selectedId]); + + useEffect(() => { + const callback = (e) => { + if (e.code === "Escape") { + onCloseMovie(); + } + }; + + document.addEventListener("keydown", callback); + + return () => { + document.removeEventListener("keydown", callback); + }; + }, [onCloseMovie]); + return (
    - - {selectedId} + {isLoading ? ( + + ) : ( + <> +
    + + {`Poster +
    +

    {title}

    +

    + {released} • {runtime} +

    +

    {genre}

    +

    + + {imdbRating} IMD rating +

    +
    +
    + +
    +
    + {!isWatched ? ( + <> + + + {userRating > 0 && ( + + )} + + ) : ( +

    You rated this movie {watchedUserRating} ⭐

    + )} +
    +

    + {plot} +

    +

    Starring {actors}

    +

    Directed by {director}

    +
    + + )}
    ); } @@ -226,36 +346,40 @@ function WatchedSummary({ watched }) {

    ⭐️ - {avgImdbRating} + {avgImdbRating.toFixed(2)}

    🌟 - {avgUserRating} + {avgUserRating.toFixed(2)}

    - {avgRuntime} min + {avgRuntime.toFixed(2)} min

    ); } -function WatchMovieList({ watched }) { +function WatchMovieList({ watched, onDeleteWatched }) { return (
      {watched.map((movie) => ( - + ))}
    ); } -function WatchedMovie({ movie }) { +function WatchedMovie({ movie, onDeleteWatched }) { return (
  • - {`${movie.Title} -

    {movie.Title}

    + {`${movie.title} +

    {movie.title}

    ⭐️ @@ -269,6 +393,12 @@ function WatchedMovie({ movie }) { {movie.runtime} min

    +
  • ); diff --git a/sample/use-popcorn/src/StarRating.jsx b/sample/use-popcorn/src/StarRating.jsx index a768c4a..803603d 100644 --- a/sample/use-popcorn/src/StarRating.jsx +++ b/sample/use-popcorn/src/StarRating.jsx @@ -36,7 +36,7 @@ export default function StarRating({ const handleRating = (rating) => { setRating(rating); - if (onSetRating) setRating(rating); + if (onSetRating) onSetRating(rating); }; const textStyle = {