-
Notifications
You must be signed in to change notification settings - Fork 219
feat: Changes #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 3 commits
b410044
7a93518
014ac30
c16b840
f233af4
bc4a6be
13fc4aa
620c220
58dd950
59e2a73
e82fdd3
7091ba2
0d07db0
fff11a0
9dd0287
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,3 +22,4 @@ dist-ssr | |
| *.njsproj | ||
| *.sln | ||
| *.sw? | ||
| .env | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,20 @@ | ||
| import { useState } from 'react' | ||
| import './App.css' | ||
| import MovieList from "./MovieList" | ||
| import "../public/movie.png" | ||
|
|
||
| const App = () => { | ||
| return ( | ||
| <div className="App"> | ||
|
|
||
| <header className='App-header'> | ||
| <div className='title'> | ||
| <h1>Flixster</h1> | ||
| <img src="../public/movie.png" alt="" /> | ||
| </div> | ||
|
|
||
| </header> | ||
| <MovieList /> | ||
| </div> | ||
| ); | ||
| } | ||
|
|
||
| export default App |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| .card { | ||
| display: flex; | ||
| flex-direction: column; | ||
| width: 200px; | ||
| height: 375px; | ||
| border: solid black; | ||
| background-color: white; | ||
| margin: 10px; | ||
| box-shadow: 12px 12px 2px 1px rgba(0, 0, 0, 0.582); | ||
| position: relative; | ||
| top: 0; | ||
| transition: top ease 0.5s; | ||
| } | ||
| .card:hover { | ||
| top: -15px; | ||
| cursor: pointer; | ||
| } | ||
|
|
||
| .img-container { | ||
| width: 100%; | ||
| height: 80%; | ||
| background-color: #ccc; | ||
| overflow: contain; | ||
| } | ||
|
|
||
| .img-container img { | ||
| width: 100%; | ||
| height: 100%; | ||
| object-fit: contain; | ||
| } | ||
|
|
||
| .txt-container { | ||
| text-align: center; | ||
| display: flex; | ||
| flex-direction: column; | ||
| justify-content: center; | ||
| align-items: center; | ||
| height: 20%; | ||
|
|
||
| } | ||
|
|
||
| .txt-container h2, .txt-container p { | ||
| font-size: 15px; | ||
| margin: 0%; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| import "./MovieCard.css"; | ||
| const MovieCard = ({key, poster, title, rating}) => { | ||
|
|
||
| return(//using info from MovieList to create element | ||
| <div className="card"> | ||
| <div className="img-container"> | ||
| <img src={poster} alt="Movie Poster" /> | ||
| </div> | ||
| <div className="txt-container"> | ||
| <h2>{title}</h2> | ||
| <p>{rating}</p> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } | ||
| export default MovieCard; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| .movie-row { | ||
| display: flex; | ||
| flex-wrap: wrap; | ||
| justify-content: space-between; /* Center cards horizontally */ | ||
| padding: 20px; | ||
| width: 75%; | ||
| margin: 0 auto; | ||
|
|
||
|
|
||
| } | ||
|
|
||
| .load-btn { | ||
| width: 100%; | ||
| float: left; | ||
| margin-top: 30px; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| import { useState, useEffect } from "react"; | ||
| import MovieCard from "./MovieCard"; | ||
| import "./MovieList.css"; | ||
|
|
||
| // Purpose: Create card elements from API info | ||
| const MovieList = () => { | ||
| const [data, setData] = useState([]); | ||
| const [page, updatePage] = useState(1); | ||
| const [searchText, updateSearchText] = useState(""); | ||
|
|
||
| const searchMovies = () => { | ||
| updatePage(1); | ||
| setData([]); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might not need this as data is being set in the fetchData function anyway |
||
| fetchData(); | ||
| }; | ||
|
|
||
| const resetPage = () => { | ||
| console.log("resetPage"); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove console |
||
| updatePage( | ||
| // make sure that fetch data runs after updating prevPage | ||
| (prevPage) => prevPage + 1, | ||
| () => { | ||
| fetchData(); | ||
| } | ||
| ); | ||
| }; | ||
|
|
||
| const options = { | ||
| method: "GET", | ||
| headers: { | ||
| accept: "application/json", | ||
| Authorization: `Bearer ${import.meta.env.VITE_TOKEN}`, //private token used to access api | ||
| }, | ||
| }; | ||
|
|
||
| const fetchData = async () => { | ||
| if (searchText === "") { | ||
| const resp = await fetch( | ||
| `https://api.themoviedb.org/3/movie/now_playing?language=en-US&page=${page}`, | ||
| options | ||
| ); //fills link | ||
| const Data = await resp.json(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. name it data or moviesList instead? |
||
| if (page === 1) { | ||
| setData([...Data.results]); | ||
| } else { | ||
| setData((prevData) => [...prevData, ...Data.results]); //appends results to end | ||
| } | ||
| console.log("prev", Data.results); | ||
| } else { | ||
| const resp = await fetch( | ||
| `https://api.themoviedb.org/3/search/movie?query=${searchText}&include_adult=false&language=en-US&page=${page}`, | ||
| options | ||
| ); | ||
| const Data = await resp.json(); | ||
| if (page === 1) { | ||
| setData([...Data.results]); | ||
| } else { | ||
| setData((prevData) => [...prevData, ...Data.results]); //appends results to end | ||
| } | ||
| } | ||
| }; | ||
| useEffect(() => { | ||
| fetchData(); | ||
| }, [page]); //adds to update for every new page | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can probably remove page from this dependency array, as we are calling API once page is changed. |
||
|
|
||
| return ( | ||
| //creates movie card element | ||
| <> | ||
| <div> | ||
| <input | ||
| type="text" | ||
| onChange={(e) => updateSearchText(e.target.value)} | ||
| value={searchText} | ||
| /> | ||
| <button onClick={searchMovies}>Search</button> | ||
| </div> | ||
| <div className="movie-row"> | ||
| {data.length > 0 ? ( | ||
| data.map((movie) => ( | ||
| <MovieCard | ||
| key={movie.id} | ||
| title={movie.title} | ||
| poster={`https://image.tmdb.org/t/p/original${movie.poster_path}`} | ||
| rating={Math.round(movie.vote_average * 100) / 100} //get two decimal points | ||
| /> | ||
| )) | ||
| ) : ( | ||
| <p>Loading movies...</p> //error handle if data length == 0 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can probably say "No Movies found instead" |
||
| )} | ||
| <button className="load-btn" onClick={resetPage}> | ||
| Show More | ||
| </button> | ||
| </div> | ||
| </> | ||
| ); | ||
| }; | ||
| export default MovieList; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: use format to eliminate empty lines.