From 2d0bcaeeeffef4e6ed6f445378b9729e70901f61 Mon Sep 17 00:00:00 2001 From: real-zephex Date: Sat, 25 May 2024 16:58:02 +0530 Subject: =?UTF-8?q?=F0=9F=9A=80=20refactor(movie):=20revamped=20movie=20se?= =?UTF-8?q?ction?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/anime/components/search.jsx | 2 +- src/app/anime/continueWatching/page.jsx | 2 +- src/app/movies/[id]/page.jsx | 151 ++++++++------------------ src/app/movies/components/cacher.js | 5 +- src/app/movies/components/descriptionTabs.jsx | 67 ++++++++++++ src/app/movies/components/faqs.jsx | 33 ++++++ src/app/movies/components/popular.jsx | 49 --------- src/app/movies/components/requestsHandler.js | 36 ++++++ src/app/movies/components/search.jsx | 71 +++++++----- src/app/movies/components/searchFormatter.jsx | 51 +++++++++ src/app/movies/components/search_2.jsx | 63 ----------- src/app/movies/components/trending.jsx | 48 -------- src/app/movies/components/videoPlayer.jsx | 17 +++ src/app/movies/components/video_player.jsx | 68 ------------ src/app/movies/page.jsx | 86 +++++++++++++-- src/app/movies/styles/info.module.css | 150 ------------------------- src/app/movies/styles/page.module.css | 3 - src/app/movies/styles/pop_trend.module.css | 79 -------------- src/app/movies/styles/search.module.css | 84 -------------- src/app/movies/styles/video_player.module.css | 31 ------ 20 files changed, 369 insertions(+), 727 deletions(-) create mode 100644 src/app/movies/components/descriptionTabs.jsx create mode 100644 src/app/movies/components/faqs.jsx delete mode 100644 src/app/movies/components/popular.jsx create mode 100644 src/app/movies/components/requestsHandler.js create mode 100644 src/app/movies/components/searchFormatter.jsx delete mode 100644 src/app/movies/components/search_2.jsx delete mode 100644 src/app/movies/components/trending.jsx create mode 100644 src/app/movies/components/videoPlayer.jsx delete mode 100644 src/app/movies/components/video_player.jsx delete mode 100644 src/app/movies/styles/info.module.css delete mode 100644 src/app/movies/styles/page.module.css delete mode 100644 src/app/movies/styles/pop_trend.module.css delete mode 100644 src/app/movies/styles/search.module.css delete mode 100644 src/app/movies/styles/video_player.module.css (limited to 'src') diff --git a/src/app/anime/components/search.jsx b/src/app/anime/components/search.jsx index 0fe883b..2631791 100644 --- a/src/app/anime/components/search.jsx +++ b/src/app/anime/components/search.jsx @@ -28,7 +28,7 @@ const SearchBar = () => { return (
-
+
{ const [localItems, setLocalItems] = useState(null); diff --git a/src/app/movies/[id]/page.jsx b/src/app/movies/[id]/page.jsx index 313fc83..11389e7 100644 --- a/src/app/movies/[id]/page.jsx +++ b/src/app/movies/[id]/page.jsx @@ -1,118 +1,53 @@ -import styles from "../styles/info.module.css"; -import { getInfoURL } from "../../../../utils/movie_urls"; -import Image from "next/image"; -import { PiThumbsUpFill } from "react-icons/pi"; -import { FaRegCheckCircle } from "react-icons/fa"; -import { RxDividerVertical } from "react-icons/rx"; -import { FaDollarSign } from "react-icons/fa"; -import { FaSackDollar } from "react-icons/fa6"; -import VIDEO_PLAYER from "../components/video_player"; +import { Image, Chip, Accordion, AccordionItem } from "@nextui-org/react"; -export default async function MOVIE_INFO({ params }) { +import { MovieInfoData } from "../components/requestsHandler"; +import DescriptionTabs from "../components/descriptionTabs"; +import MovieVideoPlayer from "../components/videoPlayer"; +import Questions from "../components/faqs"; + +const MovieInfoPage = async ({ params }) => { const id = params.id; - const data = await get_movie_info(id); + + const data = await MovieInfoData(id); return ( -
-
-
-
- Movie Poster -
-

{data.title || "Not found"}

-

- {data.tagline || "Not found"} -

-

- {data.overview || "Not found"} -

+
+
+ +
+ Anime Title Poster +
+

+ {data.title} +

+
+ {data.genres && + data.genres.map((item, index) => ( + +

{item.name}

+
+ ))}
-
-
- - -

{data.vote_average || "Not found"}

-
- - - - - -

{data.vote_count || "Not found"}

-
-
-
- - -

- $ - {data.revenue.toLocaleString() || - "Not found"} -

-
- - - - - -

- $ - {data.budget.toLocaleString() || - "Not found"} -

-
-
-
- -

- Release Date:{" "} - {data.release_date || "Not found"} -

-
-
-
- {data.genres.map((item) => ( -

{item.name || "Not found"}

- ))} -
-
-
- -

- IMPORTANT: Please use adblockers like uBlock Orgin - or Ghostery for an ad free experience. -

-
-
-
-
+
+ +
); -} - -const get_movie_info = async (id) => { - const res = await fetch(getInfoURL(id), { next: { revalidate: 21620 } }); - const data = await res.json(); - return data; }; + +export default MovieInfoPage; diff --git a/src/app/movies/components/cacher.js b/src/app/movies/components/cacher.js index 169508a..801fe95 100644 --- a/src/app/movies/components/cacher.js +++ b/src/app/movies/components/cacher.js @@ -1,10 +1,9 @@ -import { getInfoURL } from "../../../../utils/movie_urls"; +import { MovieInfoData } from "./requestsHandler"; const PreFetchMovieInfo = async (data) => { try { const fetchPromises = data.results.map(async (element) => { - const link = `${getInfoURL(element.id)}`; - await fetch(link, { next: { revalidate: 21600 } }); + await MovieInfoData(element.id); }); await Promise.all(fetchPromises); diff --git a/src/app/movies/components/descriptionTabs.jsx b/src/app/movies/components/descriptionTabs.jsx new file mode 100644 index 0000000..2f5ca91 --- /dev/null +++ b/src/app/movies/components/descriptionTabs.jsx @@ -0,0 +1,67 @@ +"use client"; + +import { Tabs, Tab, Card, CardBody, Link } from "@nextui-org/react"; +import { FiThumbsUp } from "react-icons/fi"; +import { TiStarFullOutline } from "react-icons/ti"; + +import { lexend, atkinson } from "../../../../config/fonts"; + +export default function DescriptionTabs({ data: data }) { + return ( +
+ + + + + {data.overview || "No description found"} + + + + + + +

+ Tagline:{" "} + {data.tagline || "not sure"} +

+

+ Homepage:{" "} + + + {data.homepage || "not sure"} + + +

+

+ Released on:{" "} + {data.release_date || "not sure"} +

+

+ Status:{" "} + {data.status || "not sure"} +

+

+ + + + + {data.vote_count || "not sure"} + + + + + + {data.vote_average || "not sure"} + +

+
+
+
+
+
+ ); +} diff --git a/src/app/movies/components/faqs.jsx b/src/app/movies/components/faqs.jsx new file mode 100644 index 0000000..4fa5043 --- /dev/null +++ b/src/app/movies/components/faqs.jsx @@ -0,0 +1,33 @@ +"use client"; + +import { Accordion, AccordionItem } from "@nextui-org/react"; + +const Questions = () => { + return ( + + + We do not host any media on our own servers. We simply aggregate + data from third-party providers. While these services are free + for public use, someone has to bear the costs of hosting the + servers and infrastructure. Therefore, the video player includes + advertisements to help cover these expenses. + + + To avoid ads, you can utilize ad blockers such as Ghostery, + uBlock Origin, or any preferred ad blocker. Adjust your browser + settings to maximize tracking prevention or similar features for + enhanced protection against ads + + + ); +}; + +export default Questions; diff --git a/src/app/movies/components/popular.jsx b/src/app/movies/components/popular.jsx deleted file mode 100644 index 3ef0501..0000000 --- a/src/app/movies/components/popular.jsx +++ /dev/null @@ -1,49 +0,0 @@ -import { POPULAR } from "../../../../utils/movie_urls"; -import PreFetchMovieInfo from "./cacher"; -import styles from "../styles/pop_trend.module.css"; -import Image from "next/image"; -import Link from "next/link"; - -export default async function POPULAR_MOVIES() { - const data = await get_popular(); - PreFetchMovieInfo(data); - - return ( -
-

Popular Movies

-
- {data && - data.results && - data.results.slice(0, 16).map((item, index) => ( - -
-
- Movie Poster -

{item.title}

-
-
- - ))} -
-
- ); -} - -const get_popular = async () => { - const res = await fetch(POPULAR, { next: { revalidate: 21600 } }); - const data = await res.json(); - return data; -}; diff --git a/src/app/movies/components/requestsHandler.js b/src/app/movies/components/requestsHandler.js new file mode 100644 index 0000000..5f4db8b --- /dev/null +++ b/src/app/movies/components/requestsHandler.js @@ -0,0 +1,36 @@ +"use server"; + +import { + SEARCH, + TRENDING, + POPULAR, + getInfoURL, + TOP_RATED, + NOW_IN_THEATERS, + UPCOMING_MOVIES, +} from "../../../../utils/movie_urls"; + +export const SearchMovie = async (title) => { + const res = await fetch(SEARCH(title), { next: { revalidate: 21600 } }); + const data = await res.json(); + return data; +}; + +export const MovieHomepageDataFetcher = async (type) => { + const dataAvailable = { + trending: TRENDING, + popular: POPULAR, + top: TOP_RATED, + }; + const res = await fetch(dataAvailable[type], { + next: { revalidate: 21600 }, + }); + const data = await res.json(); + return data; +}; + +export const MovieInfoData = async (id) => { + const res = await fetch(getInfoURL(id), { cache: "force-cache" }); + const data = await res.json(); + return data; +}; diff --git a/src/app/movies/components/search.jsx b/src/app/movies/components/search.jsx index dca163a..35b8432 100644 --- a/src/app/movies/components/search.jsx +++ b/src/app/movies/components/search.jsx @@ -1,38 +1,53 @@ "use client"; import { useState } from "react"; -import styles from "../styles/search.module.css"; -import { FaSearch } from "react-icons/fa"; -import SearchResults from "./search_2"; +import { Input, Progress } from "@nextui-org/react"; -export default function SEARCH_COMPONENT() { - const [title, setTitle] = useState(""); - const [result, setResults] = useState(null); +import { SearchMovie } from "./requestsHandler"; +import MovieSearchFormatter from "./searchFormatter"; - const fetch_results = async (title) => { - setResults(await SearchResults(title)); - }; +const MovieSearchBar = () => { + const [movieTitle, setMovieTitle] = useState(""); + const [loading, setLoading] = useState(<>); + const [movieResults, setMovieResults] = useState(<>); + + async function handleInputChange() { + setLoading( + + ); + const data = await SearchMovie(movieTitle); + setLoading(<>); + setMovieResults(await MovieSearchFormatter(data)); + } return ( -
-
- - setTitle(event.target.value)} - onKeyDown={async (e) => { - if ((e.key === "Enter" || e.code === 13) && title) { - await fetch_results(e.target.value); +
+
+ { + if (event.target.value.trim() !== "") { + setMovieTitle(event.target.value); } }} - > -
- -
{result}
-
+ onKeyDown={async (event) => { + if (event.key === "Enter" || event.code === "Enter") { + await handleInputChange(); + } + }} + /> + {loading} +
+
{movieResults}
+
); -} +}; + +export default MovieSearchBar; diff --git a/src/app/movies/components/searchFormatter.jsx b/src/app/movies/components/searchFormatter.jsx new file mode 100644 index 0000000..47b684f --- /dev/null +++ b/src/app/movies/components/searchFormatter.jsx @@ -0,0 +1,51 @@ +import { Card, CardHeader, CardBody, Image, Link } from "@nextui-org/react"; +import NextImage from "next/image"; + +import styles from "../../page.module.css"; + +const MovieSearchFormatter = async (data) => { + return ( +
+ {data && + data.results.map((item, index) => { + if (item.poster_path) { + return ( + + + + Anime Poster + + +

+ {item.original_title} +

+
+
+ + ); + } + })} +
+ ); +}; + +export default MovieSearchFormatter; diff --git a/src/app/movies/components/search_2.jsx b/src/app/movies/components/search_2.jsx deleted file mode 100644 index cf3fc69..0000000 --- a/src/app/movies/components/search_2.jsx +++ /dev/null @@ -1,63 +0,0 @@ -"use server"; - -import { SEARCH } from "../../../../utils/movie_urls"; -import PreFetchMovieInfo from "./cacher"; -import Image from "next/image"; -import Link from "next/link"; -import styles from "../styles/search.module.css"; - -const SearchResults = async (title) => { - const data = await get_search_results(title); - PreFetchMovieInfo(data); - if (data.results.length > 0) { - return ( -
- {data && - data.results && - data.results.map((item, index) => { - if (item.poster_path) { - return ( - -
-

- {item.title || item.original_title} -

- Movie Poster -
- - ); - } - })} -
- ); - } else { - return

No results found!

; - } -}; - -const get_search_results = async (title) => { - const res = await fetch(SEARCH + title, { next: { revalidate: 21600 } }); - const data = await res.json(); - return data; -}; - -export default SearchResults; diff --git a/src/app/movies/components/trending.jsx b/src/app/movies/components/trending.jsx deleted file mode 100644 index 8e20ba1..0000000 --- a/src/app/movies/components/trending.jsx +++ /dev/null @@ -1,48 +0,0 @@ -import { TRENDING } from "../../../../utils/movie_urls"; -import PreFetchMovieInfo from "./cacher"; -import styles from "../styles/pop_trend.module.css"; -import Link from "next/link"; -import Image from "next/image"; - -export default async function TREDNING_MOVIES() { - const data = await get_popular(); - PreFetchMovieInfo(data); - - return ( -
-

Trending Movies

-
- {data && - data.results && - data.results.slice(0, 16).map((item, index) => ( - -
-
- Movie Poster -

{item.title}

-
-
- - ))} -
-
- ); -} - -const get_popular = async () => { - const res = await fetch(TRENDING, { next: { revalidate: 21620 } }); - const data = await res.json(); - return data; -}; diff --git a/src/app/movies/components/videoPlayer.jsx b/src/app/movies/components/videoPlayer.jsx new file mode 100644 index 0000000..b7cdd81 --- /dev/null +++ b/src/app/movies/components/videoPlayer.jsx @@ -0,0 +1,17 @@ +const MovieVideoPlayer = async ({ id: id }) => { + const videoFrameGenerator = (id) => { + return ( + + ); + }; + + return
{videoFrameGenerator(id)}
; +}; + +export default MovieVideoPlayer; diff --git a/src/app/movies/components/video_player.jsx b/src/app/movies/components/video_player.jsx deleted file mode 100644 index 74f6180..0000000 --- a/src/app/movies/components/video_player.jsx +++ /dev/null @@ -1,68 +0,0 @@ -"use client"; - -import styles from "../styles/video_player.module.css"; -import { useState, useEffect } from "react"; - -export default function VIDEO_PLAYER({ id: id }) { - const [frame, setFrame] = useState(null); - - useEffect(() => { - make_player(`https://vidsrc.icu/embed/movie/${id}`); - }, []); - - function make_player(url) { - setFrame( - - ); - } - - return ( -
-
- - - - - -
- {frame} -
- ); -} diff --git a/src/app/movies/page.jsx b/src/app/movies/page.jsx index 24c2ed9..c9c8e8e 100644 --- a/src/app/movies/page.jsx +++ b/src/app/movies/page.jsx @@ -1,17 +1,81 @@ -import POPULAR_MOVIES from "./components/popular"; -import TREDNING_MOVIES from "./components/trending"; -import SEARCH_COMPONENT from "./components/search"; -import styles from "./styles/page.module.css"; +import { Card, CardHeader, CardBody, Image, Link } from "@nextui-org/react"; +import NextImage from "next/image"; + +import MovieSearchBar from "./components/search"; +import { MovieHomepageDataFetcher } from "./components/requestsHandler"; +import PreFetchMovieInfo from "./components/cacher"; +import styles from "../page.module.css"; export default async function MOVIE_HOME() { + const popular_data = await MovieHomepageDataFetcher("popular"); + const trending_data = await MovieHomepageDataFetcher("trending"); + const top_data = await MovieHomepageDataFetcher("top"); + + const dataToBeLoaded = [popular_data, trending_data]; + + for (let items of dataToBeLoaded) { + PreFetchMovieInfo(items); + } + + const dataFormatter = (title, data) => { + return ( +
+

{title}

+ +
+ {data && + data.results.map((item, index) => ( + + + + Anime Poster + + +

+ {item.original_title} +

+
+
+ + ))} +
+
+ ); + }; + return ( -
- - -
- -
-
+
+
+ +
+
+ {dataFormatter("Popular Movies", popular_data)} +
+ {dataFormatter("Trending Movies", trending_data)} +
+
+ {dataFormatter("Top Rated Movies", top_data)} +
+

); diff --git a/src/app/movies/styles/info.module.css b/src/app/movies/styles/info.module.css deleted file mode 100644 index b848f7f..0000000 --- a/src/app/movies/styles/info.module.css +++ /dev/null @@ -1,150 +0,0 @@ -.Main { - margin-top: 60px; - color: white; -} - -.MovieInfoSection { - background-color: #1f1f1fcc; - backdrop-filter: blur(10px); -} - -.MovieInfo { - max-width: 60%; - margin: 0 auto; -} - -.HeroSection { - display: flex; - align-items: center; -} - -.HeroSection img { - border-radius: 1rem; - padding: 0.5rem 0 0 0; -} - -.HeroTitle { - display: flex; - flex-direction: column; - margin-left: 0.6rem; - padding: 0.3rem; -} - -.HeroTitle h2 { - font-size: 28px; - margin: 0; -} - -.tagline { - margin: 0.2rem 0 0 0; - font-size: 12px; -} - -.tagline span { - background-color: #12121286; - padding: 0.2rem; - border-radius: 0.5rem; -} - -.MovieDescription { - font-size: 18px; - margin: 0.2rem 0 0 0; - max-height: 140px; - overflow: auto; -} - -.MovieDescription::-webkit-scrollbar { - width: 5px; -} - -.MovieDescription::-webkit-scrollbar-thumb { - background-color: var(--nord-yellow); - border-radius: 1rem; -} - -.OtherInfo { - display: flex; - flex-direction: column; - align-items: center; - margin: 1rem 0 0 0; - background-color: #12121286; - padding: 1rem; - border-radius: 0.5rem; -} - -.Ratings { - display: flex; -} - -.divider { - margin: 0 0.5rem 0 0.5rem; -} - -.Ratings span { - display: flex; - align-items: center; - justify-content: center; -} - -.Ratings p { - margin: 0 0 0 0.4rem; -} - -.Money { - margin: 0.5rem 0 0 0; - display: flex; -} - -.Money p { - margin: 0 0 0 0.4rem; -} - -.Money span { - display: flex; - align-items: center; -} - -.Genre { - display: flex; -} - -.Genre p { - background-color: #12121257; - margin: 0.5rem 0.2rem 0 0.2rem; - padding: 0.3rem; - border-radius: 0.5rem; -} - -@media screen and (max-width: 768px) { - .MovieInfo { - max-width: 100%; - } - - .VideoPlayer { - width: 98%; - margin: 1rem auto; - } - - .VideoPlayer iframe { - height: 250px; - } - - .HeroTitle h2 { - font-size: 22px; - } - - .HeroSection img { - width: 170px; - height: 267px; - } - - .MovieDescription { - font-size: 16px; - } - - .OtherInfo { - width: 90%; - margin: 1rem auto; - } - -} \ No newline at end of file diff --git a/src/app/movies/styles/page.module.css b/src/app/movies/styles/page.module.css deleted file mode 100644 index 5cba0a1..0000000 --- a/src/app/movies/styles/page.module.css +++ /dev/null @@ -1,3 +0,0 @@ -.MovieMain { - margin-top: 65px; -} diff --git a/src/app/movies/styles/pop_trend.module.css b/src/app/movies/styles/pop_trend.module.css deleted file mode 100644 index 362debd..0000000 --- a/src/app/movies/styles/pop_trend.module.css +++ /dev/null @@ -1,79 +0,0 @@ -.Main { - color: white; - margin-left: 0.2rem; - margin-right: 0.2rem; -} - -.Main h2 { - color: white; - margin: 0.4rem 0 0 0; - text-transform: uppercase; - font-size: 30px; -} - -.MovieContainer { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); - grid-gap: 0.5rem; - align-items: center; -} - -.MovieContainer::-webkit-scrollbar { - height: 0; -} - -.MovieContainer:hover .MovieEntryPrev { - opacity: 0.5; -} - -.MovieContainer:hover .MovieEntryPrev:hover { - opacity: 1; - transform: translateY(-5px) scale(1.02); - -} - -.MovieEntryPrev { - transition: opacity 200ms ease, transform 200ms ease; -} - -.MovieEntry { - background-color: #1f1f1fc2; - padding: 0.5rem; - /* border-radius: 0.5rem; */ - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - cursor: pointer; - backdrop-filter: blur(10px); - border-radius: 0.5rem; - overflow: hidden; -} - -.MovieEntry img { - border-radius: 0.5rem; - box-shadow: 0px 0px 10px 8px rgb(32, 32, 32); -} - - -.MovieEntry p { - width: 160px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - text-align: center; - margin: 0.3rem 0 0 0; -} - -@media screen and (max-width: 768px) { - .Main h1 { - font-size: 24px; - text-align: start; - } - - .MovieContainer { - display: flex; - overflow-x: auto; - overflow-y: hidden; - } -} \ No newline at end of file diff --git a/src/app/movies/styles/search.module.css b/src/app/movies/styles/search.module.css deleted file mode 100644 index d3b1a75..0000000 --- a/src/app/movies/styles/search.module.css +++ /dev/null @@ -1,84 +0,0 @@ -.Main { - margin: 0 0.4rem 0 0.4rem; -} - -.InputContainer { - display: flex; - align-items: center; - background-color: #1f1f1f; - padding: 0.4rem; - 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%; - font-size: 20px; -} - -/* Search Results */ - -.MovieSearchResultsContainer { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); - grid-gap: 0.5rem; - align-items: center; - margin: 0.2rem 0.2rem 0 0.2rem; -} - -.MovieSearchResultsContainer:hover .MovieResultsPrev { - opacity: 0.5; -} - -.MovieSearchResultsContainer:hover .MovieResultsPrev:hover { - opacity: 1; - scale: 1.02; -} - -.MovieResultsPrev { - transition: opacity 200ms ease, scale 200ms ease; -} - -.MovieEntry { - display: flex; - align-items: center; - justify-content: space-between; - color: white; - backdrop-filter: blur(10px); - padding: 0.4rem; - background-color: #1212129f; -} - -.MovieEntry img { - border-radius: 0.5rem; -} - -.MovieEntry p { - margin: 0 0.2rem 0 0; - font-size: 18px; -} - -.NoResults { - color: white; - text-align: center; -} - -@media screen and (max-width: 768px) { - .InputContainer { - width: 100%; - } -} \ No newline at end of file diff --git a/src/app/movies/styles/video_player.module.css b/src/app/movies/styles/video_player.module.css deleted file mode 100644 index 2e022f0..0000000 --- a/src/app/movies/styles/video_player.module.css +++ /dev/null @@ -1,31 +0,0 @@ -.VideoContainer { - margin: 0.5rem 0 0 0; -} - -.VideoContainer button { - font-family: "Lexend Deca", serif; - outline: none; - border: none; - background-color: #121212be; - - color: white; - margin-right: 0.2rem; - padding: 0.5rem; - border-radius: 0.5rem; - cursor: pointer; -} - -.sourcesButtonContainer { - display: flex; - overflow: auto; -} - -.VideoPlayer { - width: 100%; - height: 700px; - aspect-ratio: "16/9"; - border: none; - outline: none; - border-radius: 0.5rem; - margin: 0.5rem 0 0 0; -} \ No newline at end of file -- cgit v1.2.3