This commit is contained in:
andrzej 2024-05-05 23:59:33 +02:00
parent 5d6eaee4ba
commit da61b72402
7 changed files with 195 additions and 55 deletions

1
.gitignore vendored
View File

@ -23,3 +23,4 @@ dist-ssr
*.sln
*.sw?
src/conf.js
src/auth.json

View File

@ -1,42 +1,41 @@
#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
.flow-container {
display: flex;
flex-wrap: wrap;
width: 80%;
margin: auto;
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
.poster {
font-size: 2rem;
aspect-ratio: 3/4.5;
width: 25rem;
}
@keyframes logo-spin {
from {
transform: rotate(0deg);
.overlay {
margin: 0;
height: 100%;
width: 100%;
font-size: inherit;
color: white;
background-color: rgba(0, 0, 0, 0.5);
opacity: 0;
p {
font-size: 0.8em;
}
to {
transform: rotate(360deg);
h1 {
font-size: 1.6em;
margin: 0;
}
}
@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}
.card {
padding: 2em;
}
.read-the-docs {
color: #888;
.overlay:hover {
opacity: 1;
}

View File

@ -1,3 +1,4 @@
import './defaults.css'
import './App.css'
import { MovieWall } from './objects/movie-wall'
import { useState, useEffect } from 'react'
@ -11,11 +12,12 @@ export type Config = {
function App() {
const [config, setConfig] = useState<Config>({
language: "es",
region: "spain"
region: "spain",
page: 1
})
const [popularMovies, setPopularMovies] = useState([])
useEffect(() => { tmdb.getPopular(config, setPopularMovies) }, [])
useEffect(() => { console.log(popularMovies) }, [popularMovies])
const [movies, setMovies] = useState([])
useEffect(() => { tmdb.getPopular(config, setMovies) }, [])
useEffect(() => { console.log(movies) }, [movies])
return (
<>
<header>
@ -23,7 +25,9 @@ function App() {
</header>
<main>
Let's explore!
<MovieWall movies={popularMovies} />
<div className='flow-container'>
<MovieWall movies={movies} setMovies={setMovies} />
</div>
</main>
</>

62
src/defaults.css Normal file
View File

@ -0,0 +1,62 @@
*,
*::before,
*::after {
box-sizing: border-box;
}
img {
display: block;
max-width: 100%;
}
menu:not(article menu),
ol:not(article ol),
ul:not(article ul) {
list-style: none;
}
menu,
ol,
ul {
padding-left: 0;
}
article ol,
article ul {
list-style-position: inside;
}
a {
/* Places underlines below the descenders */
text-underline-position: under;
/* Sets the thickness as a percentage of the font size */
text-decoration-thickness: 8;
}
/* <html> = the root */
html {
font-size: 62.5%;
/* (62.5/100) * 16px = 10px */
-webkit-text-size-adjust: none;
/* for iOS Safari */
text-size-adjust: none;
/* for other mobile browsers */
}
@media (prefers-reduced-motion: no-preference) {
html {
scroll-behavior: smooth;
}
}
label,
button,
select,
summary,
[type=radio],
[type=submit],
[type=checkbox] {
cursor: pointer;
}

19
src/functions.tsx Normal file
View File

@ -0,0 +1,19 @@
/**
* Move array item from provided index to specified index
* @remarks 'to' index refers to position in original array, i.e. if to > from, to = to -1
* @param array
* @param from - the index of the item we want moved
* @param to - the index we want the item moved to
* @returns The modified array
*
* @beta
*/
export function relocateArrayItem(array: Array<any>, from: number, to: number) {
const newArray = structuredClone(array)
const element = newArray.splice(from, 1)[0]
newArray.splice(to < from ? to : to - 1, 0, element)
console.log("reordered array: ")
console.log(newArray)
return newArray
}

View File

@ -1,4 +1,5 @@
import { FC } from "react"
import React, { useState } from "react"
import { relocateArrayItem } from "../functions"
type Movie = {
id: string
@ -24,17 +25,27 @@ const sampleData = {
vote_count: 52
}
interface MovieWallProps extends React.ComponentPropsWithRef<"div"> {
movies: Array<Movie>;
setMovies: Function;
}
export const MovieWall: FC<{ movies: Array<Movie> }> = (props) => {
const movies = props.movies
export function MovieWall({ movies, setMovies }: MovieWallProps) {
function moveMovieToFront(index: number) {
setMovies((prev: Array<Movie>) => { return relocateArrayItem(prev, index, 0) })
}
function listSimilarMovies(movie: Movie) {
}
const posters = []
const posters: Array<React.Component> = []
for (let i = 0; i < movies.length; i++) {
const movie = movies[i]
posters.push(
<Poster movie={movie} />
<Poster movie={movie} key={movie.id} index={i} moveMovieToFront={moveMovieToFront} />
)
}
return <>
@ -42,15 +53,26 @@ export const MovieWall: FC<{ movies: Array<Movie> }> = (props) => {
</>
}
type PosterProps = {
interface PosterProps extends React.ComponentPropsWithRef<"div"> {
movie: Movie;
moveMovieToFront: Function;
index: number;
}
function Poster({ movie }: PosterProps) {
return <a href={"https://www.themoviedb.org/movie/" + movie.id}>
<h1>{movie.title}</h1>
<p>{movie.overview}</p>
<img src={"https://image.tmdb.org/t/p/w500/" + movie.poster_path} />
</a>
function Poster({ movie, index, moveMovieToFront: onclick }: PosterProps) {
const [style, setStyle] = useState({
backgroundImage: "url(https://image.tmdb.org/t/p/w500/" + movie.poster_path + ")",
backgroundSize: "cover",
alignSelf: "auto",
color: "inherit"
})
return <div className="poster" style={style}>
<div className="overlay" onClick={() => { onclick(index) }}>
<h1>{movie.title}</h1>
<p>{movie.overview}</p>
</div>
</div>
}

View File

@ -10,15 +10,48 @@ const tmdb = axios.create({
}
})
export default {
getPopular: async function({ language, region }: Config, callback: Function) {
let res = await tmdb.get('/popular?language=en-US&page=1',
/**
* Calls tmdb API/popular and then fires the callback with res.data.results as argument
* @param {Function} callback
* @returns {boolean}
*/
getPopular: async function({ language, region, page }: Config, callback: Function) {
let res = await tmdb.get('/popular',
{
params: {
language,
region
region,
page
}
})
res = res.data.results
callback(res)
console.log(res)
if (res.status === 200) {
res = res.data.results
callback(res)
return true
} else {
throw Error("API call failed! Response: " + JSON.stringify(res))
}
},
/**
* Calls TMDB/similar
*/
getSimilar: async function({ language, page }: Config, id: number, callback: Function) {
let res = await tmdb.get(id + '/similar', {
params: {
language,
page
}
})
console.log(res)
if (res.status === 200) {
res = res.data.results
callback(res)
return true
} else {
throw Error("API call failed! Response: " + JSON.stringify(res))
}
}
}