From 2aa9429c2aed5b7381951e4c6c37e2358f754fa0 Mon Sep 17 00:00:00 2001 From: Carson Wolber Date: Mon, 10 Jun 2024 15:08:37 -0700 Subject: [PATCH 01/11] init project setup. basic forms working --- .env | 1 + data/data.js | 0 src/App.jsx | 22 +++++++++++++++++----- src/MovieCard.css | 4 ++++ src/MovieCard.jsx | 13 +++++++++++++ src/MovieList.css | 6 ++++++ src/MovieList.jsx | 42 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 .env create mode 100644 data/data.js create mode 100644 src/MovieCard.css create mode 100644 src/MovieCard.jsx create mode 100644 src/MovieList.css create mode 100644 src/MovieList.jsx diff --git a/.env b/.env new file mode 100644 index 00000000..3f492219 --- /dev/null +++ b/.env @@ -0,0 +1 @@ +VITE_API_KEY=eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIxYTEwYzJkZTdjZGQyYTNjOTM4YzEwMTBmOTk5ZDI0MSIsInN1YiI6IjY2Njc2NzI2NTM1YjMyMTc5Nzg1YTVkNSIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.0Oh7jejjYFuQKbX-ZZkuCE2i7C_Nn5FmfKNwADZt6aQ diff --git a/data/data.js b/data/data.js new file mode 100644 index 00000000..e69de29b diff --git a/src/App.jsx b/src/App.jsx index 48215b3f..f2d6538d 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,10 +1,22 @@ -import { useState } from 'react' import './App.css' +import MovieList from './MovieList' +function App () { + return ( -const App = () => { -
- -
+ // { + // const fetchData = async () => { + // const key = import.meta.env.VITE_API_KEY; + // const repsonse = await fetch('https://api.themoviedb.org/3/configuration'); + // const data = await response.json(); + + // } + + + // } +
+ +
+ ) } export default App diff --git a/src/MovieCard.css b/src/MovieCard.css new file mode 100644 index 00000000..93b1145b --- /dev/null +++ b/src/MovieCard.css @@ -0,0 +1,4 @@ +.card { + border: 1px solid black; + border-radius: 8px; +} \ No newline at end of file diff --git a/src/MovieCard.jsx b/src/MovieCard.jsx new file mode 100644 index 00000000..ee2b9f62 --- /dev/null +++ b/src/MovieCard.jsx @@ -0,0 +1,13 @@ +import './MovieCard.css' + +function MovieCard(movie) { + return ( +
+ +

{movie.title}

+

{movie.rating}

+
+ ) +} + +export default MovieCard; \ No newline at end of file diff --git a/src/MovieList.css b/src/MovieList.css new file mode 100644 index 00000000..6fbe134c --- /dev/null +++ b/src/MovieList.css @@ -0,0 +1,6 @@ +.list { + display: flex; + flex-wrap: nowrap; + flex-direction: row; + justify-content: space-around; +} \ No newline at end of file diff --git a/src/MovieList.jsx b/src/MovieList.jsx new file mode 100644 index 00000000..664f7b61 --- /dev/null +++ b/src/MovieList.jsx @@ -0,0 +1,42 @@ +import.meta.env.VITE_API_KEY +import './MovieList.css' +import MovieCard from './MovieCard' + +function MovieList() { + return ( +
+ + + + + + + + +
+ + + ) +} + +export default MovieList; \ No newline at end of file From 36076e8b96e037e04510eb3f4cb0bc34589e0e5f Mon Sep 17 00:00:00 2001 From: Carson Wolber Date: Mon, 10 Jun 2024 17:10:35 -0700 Subject: [PATCH 02/11] end of day push --- .gitignore | 2 ++ src/App.css | 45 +++++++++++++++++++----------------- src/App.jsx | 37 +++++++++++++++++++---------- src/MovieCard.css | 1 + src/MovieList.css | 10 ++++++-- src/Search.css | 6 +++++ src/Search.jsx | 17 ++++++++++++++ data/data.js => src/Sort.css | 0 src/Sort.jsx | 19 +++++++++++++++ utils/utils.js | 0 10 files changed, 102 insertions(+), 35 deletions(-) create mode 100644 src/Search.css create mode 100644 src/Search.jsx rename data/data.js => src/Sort.css (100%) create mode 100644 src/Sort.jsx create mode 100644 utils/utils.js diff --git a/.gitignore b/.gitignore index a547bf36..50c8dda2 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ dist-ssr *.njsproj *.sln *.sw? + +.env diff --git a/src/App.css b/src/App.css index 0bf65669..fe2a33cf 100644 --- a/src/App.css +++ b/src/App.css @@ -1,28 +1,31 @@ -.App { - text-align: center; -} - -.App-header { - background-color: #282c34; +header { + height: 10vh; + background-color: #457462; + position: sticky; display: flex; - flex-direction: row; align-items: center; - justify-content: space-evenly; - color: white; - padding: 20px; } -@media (max-width: 600px) { - .movie-card { - width: 100%; - } +h1 { + color: #ee892f; + margin-left: 2%; +} - .search-bar { - flex-direction: column; - gap: 10px; - } +footer { + background-color: #457462; + height: 10vh; + justify-content: center; + align-self: center; + bottom: 0; + position: fixed; + display: flex; + width: 100%; +} - .search-bar form { - flex-direction: column; - } +#loadbtn { + justify-content: center; + align-self: center; + display: flex; } + + diff --git a/src/App.jsx b/src/App.jsx index f2d6538d..6cf15109 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,21 +1,34 @@ import './App.css' import MovieList from './MovieList' +import Search from './Search'; function App () { - return ( - - // { - // const fetchData = async () => { - // const key = import.meta.env.VITE_API_KEY; - // const repsonse = await fetch('https://api.themoviedb.org/3/configuration'); - // const data = await response.json(); + const options = { + method: 'GET', + headers: { + accept: 'application/json', + Authorization: 'eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIxYTEwYzJkZTdjZGQyYTNjOTM4YzEwMTBmOTk5ZDI0MSIsInN1YiI6IjY2Njc2NzI2NTM1YjMyMTc5Nzg1YTVkNSIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.0Oh7jejjYFuQKbX-ZZkuCE2i7C_Nn5FmfKNwADZt6aQ' + } + }; + + fetch('https://api.themoviedb.org/3/authentication', options) + .then(response => response.json()) + .then(response => console.log(response)) + .catch(err => console.error(err)); - // } - - // } -
- + return ( + <> +
+

Flixster

+ +
+
+
+
+ +
+ ) } diff --git a/src/MovieCard.css b/src/MovieCard.css index 93b1145b..43d3dc7b 100644 --- a/src/MovieCard.css +++ b/src/MovieCard.css @@ -1,4 +1,5 @@ .card { border: 1px solid black; border-radius: 8px; + margin: 2%; } \ No newline at end of file diff --git a/src/MovieList.css b/src/MovieList.css index 6fbe134c..eab1995a 100644 --- a/src/MovieList.css +++ b/src/MovieList.css @@ -1,6 +1,12 @@ .list { + text-align: center; + /* display: grid; + grid-template-columns: auto auto auto auto auto; + gap: 1vw; + */ + margin: 1vw 1vw 0 1vw; display: flex; - flex-wrap: nowrap; flex-direction: row; - justify-content: space-around; + flex-wrap: wrap; + justify-content: center; } \ No newline at end of file diff --git a/src/Search.css b/src/Search.css new file mode 100644 index 00000000..773337f3 --- /dev/null +++ b/src/Search.css @@ -0,0 +1,6 @@ +.searchbar{ + margin-left: 5%; + display: flex; + height: 4vh; + border-radius: 8px; +} \ No newline at end of file diff --git a/src/Search.jsx b/src/Search.jsx new file mode 100644 index 00000000..9fde74b6 --- /dev/null +++ b/src/Search.jsx @@ -0,0 +1,17 @@ +import './Search.css' + +function Search() { + // const handleSearchChange = (event) => { + // let searchQuery = event.target.value; + + // }; + + //value={searchQuery} onChange={handleSearchChange} + return ( +
+ +
+ ) +} + +export default Search; \ No newline at end of file diff --git a/data/data.js b/src/Sort.css similarity index 100% rename from data/data.js rename to src/Sort.css diff --git a/src/Sort.jsx b/src/Sort.jsx new file mode 100644 index 00000000..1b0a3224 --- /dev/null +++ b/src/Sort.jsx @@ -0,0 +1,19 @@ +// import './Sort.css' + +// function Sort() { +// function ShowSortOptions() { + +// } + +// return ( +//
+// +//
+ + +//
+//
+// ) +// } + +// export default Sort; \ No newline at end of file diff --git a/utils/utils.js b/utils/utils.js new file mode 100644 index 00000000..e69de29b From 00bc3ace7c4de51e2ea4ae65a6eef2b763598854 Mon Sep 17 00:00:00 2001 From: Carson Wolber Date: Mon, 10 Jun 2024 23:22:38 -0700 Subject: [PATCH 03/11] night work. Successfully set up API fetch and added search functionality --- .env | 2 +- src/App.jsx | 49 ++++++++++++++++++++++++----------------------- src/MovieCard.jsx | 6 +++--- src/MovieList.jsx | 8 +++++--- src/Search.jsx | 34 +++++++++++++++++++++----------- 5 files changed, 57 insertions(+), 42 deletions(-) diff --git a/.env b/.env index 3f492219..93563dda 100644 --- a/.env +++ b/.env @@ -1 +1 @@ -VITE_API_KEY=eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIxYTEwYzJkZTdjZGQyYTNjOTM4YzEwMTBmOTk5ZDI0MSIsInN1YiI6IjY2Njc2NzI2NTM1YjMyMTc5Nzg1YTVkNSIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.0Oh7jejjYFuQKbX-ZZkuCE2i7C_Nn5FmfKNwADZt6aQ +VITE_API_KEY=1a10c2de7cdd2a3c938c1010f999d241 diff --git a/src/App.jsx b/src/App.jsx index 6cf15109..a2542fed 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,35 +1,36 @@ -import './App.css' -import MovieList from './MovieList' +import './App.css'; +import MovieList from './MovieList'; import Search from './Search'; -function App () { - const options = { - method: 'GET', - headers: { - accept: 'application/json', - Authorization: 'eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIxYTEwYzJkZTdjZGQyYTNjOTM4YzEwMTBmOTk5ZDI0MSIsInN1YiI6IjY2Njc2NzI2NTM1YjMyMTc5Nzg1YTVkNSIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.0Oh7jejjYFuQKbX-ZZkuCE2i7C_Nn5FmfKNwADZt6aQ' - } - }; - - fetch('https://api.themoviedb.org/3/authentication', options) - .then(response => response.json()) - .then(response => console.log(response)) - .catch(err => console.error(err)); +function App() { + const getMovieData = async () => { + const response = await fetch(`https://api.themoviedb.org/3/movie/now_playing?language=en-US&page=1&api_key=${import.meta.env.VITE_API_KEY}`, { + method: 'get', + headers: new Headers({ + 'Accept': 'application/json' + }), + }); + const data = await response.json(); + console.log("Fetched Data:", data); + }; return ( <>
-

Flixster

- +

Flixster

+
- -
-
- -
+ +
+
+ +
- ) + ); } -export default App +export default App; + + + diff --git a/src/MovieCard.jsx b/src/MovieCard.jsx index ee2b9f62..bc0cd526 100644 --- a/src/MovieCard.jsx +++ b/src/MovieCard.jsx @@ -3,9 +3,9 @@ import './MovieCard.css' function MovieCard(movie) { return (
- -

{movie.title}

-

{movie.rating}

+ +

{movie.title}

+

{movie.rating}

) } diff --git a/src/MovieList.jsx b/src/MovieList.jsx index 664f7b61..5bbeef14 100644 --- a/src/MovieList.jsx +++ b/src/MovieList.jsx @@ -1,4 +1,3 @@ -import.meta.env.VITE_API_KEY import './MovieList.css' import MovieCard from './MovieCard' @@ -31,8 +30,11 @@ function MovieList() { title="test" rating="10" /> - - + diff --git a/src/Search.jsx b/src/Search.jsx index 9fde74b6..ebd40474 100644 --- a/src/Search.jsx +++ b/src/Search.jsx @@ -1,17 +1,29 @@ -import './Search.css' +import './Search.css'; function Search() { - // const handleSearchChange = (event) => { - // let searchQuery = event.target.value; + const handleKeyUp = (event) => { + const input = event.target.value.toUpperCase(); + console.log("Search Input:", input); // Check what is being typed + + const movieTitles = document.querySelectorAll('.title'); + console.log("Titles Found:", movieTitles.length); // Check how many titles are found + + movieTitles.forEach(title => { + const isVisible = title.textContent.toUpperCase().includes(input); + console.log("Title:", title.textContent, "Visible:", isVisible); // Check each title and its visibility status + title.closest('.card').style.display = isVisible ? 'block' : 'none'; + }); + }; - // }; - - //value={searchQuery} onChange={handleSearchChange} - return ( -
- -
- ) + return ( +
+ +
+ ); } export default Search; \ No newline at end of file From 14a6f8e0504378d022b1561b195819b7ac47a33e Mon Sep 17 00:00:00 2001 From: Carson Wolber Date: Wed, 12 Jun 2024 00:41:57 -0700 Subject: [PATCH 04/11] modal, react-search, api fetch, and load (big push) --- package-lock.json | 33 +++++++++++++++++++++--- package.json | 1 + src/App.css | 10 +++++++- src/App.jsx | 64 +++++++++++++++++++++++++++++++++++++---------- src/Modal.css | 42 +++++++++++++++++++++++++++++++ src/Modal.jsx | 22 ++++++++++++++++ src/MovieCard.css | 24 +++++++++++++++++- src/MovieCard.jsx | 37 +++++++++++++++++++++------ src/MovieList.css | 7 ++---- src/MovieList.jsx | 51 ++++++++++++++----------------------- src/Search.jsx | 25 +++++------------- src/index.css | 2 ++ vite.config.js | 3 +++ 13 files changed, 238 insertions(+), 83 deletions(-) create mode 100644 src/Modal.css create mode 100644 src/Modal.jsx diff --git a/package-lock.json b/package-lock.json index 92a683d2..e64eb9d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "flixster", "version": "0.0.0", "dependencies": { + "focus-trap-react": "^10.2.3", "react": "^18.2.0", "react-dom": "^18.2.0" }, @@ -2313,6 +2314,28 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, + "node_modules/focus-trap": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.4.tgz", + "integrity": "sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==", + "dependencies": { + "tabbable": "^6.2.0" + } + }, + "node_modules/focus-trap-react": { + "version": "10.2.3", + "resolved": "https://registry.npmjs.org/focus-trap-react/-/focus-trap-react-10.2.3.tgz", + "integrity": "sha512-YXBpFu/hIeSu6NnmV2xlXzOYxuWkoOtar9jzgp3lOmjWLWY59C/b8DtDHEAV4SPU07Nd/t+nS/SBNGkhUBFmEw==", + "dependencies": { + "focus-trap": "^7.5.4", + "tabbable": "^6.2.0" + }, + "peerDependencies": { + "prop-types": "^15.8.1", + "react": ">=16.3.0", + "react-dom": ">=16.3.0" + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -3193,7 +3216,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -3457,7 +3479,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -3519,8 +3540,7 @@ "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-refresh": { "version": "0.14.0", @@ -3933,6 +3953,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", diff --git a/package.json b/package.json index eded5715..fd60fea0 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "preview": "vite preview" }, "dependencies": { + "focus-trap-react": "^10.2.3", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/src/App.css b/src/App.css index fe2a33cf..8f012ac4 100644 --- a/src/App.css +++ b/src/App.css @@ -1,3 +1,4 @@ + header { height: 10vh; background-color: #457462; @@ -9,6 +10,7 @@ header { h1 { color: #ee892f; margin-left: 2%; + font-size: 40pt; } footer { @@ -17,7 +19,6 @@ footer { justify-content: center; align-self: center; bottom: 0; - position: fixed; display: flex; width: 100%; } @@ -29,3 +30,10 @@ footer { } +.App { + width: 100%; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} \ No newline at end of file diff --git a/src/App.jsx b/src/App.jsx index a2542fed..12099fc5 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,32 +1,70 @@ import './App.css'; import MovieList from './MovieList'; import Search from './Search'; +import { useState, useEffect } from 'react'; function App() { - const getMovieData = async () => { - const response = await fetch(`https://api.themoviedb.org/3/movie/now_playing?language=en-US&page=1&api_key=${import.meta.env.VITE_API_KEY}`, { - method: 'get', - headers: new Headers({ - 'Accept': 'application/json' - }), - }); - const data = await response.json(); - console.log("Fetched Data:", data); + const [movieData, setMovieData] = useState([]); + const [searchQuery, setSearchQuery] = useState(''); + const [searchData, setSearchData] = useState([]); + const [page, setPage] = useState(1); + useEffect(() => { + fetchData() + }, []) + + useEffect(() => { + const filterSearchData = () => { + if(!searchQuery) { + setSearchData(movieData); + } else { + const filteredData = movieData.filter(movie => + movie.title.toUpperCase().includes(searchQuery.toUpperCase()) + ); + setSearchData(filteredData); + } + }; + filterSearchData(); + }, [searchQuery, movieData]); + + useEffect(() => { + console.log('click') + fetchData() + }, [page]); + + const increment = () => { + setPage(page+1) }; + const fetchData = async () => { + try { + const response = await fetch(`https://api.themoviedb.org/3/movie/now_playing?language=en-US&page=${page}&api_key=${import.meta.env.VITE_API_KEY}`); + if (!response.ok) { + throw new Error('Network response was not ok'); + } + const data = await response.json(); + console.log(data.results) + setMovieData(movieData.concat(data.results)); + } catch (error) { + console.error('Fetch error:', error); + } + }; + + + return ( - <> + <>

Flixster

- +
- +
- +
+ ); } diff --git a/src/Modal.css b/src/Modal.css new file mode 100644 index 00000000..719c84f7 --- /dev/null +++ b/src/Modal.css @@ -0,0 +1,42 @@ +/* .modal { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: aliceblue; + z-index: 1000; + transition: n; + } */ + + .modal { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: aliceblue; + z-index: 1000; + width: auto; /* Adjust based on content */ + max-width: 90%; /* Adjust based on viewport */ + padding: 20px; + box-shadow: 0 4px 8px rgba(0,0,0,0.5); + animation: fadeInScaleUp 0.3s ease-out forwards; +} +@keyframes fadeInScaleUp { + from { + opacity: 0; + transform: scale(0.95) translate(-50%, -50%); + } + to { + opacity: 1; + transform: scale(1) translate(-50%, -50%); + } +} + + .modal img { + width: 100%; + height: auto; + max-width: 20vw; + display: block; + margin: 0 auto; + } + diff --git a/src/Modal.jsx b/src/Modal.jsx new file mode 100644 index 00000000..7c15b371 --- /dev/null +++ b/src/Modal.jsx @@ -0,0 +1,22 @@ +import './Modal.css'; +function Modal({ isOpen, imgSrc, title, genres, overview, date, closeModal }) { + const baseImgURL = "https://image.tmdb.org/t/p/w500"; + + if (!isOpen) { + return null; + } + + return ( +
+ +

{title}

+ {`Poster +

{`Release date: ${date}`}

+

{`Overview: ${overview}`}

+

{`Genres: ${genres}`}

+
+ ); +} + +export default Modal; + diff --git a/src/MovieCard.css b/src/MovieCard.css index 43d3dc7b..fdca5c91 100644 --- a/src/MovieCard.css +++ b/src/MovieCard.css @@ -1,5 +1,27 @@ .card { border: 1px solid black; border-radius: 8px; - margin: 2%; + margin: 10px; + width: 200px; + height: 400px; + max-width: 90%; + overflow: visible; + box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); + cursor: pointer; + transition: transform 0.1s; +} + +.card img { + width: 100%; + height: auto; + display: block; +} + +/* +.card:hover { + box-shadow: 0 12px 24px 0 rgba(0, 0, 0, 0.5); +} */ + +.card:hover { + transform: scale(1.04); } \ No newline at end of file diff --git a/src/MovieCard.jsx b/src/MovieCard.jsx index bc0cd526..9a9d9e33 100644 --- a/src/MovieCard.jsx +++ b/src/MovieCard.jsx @@ -1,13 +1,34 @@ -import './MovieCard.css' +import Modal from './Modal'; +import './MovieCard.css'; +import { useState } from 'react'; + +function MovieCard({ imgSrc, title, rating, genres, overview, date }) { + const [modalView, setModalView] = useState(false); + const baseImgURL = "https://image.tmdb.org/t/p/w500"; + + const showModal = (e) => { + e.stopPropagation(); + setModalView(true); + }; -function MovieCard(movie) { return ( -
- -

{movie.title}

-

{movie.rating}

-
- ) + <> +
+ +

{title}

+

{`Rating: ${rating}`}

+ +
+ + + ); } export default MovieCard; \ No newline at end of file diff --git a/src/MovieList.css b/src/MovieList.css index eab1995a..ee587afe 100644 --- a/src/MovieList.css +++ b/src/MovieList.css @@ -1,12 +1,9 @@ .list { text-align: center; - /* display: grid; - grid-template-columns: auto auto auto auto auto; - gap: 1vw; - */ - margin: 1vw 1vw 0 1vw; display: flex; flex-direction: row; flex-wrap: wrap; justify-content: center; + gap: 1vw; + align-items: center; } \ No newline at end of file diff --git a/src/MovieList.jsx b/src/MovieList.jsx index 5bbeef14..2abe55fa 100644 --- a/src/MovieList.jsx +++ b/src/MovieList.jsx @@ -1,44 +1,31 @@ import './MovieList.css' import MovieCard from './MovieCard' -function MovieList() { + + +function MovieList({ data }) { return (
- - - - - - + {data.map(movie => ( +
+ +
+ + + ))} +
- ) + ); } export default MovieList; \ No newline at end of file diff --git a/src/Search.jsx b/src/Search.jsx index ebd40474..bb26c3aa 100644 --- a/src/Search.jsx +++ b/src/Search.jsx @@ -1,27 +1,14 @@ import './Search.css'; -function Search() { - const handleKeyUp = (event) => { - const input = event.target.value.toUpperCase(); - console.log("Search Input:", input); // Check what is being typed - - const movieTitles = document.querySelectorAll('.title'); - console.log("Titles Found:", movieTitles.length); // Check how many titles are found - - movieTitles.forEach(title => { - const isVisible = title.textContent.toUpperCase().includes(input); - console.log("Title:", title.textContent, "Visible:", isVisible); // Check each title and its visibility status - title.closest('.card').style.display = isVisible ? 'block' : 'none'; - }); - }; +function Search({searchQuery , setSearchQuery}) { + + const handleSearchChange = (event) => { + setSearchQuery(event.target.value) + }; return (
- +
); } diff --git a/src/index.css b/src/index.css index e1faed1a..00f14d80 100644 --- a/src/index.css +++ b/src/index.css @@ -2,6 +2,8 @@ body { margin: 0; font-family: Arial, sans-serif; background-color: #f4f4f4; + align-items: center; + width: 100%; } button { diff --git a/vite.config.js b/vite.config.js index 5a33944a..ae72c212 100644 --- a/vite.config.js +++ b/vite.config.js @@ -4,4 +4,7 @@ import react from '@vitejs/plugin-react' // https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], + server: { + open: true, + }, }) From 128832117d77d2663643264b2cdb6d2ba865b49c Mon Sep 17 00:00:00 2001 From: Carson Wolber Date: Thu, 13 Jun 2024 23:52:05 -0700 Subject: [PATCH 05/11] this push adds sort and filer, delegates imperative js functions to be exported from utils, changes the state object approach into a single state, adds an empty message response if no movies match search, removes the filterData function in favor of inserting searches, filters, and sorts into the url in fetchData, adds comments to helpers and areas of nontrivial logic, and adds logic to display a placeholder image in cards and modals for movies that do not have an image source value (I know this is a ridicously large push Im sorry, meeting today made expectations here much clearer:/) --- package-lock.json | 399 +++++++++++++++++++++++++++++--- package.json | 3 +- src/App.css | 13 +- src/App.jsx | 106 +++++---- src/Filter.css | 4 + src/Filter.jsx | 51 ++++ src/Modal.css | 24 +- src/Modal.jsx | 38 ++- src/MovieCard.css | 8 +- src/MovieCard.jsx | 26 ++- src/MovieList.jsx | 3 +- src/Search.jsx | 2 +- src/Sort.css | 5 + src/Sort.jsx | 52 +++-- src/assets/movieplaceholder.jpg | Bin 0 -> 10877 bytes src/index.css | 7 +- src/utils/utils.js | 60 +++++ utils/utils.js | 0 18 files changed, 675 insertions(+), 126 deletions(-) create mode 100644 src/Filter.css create mode 100644 src/Filter.jsx create mode 100644 src/assets/movieplaceholder.jpg create mode 100644 src/utils/utils.js delete mode 100644 utils/utils.js diff --git a/package-lock.json b/package-lock.json index e64eb9d5..67a28b8d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,8 @@ "dependencies": { "focus-trap-react": "^10.2.3", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-select": "^5.8.0" }, "devDependencies": { "@types/react": "^18.2.66", @@ -49,7 +50,6 @@ "version": "7.24.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", - "dev": true, "dependencies": { "@babel/highlight": "^7.24.2", "picocolors": "^1.0.0" @@ -166,7 +166,6 @@ "version": "7.24.3", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", - "dev": true, "dependencies": { "@babel/types": "^7.24.0" }, @@ -230,7 +229,6 @@ "version": "7.24.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -239,7 +237,6 @@ "version": "7.22.20", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -271,7 +268,6 @@ "version": "7.24.2", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", - "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", @@ -324,6 +320,17 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz", + "integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.24.0", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", @@ -363,7 +370,6 @@ "version": "7.24.0", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", - "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", @@ -373,6 +379,125 @@ "node": ">=6.9.0" } }, + "node_modules/@emotion/babel-plugin": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@emotion/cache": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", + "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", + "dependencies": { + "@emotion/memoize": "^0.8.1", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/react": { + "version": "11.11.4", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", + "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", + "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", + "dependencies": { + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", @@ -812,6 +937,28 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.2.tgz", + "integrity": "sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg==", + "dependencies": { + "@floating-ui/utils": "^0.2.0" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.5.tgz", + "integrity": "sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==", + "dependencies": { + "@floating-ui/core": "^1.0.0", + "@floating-ui/utils": "^0.2.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz", + "integrity": "sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==" + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", @@ -1170,17 +1317,20 @@ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, "node_modules/@types/prop-types": { "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "dev": true + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" }, "node_modules/@types/react": { "version": "18.2.74", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.74.tgz", "integrity": "sha512-9AEqNZZyBx8OdZpxzQlaFEVCSFUM2YXJH46yPOiOpm078k6ZLOCcuAzGum/zK8YBwY+dbahVNbHrbgrAwIRlqw==", - "dev": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -1195,6 +1345,14 @@ "@types/react": "*" } }, + "node_modules/@types/react-transition-group": { + "version": "4.4.10", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", + "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", @@ -1270,7 +1428,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -1438,6 +1595,36 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/babel-plugin-macros/node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1509,7 +1696,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, "engines": { "node": ">=6" } @@ -1538,7 +1724,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -1552,7 +1737,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "dependencies": { "color-name": "1.1.3" } @@ -1560,8 +1744,7 @@ "node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/concat-map": { "version": "0.0.1", @@ -1575,6 +1758,21 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1592,8 +1790,7 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/data-view-buffer": { "version": "1.0.1", @@ -1715,12 +1912,29 @@ "node": ">=6.0.0" } }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/electron-to-chromium": { "version": "1.4.724", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.724.tgz", "integrity": "sha512-RTRvkmRkGhNBPPpdrgtDKvmOEYTrPlXDfc0J/Nfq5s29tEahAwhiX4mmhNzj6febWMleulxVYPh7QwCSL/EldA==", "dev": true }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-abstract": { "version": "1.23.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", @@ -1930,7 +2144,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, "engines": { "node": ">=0.8.0" } @@ -2278,6 +2491,11 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -2369,7 +2587,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -2533,7 +2750,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, "engines": { "node": ">=4" } @@ -2593,7 +2809,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -2601,6 +2816,14 @@ "node": ">= 0.4" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -2614,7 +2837,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -2681,6 +2903,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, "node_modules/is-async-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", @@ -2740,7 +2967,6 @@ "version": "2.13.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dev": true, "dependencies": { "hasown": "^2.0.0" }, @@ -3062,6 +3288,11 @@ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -3123,6 +3354,11 @@ "node": ">= 0.8.0" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -3164,6 +3400,11 @@ "yallist": "^3.0.2" } }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3382,7 +3623,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, "dependencies": { "callsites": "^3.0.0" }, @@ -3390,6 +3630,23 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3420,14 +3677,20 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/possible-typed-array-names": { "version": "1.0.0", @@ -3551,6 +3814,41 @@ "node": ">=0.10.0" } }, + "node_modules/react-select": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.8.0.tgz", + "integrity": "sha512-TfjLDo58XrhP6VG5M/Mi56Us0Yt8X7xD6cDybC7yoRMUNm7BGO7qk8J0TLQOua/prb8vUOtsfnXZwfm30HGsAA==", + "dependencies": { + "@babel/runtime": "^7.12.0", + "@emotion/cache": "^11.4.0", + "@emotion/react": "^11.8.1", + "@floating-ui/dom": "^1.0.1", + "@types/react-transition-group": "^4.4.0", + "memoize-one": "^6.0.0", + "prop-types": "^15.6.0", + "react-transition-group": "^4.3.0", + "use-isomorphic-layout-effect": "^1.1.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", @@ -3572,6 +3870,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, "node_modules/regexp.prototype.flags": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", @@ -3611,7 +3914,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, "engines": { "node": ">=4" } @@ -3821,6 +4123,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-js": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", @@ -3929,11 +4239,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -3945,7 +4259,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -3968,7 +4281,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, "engines": { "node": ">=4" } @@ -4124,6 +4436,19 @@ "punycode": "^2.1.0" } }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", + "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/vite": { "version": "5.2.7", "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.7.tgz", @@ -4285,6 +4610,14 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index fd60fea0..f63e9f91 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "dependencies": { "focus-trap-react": "^10.2.3", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-select": "^5.8.0" }, "devDependencies": { "@types/react": "^18.2.66", diff --git a/src/App.css b/src/App.css index 8f012ac4..84a847d3 100644 --- a/src/App.css +++ b/src/App.css @@ -14,12 +14,12 @@ h1 { } footer { - background-color: #457462; height: 10vh; - justify-content: center; - align-self: center; - bottom: 0; + background-color: #457462; + position: sticky; display: flex; + align-items: center; + justify-content: center; width: 100%; } @@ -36,4 +36,9 @@ footer { justify-content: center; align-items: center; flex-direction: column; +} + + +#emptymessage { + font-size: 16pt; } \ No newline at end of file diff --git a/src/App.jsx b/src/App.jsx index 12099fc5..df777bee 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,74 +1,98 @@ import './App.css'; import MovieList from './MovieList'; import Search from './Search'; +import Filter from './Filter'; +import Sort from './Sort'; import { useState, useEffect } from 'react'; function App() { + //a central state object map for all elements that interact with api requests allows us to ensure all fetch requests are in sync with all current relevant values + const [apiReqData, setApiReqData] = useState({ + search: '', + page: 1, + filters: [], + sort: '' + }); const [movieData, setMovieData] = useState([]); - const [searchQuery, setSearchQuery] = useState(''); - const [searchData, setSearchData] = useState([]); - const [page, setPage] = useState(1); - useEffect(() => { - fetchData() - }, []) - - useEffect(() => { - const filterSearchData = () => { - if(!searchQuery) { - setSearchData(movieData); - } else { - const filteredData = movieData.filter(movie => - movie.title.toUpperCase().includes(searchQuery.toUpperCase()) - ); - setSearchData(filteredData); - } - }; - filterSearchData(); - }, [searchQuery, movieData]); useEffect(() => { - console.log('click') - fetchData() - }, [page]); + fetchData(); + }, [apiReqData]); +//fetchData fetches data by inserting sort,search,and filter info onto the base API URL as needed and sets visible movies to correspond with API response + const fetchData = async () => { + try { + let url = `https://api.themoviedb.org/3/discover/movie?language=en-US&include_adult=false&include_video=false&page=${apiReqData.page}&api_key=${import.meta.env.VITE_API_KEY}`; - const increment = () => { - setPage(page+1) - }; + if (apiReqData.search !== '') { + url = `https://api.themoviedb.org/3/search/movie?query=${encodeURIComponent(apiReqData.search)}&language=en-US&page=${apiReqData.page}&include_adult=false&api_key=${import.meta.env.VITE_API_KEY}`; + } + if (apiReqData.filters.length > 0) { + url += `&with_genres=${apiReqData.filters.join(',')}`; + } + if (apiReqData.sort !== ''){ + url += `&sort_by=${apiReqData.sort}` + } - const fetchData = async () => { - try { - const response = await fetch(`https://api.themoviedb.org/3/movie/now_playing?language=en-US&page=${page}&api_key=${import.meta.env.VITE_API_KEY}`); + const response = await fetch(url); if (!response.ok) { - throw new Error('Network response was not ok'); + throw new Error('Failed to fetch movies: ' + response.statusText); } const data = await response.json(); - console.log(data.results) - setMovieData(movieData.concat(data.results)); - } catch (error) { + // Update movieData by appending new results to existing data if not on the first page, otherwise replace existing data. + setMovieData(prevData => apiReqData.page > 1 ? [...prevData, ...data.results] : [...data.results]); + + } catch (error) { console.error('Fetch error:', error); } }; - + // All handlers work by updating the apiReqData state with new values for search, filters, sort, or page whenever relevant while maintaining unchanged fields + const handleSearch = (query) => { + setApiReqData({...apiReqData, search: query, page: 1}); + }; + + const handleFilter = (newFilters) => { + setApiReqData({...apiReqData, filters: newFilters, page: 1}); + }; + + const handleSort = (newSort) => { + setApiReqData({...apiReqData, sort: newSort, page: 1}); + }; + + const incrementPage = () => { + setApiReqData({...apiReqData, page: apiReqData.page + 1}); + }; + + const checkForEmptyMovie = () => { + if (movieData.length > 0) { + return ( + <> + +
+ +
+ + ); + } else { + return

No movies match your search for "{apiReqData.search}", try searching for something else :D

+ } + }; return ( <>

Flixster

- + + +
- + {checkForEmptyMovie()}
-
- -
- ); } export default App; - diff --git a/src/Filter.css b/src/Filter.css new file mode 100644 index 00000000..5637702b --- /dev/null +++ b/src/Filter.css @@ -0,0 +1,4 @@ +.filterbar { + margin-left: 4%; + z-index: 10000; +} \ No newline at end of file diff --git a/src/Filter.jsx b/src/Filter.jsx new file mode 100644 index 00000000..824a336b --- /dev/null +++ b/src/Filter.jsx @@ -0,0 +1,51 @@ +import './Filter.css' +import Select from 'react-select' +import makeAnimated from 'react-select/animated' + +function Filter({ setFilters }) { + const animatedComponents = makeAnimated(); + const filterOptions = [ + { value: 28, label: 'Action' }, + { value: 12, label: 'Adventure' }, + { value: 16, label: 'Animation' }, + { value: 35, label: 'Comedy' }, + { value: 80, label: 'Crime' }, + { value: 99, label: 'Documentary' }, + { value: 18, label: 'Drama' }, + { value: 10751, label: 'Family' }, + { value: 14, label: 'Fantasy' }, + { value: 36, label: 'History' }, + { value: 27, label: 'Horror' }, + { value: 10402, label: 'Music' }, + { value: 9648, label: 'Mystery' }, + { value: 10749, label: 'Romance' }, + { value: 878, label: 'Science Fiction' }, + { value: 10770, label: 'TV Movie' }, + { value: 53, label: 'Thriller' }, + { value: 10752, label: 'War' }, + { value: 37, label: 'Western' }, + ]; + + const handleChange = (selectedOptions) => { + const selectedGenres = selectedOptions ? selectedOptions.map(option => option.value) : []; + setFilters(selectedGenres); + }; + + return ( +
+ +
); } diff --git a/src/Sort.css b/src/Sort.css index e69de29b..d20f4dfe 100644 --- a/src/Sort.css +++ b/src/Sort.css @@ -0,0 +1,5 @@ +.sortbar { + margin-left: 4%; + z-index: 10000; + margin-right: 1%; +} \ No newline at end of file diff --git a/src/Sort.jsx b/src/Sort.jsx index 1b0a3224..028e6f5a 100644 --- a/src/Sort.jsx +++ b/src/Sort.jsx @@ -1,19 +1,45 @@ -// import './Sort.css' +import './Sort.css' +import Select from 'react-select' +import makeAnimated from 'react-select/animated' + +function Sort({ setSort }) { + const animatedComponents = makeAnimated(); + const sortOptions = [ + { value: 'release_date.desc', label: 'Release Date (descending)' }, + {value: 'release_date.asc', label: 'Release Date (ascending)'}, + { value: 'vote_average.desc', label: 'Rating (descending)' }, + { value: 'vote_average.asc', label: 'Rating (ascending)' }, + { value: 'original_title.desc', label: 'Alphabetical (descending)' }, + { value: 'original_title.asc', label: 'Alphabetical (ascending)' }, + ]; + const handleChange = (selectedOption) => { + let sort = selectedOption ? selectedOption.value : '' + setSort(sort); + }; + + return ( +
+