Compare commits
	
		
			2 Commits
		
	
	
		
			88ba270647
			...
			8225d77a99
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								
								 | 
						8225d77a99 | |
| 
							
							
								
								 | 
						5fcde524fe | 
							
								
								
									
										29
									
								
								src/App.css
								
								
								
								
							
							
						
						
									
										29
									
								
								src/App.css
								
								
								
								
							| 
						 | 
					@ -52,6 +52,11 @@ main {
 | 
				
			||||||
  font-size: 1.6rem;
 | 
					  font-size: 1.6rem;
 | 
				
			||||||
  background-color: rgba(0, 0, 0, 0.5);
 | 
					  background-color: rgba(0, 0, 0, 0.5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  min-height: 100%;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-direction: column;
 | 
				
			||||||
 | 
					  justify-content: flex-end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  h1 {
 | 
					  h1 {
 | 
				
			||||||
    font-size: 2em;
 | 
					    font-size: 2em;
 | 
				
			||||||
    margin: 0;
 | 
					    margin: 0;
 | 
				
			||||||
| 
						 | 
					@ -134,7 +139,7 @@ main {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#background {
 | 
					#background {
 | 
				
			||||||
  /* background-color: black; */
 | 
					  background-color: black;
 | 
				
			||||||
  position: absolute;
 | 
					  position: absolute;
 | 
				
			||||||
  width: 100%;
 | 
					  width: 100%;
 | 
				
			||||||
  height: 100%;
 | 
					  height: 100%;
 | 
				
			||||||
| 
						 | 
					@ -145,6 +150,24 @@ main {
 | 
				
			||||||
.CrossfadeImage {
 | 
					.CrossfadeImage {
 | 
				
			||||||
  width: 100%;
 | 
					  width: 100%;
 | 
				
			||||||
  height: 100%;
 | 
					  height: 100%;
 | 
				
			||||||
 | 
					  filter: blur(1rem) brightness(0.4);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#watch-providers {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  h1 {
 | 
				
			||||||
 | 
					    font-size: 1.6rem;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .watch-logos-container {
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    gap: 0.4rem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .watch-logo {
 | 
				
			||||||
 | 
					      width: 30px;
 | 
				
			||||||
 | 
					      aspect-ratio: 1/1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										16
									
								
								src/App.tsx
								
								
								
								
							
							
						
						
									
										16
									
								
								src/App.tsx
								
								
								
								
							| 
						 | 
					@ -7,11 +7,13 @@ import tmdb from './objects/tmdb'
 | 
				
			||||||
import { Sidebar } from './objects/sidebar'
 | 
					import { Sidebar } from './objects/sidebar'
 | 
				
			||||||
import { Movie } from './objects/movie-wall'
 | 
					import { Movie } from './objects/movie-wall'
 | 
				
			||||||
import CrossfadeImage from 'react-crossfade-image'
 | 
					import CrossfadeImage from 'react-crossfade-image'
 | 
				
			||||||
 | 
					import { WhereToWatch } from './objects/whereToWatch'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type Config = {
 | 
					export type Config = {
 | 
				
			||||||
  language: string,
 | 
					  language: string,
 | 
				
			||||||
  region: string,
 | 
					  region: string,
 | 
				
			||||||
  page: number,
 | 
					  page: number,
 | 
				
			||||||
 | 
					  locale: string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
class MovieClass implements Movie {
 | 
					class MovieClass implements Movie {
 | 
				
			||||||
  id = null
 | 
					  id = null
 | 
				
			||||||
| 
						 | 
					@ -26,13 +28,14 @@ function App() {
 | 
				
			||||||
  const [config, setConfig] = useState<Config>({
 | 
					  const [config, setConfig] = useState<Config>({
 | 
				
			||||||
    language: "es",
 | 
					    language: "es",
 | 
				
			||||||
    region: "spain",
 | 
					    region: "spain",
 | 
				
			||||||
    page: 1
 | 
					    page: 1,
 | 
				
			||||||
 | 
					    locale: "ES"
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
  const [movies, setMovies] = useState([new MovieClass()])
 | 
					  const [movies, setMovies] = useState([new MovieClass()])
 | 
				
			||||||
  const [backdrop, setBackdrop] = useState("")
 | 
					  const [backdrop, setBackdrop] = useState("")
 | 
				
			||||||
  const [chosenMovie, setChosenMovie] = useState(new MovieClass())
 | 
					  const [chosenMovie, setChosenMovie] = useState(new MovieClass())
 | 
				
			||||||
  const [similarMoviesAvailable, setSimilarMoviesAvailable] = useState(true)
 | 
					  const [similarMoviesAvailable, setSimilarMoviesAvailable] = useState(true)
 | 
				
			||||||
 | 
					  const [watchProviders, setWatchProviders] = useState({})
 | 
				
			||||||
  useEffect(() => { tmdb.getPopular(config, setMovies) }, [])
 | 
					  useEffect(() => { tmdb.getPopular(config, setMovies) }, [])
 | 
				
			||||||
  useEffect(() => {
 | 
					  useEffect(() => {
 | 
				
			||||||
    const bgString = chosenMovie.backdrop_path ?
 | 
					    const bgString = chosenMovie.backdrop_path ?
 | 
				
			||||||
| 
						 | 
					@ -40,9 +43,12 @@ function App() {
 | 
				
			||||||
      : tmdb.makeBgImgUrl(movies[0]?.backdrop_path ?? "")
 | 
					      : tmdb.makeBgImgUrl(movies[0]?.backdrop_path ?? "")
 | 
				
			||||||
    setBackdrop(bgString)
 | 
					    setBackdrop(bgString)
 | 
				
			||||||
  }, [movies])
 | 
					  }, [movies])
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    tmdb.getWhereToWatch(chosenMovie, setWatchProviders, config)
 | 
				
			||||||
 | 
					  }, [chosenMovie])
 | 
				
			||||||
  const crossfadeImageStyles = {
 | 
					  const crossfadeImageStyles = {
 | 
				
			||||||
    width: "100%",
 | 
					    width: "2560px",
 | 
				
			||||||
 | 
					    minHeight: "100%",
 | 
				
			||||||
    aspectRatio: "16/9"
 | 
					    aspectRatio: "16/9"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
| 
						 | 
					@ -51,7 +57,7 @@ function App() {
 | 
				
			||||||
        <CrossfadeImage src={backdrop} style={crossfadeImageStyles} />
 | 
					        <CrossfadeImage src={backdrop} style={crossfadeImageStyles} />
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <main >
 | 
					      <main >
 | 
				
			||||||
        <Sidebar movie={chosenMovie} similarMoviesAvailable={similarMoviesAvailable} />
 | 
					        <Sidebar movie={chosenMovie} similarMoviesAvailable={similarMoviesAvailable} watchProviders={watchProviders} />
 | 
				
			||||||
        <div id="movie-wall-container">
 | 
					        <div id="movie-wall-container">
 | 
				
			||||||
          <MovieWall movies={movies}
 | 
					          <MovieWall movies={movies}
 | 
				
			||||||
            setMovies={setMovies}
 | 
					            setMovies={setMovies}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,11 +1,13 @@
 | 
				
			||||||
import React from "react";
 | 
					import React from "react";
 | 
				
			||||||
import { Movie } from "./movie-wall";
 | 
					import { Movie } from "./movie-wall";
 | 
				
			||||||
import tmdb from "./tmdb";
 | 
					import tmdb from "./tmdb";
 | 
				
			||||||
 | 
					import { WhereToWatch } from "./whereToWatch";
 | 
				
			||||||
export interface SidebarProps extends React.ComponentPropsWithRef<"div"> {
 | 
					export interface SidebarProps extends React.ComponentPropsWithRef<"div"> {
 | 
				
			||||||
  movie: Movie;
 | 
					  movie: Movie;
 | 
				
			||||||
  similarMoviesAvailable: boolean;
 | 
					  similarMoviesAvailable: boolean;
 | 
				
			||||||
 | 
					  watchProviders: {};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
export function Sidebar({ movie, similarMoviesAvailable }: SidebarProps) {
 | 
					export function Sidebar({ movie, similarMoviesAvailable, watchProviders }: SidebarProps) {
 | 
				
			||||||
  return <div id="sidebar">
 | 
					  return <div id="sidebar">
 | 
				
			||||||
    <h1>{movie?.title ?? "loading"}</h1>
 | 
					    <h1>{movie?.title ?? "loading"}</h1>
 | 
				
			||||||
    <figure>
 | 
					    <figure>
 | 
				
			||||||
| 
						 | 
					@ -20,6 +22,7 @@ export function Sidebar({ movie, similarMoviesAvailable }: SidebarProps) {
 | 
				
			||||||
      : movie.overview === "" ? "Resumen no disponible."
 | 
					      : movie.overview === "" ? "Resumen no disponible."
 | 
				
			||||||
        : movie.overview}
 | 
					        : movie.overview}
 | 
				
			||||||
    </p>
 | 
					    </p>
 | 
				
			||||||
 | 
					    <WhereToWatch watchProviders={watchProviders} />
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,7 +56,6 @@ export default {
 | 
				
			||||||
        setSimilarMoviesAvailable(true)
 | 
					        setSimilarMoviesAvailable(true)
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        setSimilarMoviesAvailable(false)
 | 
					        setSimilarMoviesAvailable(false)
 | 
				
			||||||
        console.log("SIMILAR NOT AVAILABLE")
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return true
 | 
					      return true
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
| 
						 | 
					@ -64,24 +63,15 @@ export default {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  /**
 | 
					  getWhereToWatch: async function(movie: Movie, setWatchProviders: Function, config: Config) {
 | 
				
			||||||
   *Calls TMDB/images, and sets the backdrop state accordingly
 | 
					    if (movie?.id) {
 | 
				
			||||||
   * 
 | 
					      let res = await tmdb.get(movie.id + "/watch/providers")
 | 
				
			||||||
   */
 | 
					      if (res.status == 200) {
 | 
				
			||||||
  getBackdrop: async function(movie: Movie, setBackdrop: Function) {
 | 
					        setWatchProviders(res.data.results[config.locale])
 | 
				
			||||||
    let res = await tmdb.get(movie.id + '/images')
 | 
					 | 
				
			||||||
    console.log(res)
 | 
					 | 
				
			||||||
    if (res.status === 200) {
 | 
					 | 
				
			||||||
      const file_path = res.data.backdrops[0].file_path
 | 
					 | 
				
			||||||
      console.log("file_path:" + file_path)
 | 
					 | 
				
			||||||
      const imgUrl = this.makeBgImgUrl(file_path)
 | 
					 | 
				
			||||||
      console.log("imgUrl: " + imgUrl)
 | 
					 | 
				
			||||||
      setBackdrop(imgUrl)
 | 
					 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        throw Error("API call failed! Response: " + JSON.stringify(res))
 | 
					        throw Error("API call failed! Response: " + JSON.stringify(res))
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  makeBgImgUrl:
 | 
					  makeBgImgUrl:
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					@ -103,5 +93,8 @@ export default {
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
    function(movie: Movie) {
 | 
					    function(movie: Movie) {
 | 
				
			||||||
      return "https://www.themoviedb.org/movie/" + movie.id
 | 
					      return "https://www.themoviedb.org/movie/" + movie.id
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  makeLogoPath: function(str: string) {
 | 
				
			||||||
 | 
					    return "https://image.tmdb.org/t/p/original/" + str
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,86 @@
 | 
				
			||||||
 | 
					import React from "react"
 | 
				
			||||||
 | 
					import tmdb from "./tmdb"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface WhereToWatchProps extends React.ComponentPropsWithRef<"div"> {
 | 
				
			||||||
 | 
					  watchProviders: {
 | 
				
			||||||
 | 
					    flatrate: Array<{}>;
 | 
				
			||||||
 | 
					    rent: Array<{}>;
 | 
				
			||||||
 | 
					    buy: Array<{}>;
 | 
				
			||||||
 | 
					    link: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const sampleData = {
 | 
				
			||||||
 | 
					  link: "https://www.themoviedb.org/movie/872585-oppenheimer/watch?locale=ES",
 | 
				
			||||||
 | 
					  rent: [{
 | 
				
			||||||
 | 
					    logo_path: "/7K6rVbpWXB6ByDI0PRzGGRXRBSY.jpg",
 | 
				
			||||||
 | 
					    provider_id: 149,
 | 
				
			||||||
 | 
					    provider_name: "Movistar Plus",
 | 
				
			||||||
 | 
					    display_priority: 12
 | 
				
			||||||
 | 
					  }],
 | 
				
			||||||
 | 
					  buy: [{
 | 
				
			||||||
 | 
					    logo_path: "/9ghgSC0MA082EL6HLCW3GalykFD.jpg",
 | 
				
			||||||
 | 
					    provider_id: 2,
 | 
				
			||||||
 | 
					    provider_name: "Apple TV",
 | 
				
			||||||
 | 
					    display_priority: 4
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    logo_path: "/bZvc9dXrXNly7cA0V4D9pR8yJwm.jpg",
 | 
				
			||||||
 | 
					    provider_id: 35,
 | 
				
			||||||
 | 
					    provider_name: "Rakuten TV",
 | 
				
			||||||
 | 
					    display_priority: 13
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    logo_path: "/8z7rC8uIDaTM91X0ZfkRf04ydj2.jpg",
 | 
				
			||||||
 | 
					    provider_id: 3,
 | 
				
			||||||
 | 
					    provider_name: "Google Play Movies",
 | 
				
			||||||
 | 
					    display_priority: 15
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    logo_path: "/5vfrJQgNe9UnHVgVNAwZTy0Jo9o.jpg",
 | 
				
			||||||
 | 
					    provider_id: 68,
 | 
				
			||||||
 | 
					    provider_name: "Microsoft Store",
 | 
				
			||||||
 | 
					    display_priority: 16
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    logo_path: "/seGSXajazLMCKGB5hnRCidtjay1.jpg",
 | 
				
			||||||
 | 
					    provider_id: 10,
 | 
				
			||||||
 | 
					    provider_name: "Amazon Video",
 | 
				
			||||||
 | 
					    display_priority: 36
 | 
				
			||||||
 | 
					  }],
 | 
				
			||||||
 | 
					  flatrate: [{
 | 
				
			||||||
 | 
					    logo_path: "/gQbqEYd0C9uprYxEUqTM589qn8g.jpg",
 | 
				
			||||||
 | 
					    provider_id: 1773,
 | 
				
			||||||
 | 
					    provider_name: "SkyShowtime",
 | 
				
			||||||
 | 
					    display_priority: 9
 | 
				
			||||||
 | 
					  }]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					interface ProviderIconsProps extends React.ComponentPropsWithRef<"div"> {
 | 
				
			||||||
 | 
					  providerList: Array<{}>;
 | 
				
			||||||
 | 
					  link: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					function ProviderIcons({ providerList, link }: ProviderIconsProps) {
 | 
				
			||||||
 | 
					  const list = providerList.map((e: any, i: number) => {
 | 
				
			||||||
 | 
					    return <a href={link}><img src={tmdb.makeLogoPath(e.logo_path)} className="watch-logo" key={e.provider_id + "_" + i} /></a>
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  return <div className="watch-logos-container">
 | 
				
			||||||
 | 
					    {list}
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function WhereToWatch({ watchProviders }: WhereToWatchProps) {
 | 
				
			||||||
 | 
					  if (!watchProviders?.link) {
 | 
				
			||||||
 | 
					    console.group()
 | 
				
			||||||
 | 
					    console.log("Watch providers (WhereToWatch)")
 | 
				
			||||||
 | 
					    console.log(watchProviders)
 | 
				
			||||||
 | 
					    console.groupEnd()
 | 
				
			||||||
 | 
					    return <div id="no-watch"></div>
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return <><div id="watch-providers">
 | 
				
			||||||
 | 
					    {watchProviders?.flatrate?.length > 0 ? <div><h1>Streaming:</h1><ProviderIcons providerList={watchProviders.flatrate} link={watchProviders.link} /></div> : ""}
 | 
				
			||||||
 | 
					    {watchProviders?.rent?.length > 0 ? <div><h1>Alquiler:</h1><ProviderIcons providerList={watchProviders.rent} link={watchProviders.link} /></div> : ""}
 | 
				
			||||||
 | 
					    {watchProviders?.buy?.length > 0 ? <div><h1>Comprar:</h1><ProviderIcons providerList={watchProviders.buy} link={watchProviders.link} /></div> : ""}
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					    <p>Powered by Just Watch.</p>
 | 
				
			||||||
 | 
					  </>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue