Started adding responsiveness

This commit is contained in:
“Henry-Hiles” 2022-11-03 14:12:52 -04:00
parent 93c6bc7e80
commit 7b2bd29f62
13 changed files with 230 additions and 173 deletions

View file

@ -2,7 +2,7 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<!-- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> --> <link rel="icon" type="image/svg+xml" href="/icon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>React movie viewer</title> <title>React movie viewer</title>
</head> </head>

5
public/icon.svg Normal file
View file

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-camera-reels-fill" viewBox="0 0 16 16">
<path d="M6 3a3 3 0 1 1-6 0 3 3 0 0 1 6 0z"/>
<path d="M9 6a3 3 0 1 1 0-6 3 3 0 0 1 0 6z"/>
<path d="M9 6h.5a2 2 0 0 1 1.983 1.738l3.11-1.382A1 1 0 0 1 16 7.269v7.462a1 1 0 0 1-1.406.913l-3.111-1.382A2 2 0 0 1 9.5 16H2a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h7z"/>
</svg>

After

Width:  |  Height:  |  Size: 404 B

View file

@ -4,11 +4,9 @@ import Movie from "pages/Movie"
import Actor from "pages/Actor" import Actor from "pages/Actor"
import Ratings from "pages/Ratings" import Ratings from "pages/Ratings"
import styles from "styles/App.module.css" import styles from "styles/App.module.css"
import TopBar from "components/TopBar"
const App = () => ( const App = () => (
<div className={styles.App}> <div className={styles.App}>
<TopBar />
<Routes> <Routes>
<Route index element={<Home />} /> <Route index element={<Home />} />
<Route path="/movie/:movieId" element={<Movie />} /> <Route path="/movie/:movieId" element={<Movie />} />

View file

@ -1,15 +1,44 @@
import { useEffect, useState } from "react"
import { Link } from "react-router-dom" import { Link } from "react-router-dom"
import styles from "styles/TopBar.module.css" import styles from "styles/TopBar.module.css"
const TopBar = () => ( const TopBar = ({ search, setSearch, absolute }) => {
<div className={styles.Container}> const [width, setWidth] = useState(window.innerWidth)
<Link to="/">
<h1 className={styles.Title}>React Movie Finder</h1> useEffect(() => {
</Link> const handleResize = () => setWidth(window.innerWidth)
<Link to="/ratings">
<h1>Your ratings</h1> window.addEventListener("resize", handleResize)
</Link>
</div> return () => window.removeEventListener("resize", handleResize)
) }, [])
return (
<div
className={`${styles.Container} ${
absolute && width > 1000 ? styles.Absolute : ""
} ${setSearch ? styles.HasSearch : ""}`}
>
<Link to="/">
<h1 className={styles.Title}>React Movie Finder</h1>
</Link>
{setSearch && (
<input
type="text"
className={styles.Search}
value={search}
autoFocus
placeholder="Search for movies..."
onChange={({ target }) => setSearch(target.value)}
/>
)}
<Link to="/ratings" className={styles.Ratings}>
<h1>Your ratings</h1>
</Link>
</div>
)
}
export default TopBar export default TopBar

View file

@ -3,6 +3,7 @@ import config from "config"
import styles from "styles/Actor.module.css" import styles from "styles/Actor.module.css"
import { Link, useParams } from "react-router-dom" import { Link, useParams } from "react-router-dom"
import { GENRES } from "../constants" import { GENRES } from "../constants"
import TopBar from "components/TopBar"
const Actor = () => { const Actor = () => {
const { actorId } = useParams() const { actorId } = useParams()
@ -62,63 +63,70 @@ const Actor = () => {
}, [actorId]) }, [actorId])
return ( return (
<div className={styles.Container}> <>
<hr /> <TopBar />
<h1 className={styles.Name}>{actor?.name}</h1> <div className={styles.Container}>
<div className={styles.Section}> <hr />
<h2>Biography</h2> <h1 className={styles.Name}>{actor?.name}</h1>
<div className={styles.Description}> <div className={styles.Section}>
{actor?.biography ? ( <h2>Biography</h2>
<a <div className={styles.Description}>
href="#" {actor?.biography ? (
className={styles.Collapse} <a
onClick={() => href="#"
setCollapsed((collapsed) => !collapsed) className={styles.Collapse}
} onClick={() =>
> setCollapsed((collapsed) => !collapsed)
<p className={collapsed ? styles.Collapsed : ""}> }
{actor.biography} >
</p> <p
className={
collapsed ? styles.Collapsed : ""
}
>
{actor.biography}
</p>
<p className={styles.ReadMore}> <p className={styles.ReadMore}>
{collapsed ? "Read More" : "Read Less"} {collapsed ? "Read More" : "Read Less"}
</p> </p>
<p>{collapsed}</p> <p>{collapsed}</p>
</a> </a>
) : ( ) : (
<p>No biography available.</p> <p>No biography available.</p>
)} )}
</div>
</div>
<div className={styles.Section}>
<h2>Images</h2>
<div className={styles.Images}>
{images?.profiles.map((image) => (
<img
key={image.file_path}
className={styles.Image}
src={`https://image.tmdb.org/t/p/w300${image.file_path}`}
/>
))}
</div>
</div>
<div className={styles.Section}>
<h2>Movies</h2>
<div className={styles.Credits}>
{credits?.map((movie) => (
<Link
to={`/movie/${movie.id}`}
key={movie.id}
className={styles.Movie}
>
<img src={movie.posterUrl} />
<span>{movie.title}</span>
</Link>
))}
</div>
</div> </div>
</div> </div>
<div className={styles.Section}> </>
<h2>Images</h2>
<div className={styles.Images}>
{images?.profiles.map((image) => (
<img
key={image.file_path}
className={styles.Image}
src={`https://image.tmdb.org/t/p/w300${image.file_path}`}
/>
))}
</div>
</div>
<div className={styles.Section}>
<h2>Movies</h2>
<div className={styles.Credits}>
{credits?.map((movie) => (
<Link
to={`/movie/${movie.id}`}
key={movie.id}
className={styles.Movie}
>
<img src={movie.posterUrl} />
<span>{movie.title}</span>
</Link>
))}
</div>
</div>
</div>
) )
} }

View file

@ -47,14 +47,7 @@ const Home = () => {
return ( return (
<div className={styles.Container}> <div className={styles.Container}>
<input <TopBar search={search} setSearch={setSearch} />
type="text"
className={styles.Search}
value={search}
autoFocus
placeholder="Search for movies..."
onChange={({ target }) => setSearch(target.value)}
/>
<div className={styles.CardList}> <div className={styles.CardList}>
{movies?.map((movie) => ( {movies?.map((movie) => (
<Card key={movie.id} movie={movie} /> <Card key={movie.id} movie={movie} />

View file

@ -4,6 +4,7 @@ import styles from "styles/Movie.module.css"
import config from "config" import config from "config"
import useLocalStorage from "hooks/useLocalStorage" import useLocalStorage from "hooks/useLocalStorage"
import Rate from "components/Rate" import Rate from "components/Rate"
import TopBar from "components/TopBar"
const Movie = () => { const Movie = () => {
const { movieId } = useParams() const { movieId } = useParams()
@ -54,77 +55,78 @@ const Movie = () => {
run() run()
}, [movieId]) }, [movieId])
return movie ? ( return (
<div className={styles.Container}> <>
<div <TopBar absolute />
className={styles.Top} <div className={styles.Container}>
style={{ <div
backgroundImage: `url(${movie.backdropUrl})`, className={styles.Top}
}} style={{
> backgroundImage: `url(${movie?.backdropUrl})`,
<div className={styles.Summary}> }}
<h2 className={styles.Title}> >
{movie.title} - {movie.year} <div className={styles.Summary}>
</h2> <h2 className={styles.Title}>
<p>{movie.tagline}</p> {movie?.title} - {movie?.year}
<p className={styles.Overview}>{movie.overview}</p> </h2>
<p>{movie?.tagline}</p>
<p className={styles.Overview}>{movie?.overview}</p>
</div>
</div> </div>
</div> <div className={styles.Bottom}>
<div className={styles.Bottom}> <div className={styles.Tags}>
<div className={styles.Tags}> {movie?.genres.map((genre) => (
{movie.genres.map((genre) => ( <p key={genre}>{genre}</p>
<p key={genre}>{genre}</p>
))}
<p className={styles.Average}>
<span>
Average Rating: {movie.averageVote.toFixed(1)}
</span>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16"
>
<path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.282.95l-3.522 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z" />
</svg>
</p>
</div>
<div className={styles.Section}>
<h1 className={styles.Header}>Your Rating</h1>
<Rate rating={rating} setRating={setRating} />
<br />
<Link to="/ratings" className={styles.RatingsLink}>
Go to ratings
</Link>
</div>
<div className={styles.Section}>
<h1 className={styles.Header}>Actors</h1>
<div className={styles.Actors}>
{cast?.map((actor) => (
<Link
key={actor.id}
to={`/actor/${actor.id}`}
className={styles.Actor}
>
{actor.profile_path ? (
<img
src={`https://image.tmdb.org/t/p/w200${actor.profile_path}`}
alt={actor.name}
/>
) : (
<p>Image Unavailable</p>
)}
<h3>{actor.name}</h3>
</Link>
))} ))}
<p className={styles.Average}>
<span>
Average Rating: {movie?.averageVote.toFixed(1)}
</span>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16"
>
<path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.282.95l-3.522 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z" />
</svg>
</p>
</div>
<div className={styles.Section}>
<h1 className={styles.Header}>Your Rating</h1>
<Rate rating={rating} setRating={setRating} />
<br />
<Link to="/ratings" className={styles.RatingsLink}>
Go to ratings
</Link>
</div>
<div className={styles.Section}>
<h1 className={styles.Header}>Actors</h1>
<div className={styles.Actors}>
{cast?.map((actor) => (
<Link
key={actor.id}
to={`/actor/${actor.id}`}
className={styles.Actor}
>
{actor.profile_path ? (
<img
src={`https://image.tmdb.org/t/p/w200${actor.profile_path}`}
alt={actor.name}
/>
) : (
<p>Image Unavailable</p>
)}
<h3>{actor.name}</h3>
</Link>
))}
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </>
) : (
<div></div>
) )
} }

View file

@ -1,4 +1,5 @@
import Card from "components/Card" import Card from "components/Card"
import TopBar from "components/TopBar"
import useLocalStorage from "hooks/useLocalStorage" import useLocalStorage from "hooks/useLocalStorage"
import styles from "styles/Ratings.module.css" import styles from "styles/Ratings.module.css"
@ -11,18 +12,21 @@ const Ratings = () => {
]) ])
return ( return (
<div className={styles.Container}> <>
<hr /> <TopBar />
<div className={styles.CardList}> <div className={styles.Container}>
{ratings?.map((movie) => ( <hr />
<Card <div className={styles.CardList}>
key={movie.id} {ratings?.map((movie) => (
movie={movie} <Card
setRating={(rating) => setRating(rating, movie)} key={movie.id}
/> movie={movie}
))} setRating={(rating) => setRating(rating, movie)}
/>
))}
</div>
</div> </div>
</div> </>
) )
} }

View file

@ -3,7 +3,6 @@
flex-direction: column; flex-direction: column;
padding: 15px; padding: 15px;
color: white; color: white;
padding-top: 80px;
} }
.Name { .Name {
margin-top: 10px; margin-top: 10px;

View file

@ -3,7 +3,6 @@
align-items: center; align-items: center;
flex-direction: column; flex-direction: column;
gap: 1.5em; gap: 1.5em;
padding-top: 30px;
} }
.CardList { .CardList {
@ -15,14 +14,3 @@
gap: 20px; gap: 20px;
text-align: center; text-align: center;
} }
.Search {
padding: 0.5em;
border: 2px solid white;
color: white;
font: inherit;
width: 20em;
height: 3em;
border-radius: 10px;
background-color: var(--secondary);
}

View file

@ -5,7 +5,6 @@
.Top { .Top {
height: 100vh; height: 100vh;
display: flex; display: flex;
background-size: cover; background-size: cover;
background-position: center; background-position: center;
background-repeat: no-repeat; background-repeat: no-repeat;
@ -16,6 +15,7 @@
.Summary { .Summary {
background: linear-gradient(#00000035, black); background: linear-gradient(#00000035, black);
height: 15%; height: 15%;
overflow: scroll;
text-align: center; text-align: center;
} }
@ -50,12 +50,15 @@
.Tags { .Tags {
display: flex; display: flex;
gap: 10px; gap: 10px;
width: 100%;
overflow: scroll;
} }
.Tags > * { .Tags > * {
background-color: var(--primary); background-color: var(--primary);
padding: 5px 7px; padding: 5px 7px;
border-radius: 10px; border-radius: 10px;
white-space: nowrap;
} }
.Average { .Average {

View file

@ -5,7 +5,6 @@
gap: 1.5em; gap: 1.5em;
color: white; color: white;
padding: 10px; padding: 10px;
padding-top: 90px;
} }
.CardList { .CardList {

View file

@ -1,13 +1,42 @@
.Container.HasSearch {
--cols: 3;
}
.Container { .Container {
display: flex; display: grid;
width: 100%; width: 100%;
justify-content: space-between; grid-template-columns: repeat(var(--cols, 2), 1fr);
padding: 10px 20px; padding: 0 30px;
background-color: transparent; align-items: center;
position: absolute; background: linear-gradient(to bottom, #00000090, #00000000);
color: white; color: white;
} }
.Container h1 { .Container.Absolute {
color: white; position: absolute;
}
.Container a {
color: white;
text-decoration: none;
}
.Container a::hover {
text-decoration: underline;
}
.Search {
padding: 0.5em;
border: 2px solid white;
color: white;
font: inherit;
justify-self: center;
width: 20em;
height: 3em;
border-radius: 10px;
background-color: var(--secondary);
}
.Ratings {
justify-self: end;
} }