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 ? (
+
+ ) : (
+ <>
+
+
+
+
+ {!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}
⭐️
@@ -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 = {