diff options
| author | real-zephex <[email protected]> | 2024-05-19 08:08:57 +0530 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-05-19 08:08:57 +0530 |
| commit | a8e9ca0c14bcd6a8b2aa8cfe5b95a4e98dbcebfe (patch) | |
| tree | 98fa3f6cbdd690648c7d31a79c7d381624f38530 | |
| parent | minor changes to the manga page (diff) | |
| parent | added series support (diff) | |
| download | dramalama-a8e9ca0c14bcd6a8b2aa8cfe5b95a4e98dbcebfe.tar.xz dramalama-a8e9ca0c14bcd6a8b2aa8cfe5b95a4e98dbcebfe.zip | |
Merge pull request #28 from real-zephex/improvement-2
added series support
| -rw-r--r-- | src/app/anime/components/popularAnimes.jsx | 2 | ||||
| -rw-r--r-- | src/app/components/header/header.jsx | 1 | ||||
| -rw-r--r-- | src/app/page.jsx | 9 | ||||
| -rw-r--r-- | src/app/web-series/[id]/page.jsx | 111 | ||||
| -rw-r--r-- | src/app/web-series/components/HomePageModules.jsx | 56 | ||||
| -rw-r--r-- | src/app/web-series/components/cacher.js | 19 | ||||
| -rw-r--r-- | src/app/web-series/components/data-fetch.js | 87 | ||||
| -rw-r--r-- | src/app/web-series/components/searchBar.jsx | 49 | ||||
| -rw-r--r-- | src/app/web-series/components/searchResults.jsx | 35 | ||||
| -rw-r--r-- | src/app/web-series/components/videoPlayer.jsx | 66 | ||||
| -rw-r--r-- | src/app/web-series/page.jsx | 28 | ||||
| -rw-r--r-- | src/app/web-series/styles/info.module.css | 171 | ||||
| -rw-r--r-- | src/app/web-series/styles/pages.module.css | 46 | ||||
| -rw-r--r-- | src/app/web-series/styles/search.module.css | 78 | ||||
| -rw-r--r-- | src/app/web-series/styles/videoPlayer.module.css | 76 | ||||
| -rw-r--r-- | src/app/web-series/styles/web-series.module.css | 4 | ||||
| -rw-r--r-- | utils/movie_urls.js | 2 | ||||
| -rw-r--r-- | utils/series_urls.js | 28 |
18 files changed, 866 insertions, 2 deletions
diff --git a/src/app/anime/components/popularAnimes.jsx b/src/app/anime/components/popularAnimes.jsx index 2259a42..5bf8904 100644 --- a/src/app/anime/components/popularAnimes.jsx +++ b/src/app/anime/components/popularAnimes.jsx @@ -4,7 +4,7 @@ import { Atkinson_Hyperlegible } from "next/font/google"; import styles from "../styles/pop_recent_top.module.css"; import { popular, anime_info } from "../data-fetch/request"; -import { preFetchAnimeInfo, preFetchVideoLinks } from "./cacher"; +import { preFetchAnimeInfo } from "./cacher"; const atkinson = Atkinson_Hyperlegible({ subsets: ["latin"], weight: "400" }); diff --git a/src/app/components/header/header.jsx b/src/app/components/header/header.jsx index c1fbc2d..ba9ff86 100644 --- a/src/app/components/header/header.jsx +++ b/src/app/components/header/header.jsx @@ -18,6 +18,7 @@ export default async function Header() { <Link href="/kdrama">Kdrama</Link>
<Link href="/manga">Manga</Link>
<Link href="/movies">Movies</Link>
+ <Link href="/web-series">Web Series</Link>
</div>
</div>
</main>
diff --git a/src/app/page.jsx b/src/app/page.jsx index 4f9eda2..91f9551 100644 --- a/src/app/page.jsx +++ b/src/app/page.jsx @@ -42,6 +42,15 @@ export default async function Home() { <p>Your one stop for all your movie needs</p> </div> </Link> + <Link + href={"/web-series"} + title="Click here to get redirected to the kdrama webpage" + > + <div className={styles.movies}> + <h2>Web Series</h2> + <p>Your one stop for all your web-series needs</p> + </div> + </Link> </div> </div> </main> diff --git a/src/app/web-series/[id]/page.jsx b/src/app/web-series/[id]/page.jsx new file mode 100644 index 0000000..63fcc3a --- /dev/null +++ b/src/app/web-series/[id]/page.jsx @@ -0,0 +1,111 @@ +import Image from "next/image"; +import { SERIES_INFO, CREW_DETAILS } from "../components/data-fetch"; +import styles from "../styles/info.module.css"; +import { BiSolidUpvote } from "react-icons/bi"; +import { LiaStarSolid } from "react-icons/lia"; +import SeriesPlayer from "../components/videoPlayer"; + +const SeriesInfoPage = async ({ params }) => { + const id = params.id; + const data = await FetchSeriesInfo(id); + const crew_data = await CREW_DETAILS(id); + return ( + <main + style={{ + // backgroundImage: `url(https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=https://image.tmdb.org/t/p/original${data.backdrop_path})`, + background: `linear-gradient(to bottom, rgba(0, 0, 0, 0) 70%, rgba(0, 0, 0, 1) 100%), + url(https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=https://image.tmdb.org/t/p/original${data.backdrop_path}) no-repeat center center fixed`, + backgroundSize: "cover", + }} + className={styles.Main} + > + <div className={styles.AnimeInfo}> + <section className={styles.AnimeInfoContainer}> + <div className={styles.TitleContainer}> + <Image + src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=https://image.tmdb.org/t/p/original${data.poster_path}`} + width={190} + height={290} + alt="Series Poster" + priority + /> + <section className={styles.SideTitleContainer}> + <h2 className={styles.title}>{data.name}</h2> + <p className={styles.secondTitle}> + {data.original_name} + </p> + <p className={styles.tagline}> + <span>{data.tagline || "not found"}</span> + </p> + <p className={styles.description}> + {" "} + {data.overview} + </p> + <hr /> + <p className={styles.genres}> + Genres:{" "} + {data.genres.map((item, index) => ( + <span key={index}> + {item.name} + {index !== data.genres.length - 1 && + ", "} + </span> + ))} + </p> + <p className={styles.epiInfo}> + Seasons: <span>{data.number_of_seasons}</span> + </p> + <p className={styles.epiInfo}> + Episodes: <span>{data.number_of_episodes}</span> + </p> + <div className={styles.votes}> + <section className={styles.vote}> + <BiSolidUpvote color="var(--nord-green)" />{" "} + <p>{data.vote_count}</p> + </section> + <section className={styles.vote}> + <LiaStarSolid color="var(--nord-green)" />{" "} + <p>{data.vote_average}</p> + </section> + </div> + </section> + </div> + <section className={styles.CrewContainer}> + <h2>Crew</h2> + <div className={styles.CrewEntry}> + {crew_data && + crew_data.cast.map((item, index) => ( + <div + key={index} + className={styles.CastEntry} + > + <Image + src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=https://image.tmdb.org/t/p/original${item.profile_path}`} + width={140} + height={190} + alt="Crew Poster" + /> + <p>{item.name}</p> + <p style={{ fontSize: 11 }}> + {item.character} + </p> + </div> + ))} + </div> + </section> + + <section className={styles.VideoContainer}> + <SeriesPlayer id={data.id} /> + </section> + </section> + </div> + </main> + ); +}; + +const FetchSeriesInfo = async (id) => { + const data = SERIES_INFO(id); + return data; +}; + +export default SeriesInfoPage; diff --git a/src/app/web-series/components/HomePageModules.jsx b/src/app/web-series/components/HomePageModules.jsx new file mode 100644 index 0000000..90af2f8 --- /dev/null +++ b/src/app/web-series/components/HomePageModules.jsx @@ -0,0 +1,56 @@ +import { POPULAR_SHOWS, TRENDING_SHOWS, TOP_SHOWS } from "./data-fetch"; +import styles from "../styles/pages.module.css"; +import Image from "next/image"; +import Link from "next/link"; +import PreFecthSeriesInfo from "./cacher"; + +const HomepageUtils = async (type) => { + const fetchFunctions = { + popular: POPULAR_SHOWS, + trending: TRENDING_SHOWS, + top: TOP_SHOWS, + }; + + const fetchData = fetchFunctions[type]; + + if (fetchData) { + return await fetchData(); + } else { + return; + } +}; + +const Pages = async ({ type: type }) => { + const data = await HomepageUtils(type); + PreFecthSeriesInfo(data); + return ( + <main className={styles.main}> + <h2>{type} series</h2> + <section className={styles.SeriesContainer}> + {data && + data.results.length > 0 && + data.results.map((item, index) => ( + <Link + key={index} + href={`/web-series/${item.id}`} + style={{ textDecoration: "none", color: "white" }} + title={item.name} + > + <section className={styles.SeriesEntry}> + <Image + src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=https://image.tmdb.org/t/p/original${item.poster_path}`} + width={167} + height={267} + alt="Series Poster" + priority + /> + <p>{item.name || "Not sure"}</p> + </section> + </Link> + ))} + </section> + </main> + ); +}; + +export default Pages; diff --git a/src/app/web-series/components/cacher.js b/src/app/web-series/components/cacher.js new file mode 100644 index 0000000..3e2a197 --- /dev/null +++ b/src/app/web-series/components/cacher.js @@ -0,0 +1,19 @@ +import { SERIES_INFO } from "./data-fetch"; + +const PreFecthSeriesInfo = async (data) => { + try { + const fetchPromises = data.results.map(async (element) => { + await SERIES_INFO(element.id); + }); + + await Promise.all(fetchPromises); + console.log("Series info pre-fetched successfully!"); + } catch (error) { + console.error( + "Error occurred while pre-fetching series info page:", + error + ); + } +}; + +export default PreFecthSeriesInfo; diff --git a/src/app/web-series/components/data-fetch.js b/src/app/web-series/components/data-fetch.js new file mode 100644 index 0000000..e0feca5 --- /dev/null +++ b/src/app/web-series/components/data-fetch.js @@ -0,0 +1,87 @@ +"use server"; + +import { + popular_tv_shows, + trending_tv_shows, + top_rated_shows, + recommended_shows, + crew_details, + tv_info, + search_tv, +} from "../../../../utils/series_urls"; + +export const POPULAR_SHOWS = async () => { + try { + const res = await fetch(popular_tv_shows(), { + next: { + revalidate: 21600, + }, + }); + const data = await res.json(); + return data; + } catch (error) { + throw new Error(error.message); + } +}; + +export const TRENDING_SHOWS = async () => { + try { + const res = await fetch(trending_tv_shows(), { + next: { + revalidate: 21600, + }, + }); + const data = await res.json(); + return data; + } catch (error) { + throw new Error(error.message); + } +}; + +export const TOP_SHOWS = async () => { + try { + const res = await fetch(top_rated_shows(), { + next: { + revalidate: 21600, + }, + }); + const data = await res.json(); + return data; + } catch (error) { + throw new Error(error.message); + } +}; + +export const SERIES_INFO = async (id) => { + try { + const res = await fetch(tv_info(id), { next: { revalidate: 21600 } }); + const data = await res.json(); + return data; + } catch (error) { + throw new Error(error.message); + } +}; + +export const CREW_DETAILS = async (id) => { + try { + const res = await fetch(crew_details(id), { + next: { revalidate: 21600 }, + }); + const data = await res.json(); + return data; + } catch (error) { + throw new Error(error.message); + } +}; + +export const SEARCH_TV = async (title) => { + try { + const res = await fetch(search_tv(title), { + next: { revalidate: 21600 }, + }); + const data = await res.json(); + return data; + } catch (error) { + throw new Error(error.message); + } +}; diff --git a/src/app/web-series/components/searchBar.jsx b/src/app/web-series/components/searchBar.jsx new file mode 100644 index 0000000..81dd25f --- /dev/null +++ b/src/app/web-series/components/searchBar.jsx @@ -0,0 +1,49 @@ +"use client"; +import styles from "../styles/search.module.css"; +import { FaSearch } from "react-icons/fa"; +import { useState } from "react"; + +import { SEARCH_TV } from "./data-fetch"; +import SearchResults from "./searchResults"; + +const SearchBar = () => { + const [title, setTitle] = useState(""); + const [result, setResults] = useState(null); + const [loading, setloading] = useState(false); + + const fetch_results = async (title) => { + setloading(true); + setResults(await SearchResults(await SEARCH_TV(title))); + setloading(false); + }; + + return ( + <main className={styles.Main}> + <section className={styles.InputContainer}> + <FaSearch + color="white" + className={styles.SearchIcon} + size={17} + /> + <input + placeholder="Enter series title here" + onChange={(event) => setTitle(event.target.value)} + onKeyDown={async (e) => { + if ((e.key === "Enter" || e.code === 13) && title) { + await fetch_results(e.target.value); + } + }} + ></input> + </section> + + {loading && ( + <p style={{ color: "white", textAlign: "center" }}> + Please wait while we crunch up all the data + </p> + )} + <section className={styles.SearchResults}>{result}</section> + </main> + ); +}; + +export default SearchBar; diff --git a/src/app/web-series/components/searchResults.jsx b/src/app/web-series/components/searchResults.jsx new file mode 100644 index 0000000..d1564e0 --- /dev/null +++ b/src/app/web-series/components/searchResults.jsx @@ -0,0 +1,35 @@ +"use server"; + +import Link from "next/link"; +import Image from "next/image"; +import styles from "../styles/search.module.css"; +import PreFecthSeriesInfo from "./cacher"; + +const SearchResults = async (data) => { + PreFecthSeriesInfo(data); + return ( + <div className={styles.SearchedSeriesContainer}> + {data && + data.results.map((item, index) => ( + <Link + key={index} + style={{ color: "white", textDecoration: "none" }} + href={`/web-series/${item.id}`} + title={item.name} + > + <div className={styles.SearchedSeriesEntry}> + <Image + src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=https://image.tmdb.org/t/p/original${item.poster_path}`} + width={160} + height={247} + alt="Searched Series Poster" + /> + <p>{item.name}</p> + </div> + </Link> + ))} + </div> + ); +}; + +export default SearchResults; diff --git a/src/app/web-series/components/videoPlayer.jsx b/src/app/web-series/components/videoPlayer.jsx new file mode 100644 index 0000000..cc8feb3 --- /dev/null +++ b/src/app/web-series/components/videoPlayer.jsx @@ -0,0 +1,66 @@ +"use client"; + +import { useState } from "react"; +import styles from "../styles/videoPlayer.module.css"; + +const SeriesPlayer = ({ id: id }) => { + const [iframe, iframeContent] = useState(null); + const [episode, setEpisode] = useState(""); + const [season, setSeason] = useState(""); + + async function VideoPlayerInitialize() { + if (!episode || !season) { + alert("Please provide the required episode and season number."); + return; + } + iframeContent(await iframeGenerator(id, season, episode)); + document.getElementById("video-player").style.display = "none"; + } + + return ( + <main className={styles.Main}> + <div className={styles.EpisodeSeasonInput}> + <input + name="Season" + type="number" + placeholder="Season Number" + onChange={(e) => { + if (Number(e.target.value) > 0) { + setSeason(e.target.value); + } + }} + ></input> + <input + name="Episode" + type="number" + placeholder="Episode Number" + onChange={(e) => { + if (Number(e.target.value) > 0) { + setEpisode(e.target.value); + } + }} + ></input> + + <button onClick={() => VideoPlayerInitialize(id)}> + Search + </button> + </div> + + <div className={styles.VideoPlayer}> + {iframe} + <p id="video-player"> + Please use adblockers to prevent ads and redirects. We have + no control over the amount of ads or the type of ads which + you might encounter. + </p> + </div> + </main> + ); +}; + +const iframeGenerator = async (id, seasonNumber, episodeNumber) => { + const url = `https://vidsrc.pro/embed/tv/${id}/${seasonNumber}/${episodeNumber}`; + return <iframe src={url} allowFullScreen referrerPolicy="origin"></iframe>; +}; + +export default SeriesPlayer; diff --git a/src/app/web-series/page.jsx b/src/app/web-series/page.jsx new file mode 100644 index 0000000..63fcd05 --- /dev/null +++ b/src/app/web-series/page.jsx @@ -0,0 +1,28 @@ +import styles from "./styles/web-series.module.css"; +import Pages from "./components/HomePageModules"; +import SearchBar from "./components/searchBar"; + +export default async function SeriesHomepage() { + return ( + <main className={styles.main}> + <SearchBar /> + <Pages type={"popular"} /> + <hr + style={{ + borderColor: "grey", + marginTop: 15, + marginBottom: -15, + }} + /> + <Pages type={"trending"} /> + <hr + style={{ + borderColor: "grey", + marginTop: 15, + marginBottom: -15, + }} + /> + <Pages type={"top"} /> + </main> + ); +} diff --git a/src/app/web-series/styles/info.module.css b/src/app/web-series/styles/info.module.css new file mode 100644 index 0000000..8873b41 --- /dev/null +++ b/src/app/web-series/styles/info.module.css @@ -0,0 +1,171 @@ +.Main { + min-height: 100vh; + margin-top: 60px; + +} + +.Main::-webkit-scrollbar { + width: 0; +} + +.AnimeInfo { + backdrop-filter: blur(10px); + background-color: #1f1f1fcb; + +} + +.AnimeInfoContainer { + width: 50%; + height: 100vh; + margin: 0px auto; +} + +.TitleContainer { + display: flex; + align-items: center; +} + +.TitleContainer img { + border-radius: 0.8rem; + padding: 0.5rem; +} + +.SideTitleContainer { + margin: 0.4rem; + color: white; +} + +.title { + margin: 0; +} + +.secondTitle { + margin: 0; + font-size: small; +} + +.tagline { + margin: 0; +} + +.tagline span { + background-color: #121212b7; + padding: 0.2rem; + border-radius: 0.5rem; + font-size: 12px; +} + +.description { + margin: 0.2rem 0 0 0; + height: auto; + max-height: 100px; + overflow: auto; +} + +.description::-webkit-scrollbar { + width: 3px; +} + +.description::-webkit-scrollbar-thumb { + background-color: var(--neon-yellow); + border-radius: 1rem; +} + + +.genres { + margin: 0; + color: var(--nord-yellow); +} + +.genres span { + color: white; +} + +.epiInfo { + margin: 0; + color: var(--nord-yellow); +} + +.epiInfo span { + color: white; +} + +.votes { + display: flex; +} + +.votes p { + margin: 0 0 0 0; +} + +.vote { + display: flex; + align-items: center; + margin: 0 0.2rem 0 0; +} + +.CrewContainer { + color: white; + margin-top: -1rem; +} + +.CrewEntry { + display: flex; + align-items: center; + overflow: auto; +} + +.CrewEntry h2 { + margin: 0; + color: white; +} + +.CastEntry { + display: flex; + flex-direction: column; + align-items: center; + margin: 0 0 0 0.4rem; +} + +.CastEntry img { + border-radius: 0.5rem; +} + +.CastEntry p { + margin: 0; + width: 140px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + text-align: center; +} + +.CrewEntry::-webkit-scrollbar { + height: 3px; +} + +.CrewEntry::-webkit-scrollbar-thumb { + background-color: var(--neon-yellow); + border-radius: 1rem; +} + + +@media screen and (max-width: 1024px) { + .AnimeInfoContainer { + width: 100%; + } + + .title { + font-size: 20px; + } + + .description { + font-size: 14px; + max-height: 100px; + overflow: auto; + } + + .SideTitleContainer { + font-size: 14px; + } +}
\ No newline at end of file diff --git a/src/app/web-series/styles/pages.module.css b/src/app/web-series/styles/pages.module.css new file mode 100644 index 0000000..631f7db --- /dev/null +++ b/src/app/web-series/styles/pages.module.css @@ -0,0 +1,46 @@ +.main h2 { + color: white; +} + +.SeriesContainer { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); + grid-gap: 0.5rem; + align-items: center; + margin: -1rem 0 0 0; +} + +.SeriesEntry { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background-color: #1f1f1fce; + border-radius: 0.5rem; + padding: 0.4rem; + color: white; + cursor: pointer; +} + +.SeriesEntry p { + width: 160px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + text-align: center; + margin: 0.3rem 0 0 0; + font-family: "Atkinson Hyperlegible", serif; +} + +.SeriesEntry img { + border-radius: 0.5rem; +} + +@media screen and (max-width: 768px) { + .SeriesContainer { + display: flex; + align-items: center; + overflow-x: auto; + overflow-y: hidden; + } +}
\ No newline at end of file diff --git a/src/app/web-series/styles/search.module.css b/src/app/web-series/styles/search.module.css new file mode 100644 index 0000000..145a2aa --- /dev/null +++ b/src/app/web-series/styles/search.module.css @@ -0,0 +1,78 @@ +.InputContainer { + display: flex; + align-items: center; + background-color: #121212; + width: 40vw; + border-radius: 0.5rem; +} + +.SearchIcon { + margin-left: 0.4rem; +} + +.InputContainer input { + background-color: transparent; + outline: none; + border: none; + padding: 0.4rem; + font-family: "Lexend Deca", serif; + margin-left: 0.2rem; + font-size: large; + color: white; + width: 100%; +} + +.SearchedSeriesContainer { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); + grid-gap: 0.7rem; + align-items: center; + margin-top: 0.8rem; +} + +.SearchedSeriesEntry { + display: flex; + align-items: center; + flex-direction: column; + background-color: #1f1f1f; + border-radius: 0.5rem; + padding: 0.2rem; + transition: opacity 200ms ease; + +} + +.SearchedSeriesContainer:hover .SearchedSeriesEntry { + opacity: 0.5; +} + +.SearchedSeriesContainer .SearchedSeriesEntry:hover { + opacity: 1; +} + +.SearchedSeriesEntry p { + width: 150px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + text-align: center; + margin: 0.2rem 0 0.2rem 0; +} + +.SearchedSeriesEntry img { + border-radius: 0.5rem; + padding: 0.2rem 0.2rem 0 0.2rem; +} + +@media screen and (max-width: 768px) { + + .InputContainer { + width: 100%; + } + + .SearchedSeriesContainer { + display: flex; + overflow: auto; + } + + +}
\ No newline at end of file diff --git a/src/app/web-series/styles/videoPlayer.module.css b/src/app/web-series/styles/videoPlayer.module.css new file mode 100644 index 0000000..f44776f --- /dev/null +++ b/src/app/web-series/styles/videoPlayer.module.css @@ -0,0 +1,76 @@ +.Main { + margin: 1.5rem 0 0 0; +} + +.EpisodeSeasonInput { + display: flex; + align-items: center; + justify-content: center; +} + +.EpisodeSeasonInput input { + padding: 0.6rem; + margin: 0 0.2rem 0 0.2rem; + border: none; + outline: none; + background-color: #121212a6; + border-radius: 0.5rem; + font-family: "Lexend Deca", serif; + color: white; +} + +.EpisodeSeasonInput button { + padding: 0.5rem; + border: none; + outline: none; + border-radius: 0.5rem; + background-color: #121212a6; + color: white; + cursor: pointer; + font-family: "Atkinson Hyperlegible", serif; +} + + +.EpisodeSeasonInput input::placeholder { + color: gray; +} + +.VideoPlayer iframe { + margin: 1rem 0 2.5rem 0; + width: 100%; + height: 400px; + border-radius: 0.5rem; + border: none; + outline: none; +} + +.VideoPlayer p { + color: white; + margin: 0.5rem 0 0 0; + text-align: center; + font-size: 12px; +} + +@media screen and (max-width: 768px) { + + .EpisodeSeasonInput { + width: 80%; + margin: 0px auto; + } + + .VideoPlayer iframe { + width: 100%; + height: 300px; + margin-bottom: 50px; + } + + .EpisodeSeasonInput input { + padding: 0.4rem; + } + + .EpisodeSeasonInput button { + padding: 0.3rem 0.4rem 0.3rem 0.4rem; + font-size: 14px; + } + +}
\ No newline at end of file diff --git a/src/app/web-series/styles/web-series.module.css b/src/app/web-series/styles/web-series.module.css new file mode 100644 index 0000000..849fed9 --- /dev/null +++ b/src/app/web-series/styles/web-series.module.css @@ -0,0 +1,4 @@ +.main { + margin: 65px auto; + width: 99%; +}
\ No newline at end of file diff --git a/utils/movie_urls.js b/utils/movie_urls.js index dd39bb6..066041d 100644 --- a/utils/movie_urls.js +++ b/utils/movie_urls.js @@ -1,4 +1,4 @@ -const API_KEY = "171fe27dbfecc58e2a18fbced644cda9"; +export const API_KEY = "171fe27dbfecc58e2a18fbced644cda9"; export const PROXY = "https://sup-proxy.zephex0-f6c.workers.dev/api-json?url="; // MOVIES diff --git a/utils/series_urls.js b/utils/series_urls.js new file mode 100644 index 0000000..26d83bf --- /dev/null +++ b/utils/series_urls.js @@ -0,0 +1,28 @@ +import { API_KEY, PROXY } from "./movie_urls"; + +// Popular TV shows +export const popular_tv_shows = () => + `${PROXY}https://api.themoviedb.org/3/tv/popular?api_key=${API_KEY}`; + +// Trending show either for the week or the day +export const trending_tv_shows = (duration = "day") => + `${PROXY}https://api.themoviedb.org/3/trending/tv/${duration}?api_key=${API_KEY}`; + +// Top Rated TV Shows +export const top_rated_shows = () => + `${PROXY}https://api.themoviedb.org/3/tv/top_rated?api_key=${API_KEY}`; + +// Recommendations based on a particular show +export const recommended_shows = (id) => + `https://api.themoviedb.org/3/tv/${id}/recommendations?api_key=${API_KEY}`; + +// Crew Details +export const crew_details = (id) => + `https://api.themoviedb.org/3/tv/${id}/credits?api_key=${API_KEY}`; + +// TV Info +export const tv_info = (id) => + `https://api.themoviedb.org/3/tv/${id}?api_key=${API_KEY}`; + +// Search shows +export const search_tv = (query) => `https://api.themoviedb.org/3/search/tv?api_key=${API_KEY}&query=${query}`
\ No newline at end of file |