Compare commits
	
		
			No commits in common. "8225d77a997efe58ad89287a1e810d77ca1808e2" and "88ba270647bf5ca00450772687e992f0763e1e89" have entirely different histories.
		
	
	
		
			8225d77a99
			...
			88ba270647
		
	
		
							
								
								
									
										29
									
								
								src/App.css
								
								
								
								
							
							
						
						
									
										29
									
								
								src/App.css
								
								
								
								
							| 
						 | 
				
			
			@ -52,11 +52,6 @@ main {
 | 
			
		|||
  font-size: 1.6rem;
 | 
			
		||||
  background-color: rgba(0, 0, 0, 0.5);
 | 
			
		||||
 | 
			
		||||
  min-height: 100%;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  justify-content: flex-end;
 | 
			
		||||
 | 
			
		||||
  h1 {
 | 
			
		||||
    font-size: 2em;
 | 
			
		||||
    margin: 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -139,7 +134,7 @@ main {
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
#background {
 | 
			
		||||
  background-color: black;
 | 
			
		||||
  /* background-color: black; */
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
| 
						 | 
				
			
			@ -150,24 +145,6 @@ main {
 | 
			
		|||
.CrossfadeImage {
 | 
			
		||||
  width: 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,13 +7,11 @@ import tmdb from './objects/tmdb'
 | 
			
		|||
import { Sidebar } from './objects/sidebar'
 | 
			
		||||
import { Movie } from './objects/movie-wall'
 | 
			
		||||
import CrossfadeImage from 'react-crossfade-image'
 | 
			
		||||
import { WhereToWatch } from './objects/whereToWatch'
 | 
			
		||||
 | 
			
		||||
export type Config = {
 | 
			
		||||
  language: string,
 | 
			
		||||
  region: string,
 | 
			
		||||
  page: number,
 | 
			
		||||
  locale: string
 | 
			
		||||
}
 | 
			
		||||
class MovieClass implements Movie {
 | 
			
		||||
  id = null
 | 
			
		||||
| 
						 | 
				
			
			@ -28,14 +26,13 @@ function App() {
 | 
			
		|||
  const [config, setConfig] = useState<Config>({
 | 
			
		||||
    language: "es",
 | 
			
		||||
    region: "spain",
 | 
			
		||||
    page: 1,
 | 
			
		||||
    locale: "ES"
 | 
			
		||||
    page: 1
 | 
			
		||||
  })
 | 
			
		||||
  const [movies, setMovies] = useState([new MovieClass()])
 | 
			
		||||
  const [backdrop, setBackdrop] = useState("")
 | 
			
		||||
  const [chosenMovie, setChosenMovie] = useState(new MovieClass())
 | 
			
		||||
  const [similarMoviesAvailable, setSimilarMoviesAvailable] = useState(true)
 | 
			
		||||
  const [watchProviders, setWatchProviders] = useState({})
 | 
			
		||||
 | 
			
		||||
  useEffect(() => { tmdb.getPopular(config, setMovies) }, [])
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const bgString = chosenMovie.backdrop_path ?
 | 
			
		||||
| 
						 | 
				
			
			@ -43,12 +40,9 @@ function App() {
 | 
			
		|||
      : tmdb.makeBgImgUrl(movies[0]?.backdrop_path ?? "")
 | 
			
		||||
    setBackdrop(bgString)
 | 
			
		||||
  }, [movies])
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    tmdb.getWhereToWatch(chosenMovie, setWatchProviders, config)
 | 
			
		||||
  }, [chosenMovie])
 | 
			
		||||
 | 
			
		||||
  const crossfadeImageStyles = {
 | 
			
		||||
    width: "2560px",
 | 
			
		||||
    minHeight: "100%",
 | 
			
		||||
    width: "100%",
 | 
			
		||||
    aspectRatio: "16/9"
 | 
			
		||||
  }
 | 
			
		||||
  return (
 | 
			
		||||
| 
						 | 
				
			
			@ -57,7 +51,7 @@ function App() {
 | 
			
		|||
        <CrossfadeImage src={backdrop} style={crossfadeImageStyles} />
 | 
			
		||||
      </div>
 | 
			
		||||
      <main >
 | 
			
		||||
        <Sidebar movie={chosenMovie} similarMoviesAvailable={similarMoviesAvailable} watchProviders={watchProviders} />
 | 
			
		||||
        <Sidebar movie={chosenMovie} similarMoviesAvailable={similarMoviesAvailable} />
 | 
			
		||||
        <div id="movie-wall-container">
 | 
			
		||||
          <MovieWall movies={movies}
 | 
			
		||||
            setMovies={setMovies}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,13 +1,11 @@
 | 
			
		|||
import React from "react";
 | 
			
		||||
import { Movie } from "./movie-wall";
 | 
			
		||||
import tmdb from "./tmdb";
 | 
			
		||||
import { WhereToWatch } from "./whereToWatch";
 | 
			
		||||
export interface SidebarProps extends React.ComponentPropsWithRef<"div"> {
 | 
			
		||||
  movie: Movie;
 | 
			
		||||
  similarMoviesAvailable: boolean;
 | 
			
		||||
  watchProviders: {};
 | 
			
		||||
}
 | 
			
		||||
export function Sidebar({ movie, similarMoviesAvailable, watchProviders }: SidebarProps) {
 | 
			
		||||
export function Sidebar({ movie, similarMoviesAvailable }: SidebarProps) {
 | 
			
		||||
  return <div id="sidebar">
 | 
			
		||||
    <h1>{movie?.title ?? "loading"}</h1>
 | 
			
		||||
    <figure>
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +20,6 @@ export function Sidebar({ movie, similarMoviesAvailable, watchProviders }: Sideb
 | 
			
		|||
      : movie.overview === "" ? "Resumen no disponible."
 | 
			
		||||
        : movie.overview}
 | 
			
		||||
    </p>
 | 
			
		||||
    <WhereToWatch watchProviders={watchProviders} />
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,6 +56,7 @@ export default {
 | 
			
		|||
        setSimilarMoviesAvailable(true)
 | 
			
		||||
      } else {
 | 
			
		||||
        setSimilarMoviesAvailable(false)
 | 
			
		||||
        console.log("SIMILAR NOT AVAILABLE")
 | 
			
		||||
      }
 | 
			
		||||
      return true
 | 
			
		||||
    } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -63,15 +64,24 @@ export default {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
  },
 | 
			
		||||
  getWhereToWatch: async function(movie: Movie, setWatchProviders: Function, config: Config) {
 | 
			
		||||
    if (movie?.id) {
 | 
			
		||||
      let res = await tmdb.get(movie.id + "/watch/providers")
 | 
			
		||||
      if (res.status == 200) {
 | 
			
		||||
        setWatchProviders(res.data.results[config.locale])
 | 
			
		||||
      } else {
 | 
			
		||||
        throw Error("API call failed! Response: " + JSON.stringify(res))
 | 
			
		||||
      }
 | 
			
		||||
  /**
 | 
			
		||||
   *Calls TMDB/images, and sets the backdrop state accordingly
 | 
			
		||||
   * 
 | 
			
		||||
   */
 | 
			
		||||
  getBackdrop: async function(movie: Movie, setBackdrop: Function) {
 | 
			
		||||
    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 {
 | 
			
		||||
      throw Error("API call failed! Response: " + JSON.stringify(res))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  },
 | 
			
		||||
  makeBgImgUrl:
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -93,8 +103,5 @@ export default {
 | 
			
		|||
    */
 | 
			
		||||
    function(movie: Movie) {
 | 
			
		||||
      return "https://www.themoviedb.org/movie/" + movie.id
 | 
			
		||||
    },
 | 
			
		||||
  makeLogoPath: function(str: string) {
 | 
			
		||||
    return "https://image.tmdb.org/t/p/original/" + str
 | 
			
		||||
  }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,86 +0,0 @@
 | 
			
		|||
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