Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added MOVIES support #17

Merged
merged 4 commits into from May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ const nextConfig = {
protocol: "https",
hostname: "sup-proxy.zephex0-f6c.workers.dev",
},
{
protocol: "https",
hostname: "image.tmdb.org",
},
],
},
logging: {
Expand All @@ -40,9 +44,9 @@ const nextConfig = {
},
experimental: {
serverActions: {
allowedOrigins: ["localhost:3000"]
}
}
allowedOrigins: ["localhost:3000"],
},
},
};

export default nextConfig;
3 changes: 2 additions & 1 deletion src/app/components/header/header.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Link from "next/link";
import styles from "../../page.module.css";

export default function Header() {
export default async function Header() {
return (
<main className={styles.main}>
<div className={styles.header}>
Expand All @@ -17,6 +17,7 @@ export default function Header() {
<Link href="/anime">Anime</Link>
<Link href="/kdrama">Kdrama</Link>
<Link href="/manga">Manga</Link>
<Link href="/movies">Movies</Link>
</div>
</div>
</main>
Expand Down
117 changes: 117 additions & 0 deletions src/app/movies/[id]/page.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
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";

export default async function MOVIE_INFO({ params }) {
const id = params.id;
const data = await get_movie_info(id);

return (
<main
style={{
backgroundImage: `url(https://image.tmdb.org/t/p/original${data.backdrop_path})`,
backgroundRepeat: "no-repeat",
backgroundSize: "cover",
}}
className={styles.Main}
>
<section className={styles.MovieInfoSection}>
<section className={styles.MovieInfo}>
<div className={styles.HeroSection}>
<Image
src={`https://image.tmdb.org/t/p/original${data.poster_path}`}
width={200}
height={300}
alt="Movie Poster"
priority
></Image>
<div className={styles.HeroTitle}>
<h2>{data.title || "Not found"}</h2>
<p className={styles.tagline}>
<span>{data.tagline || "Not found"}</span>
</p>
<p className={styles.MovieDescription}>
{data.overview || "Not found"}
</p>
</div>
</div>
<div className={styles.OtherInfo}>
<section className={styles.Ratings}>
<span>
<PiThumbsUpFill size={16} />
<p>{data.vote_average || "Not found"}</p>
</span>
<span className={styles.divider}>
<RxDividerVertical size={22} />
</span>
<span>
<FaRegCheckCircle size={16} />
<p>{data.vote_count || "Not found"}</p>
</span>
</section>
<section className={styles.Money}>
<span title="revenue">
<FaSackDollar />
<p>
$
{data.revenue.toLocaleString() ||
"Not found"}
</p>
</span>
<span className={styles.divider}>
<RxDividerVertical size={22} />
</span>
<span title="budget">
<FaDollarSign />
<p>
$
{data.budget.toLocaleString() ||
"Not found"}
</p>
</span>
</section>
<section className={styles.Money}>
<span title="Released on">
<p>Release Date: {data.release_date}</p>
</span>
</section>
<section className={styles.Genre}>
{data.genres.map((item) => (
<p key={item.id}>{item.name || "Not found"}</p>
))}
</section>
</div>
<section className={styles.VideoPlayer}>
<VIDEO_PLAYER id={id} />
<p
style={{
textAlign: "center",
margin: 0,
fontSize: 14,
}}
>
NOTE: Please wait for some time for the video to
load. If it buffers for a long time, then try
chanding the server. If the issue persists, please
check your internet connection.
</p>
</section>
<br />
<br />
</section>
</section>
</main>
);
}

const get_movie_info = async (id) => {
const res = await fetch(getInfoURL(id), { next: { revalidate: 21620 } });
const data = await res.json();
return data;
};
17 changes: 17 additions & 0 deletions src/app/movies/components/cacher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { getInfoURL } from "../../../../utils/movie_urls";

const PreFetchMovieInfo = async (data) => {
try {
const fetchPromises = data.results.map(async (element) => {
const link = `${getInfoURL(element.id)}`;
await fetch(link, { next: { revalidate: 21600 } });
});

await Promise.all(fetchPromises);
console.log("Movie info pre-fetched successfully!");
} catch (error) {
console.error("Error occurred while pre-fetching video links:", error);
}
};

export default PreFetchMovieInfo;
58 changes: 58 additions & 0 deletions src/app/movies/components/popular.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
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 (
<main className={styles.Main}>
<h1>Popular Movies</h1>
<section className={styles.MovieContainer}>
{data &&
data.results &&
data.results.slice(0, 16).map((item, index) => (
<Link
href={`/movies/${item.id}`}
style={{
textDecoration: "none",
color: "white",
}}
key={index}
>
<div
style={{
borderRadius: "0.5rem",
overflow: "hidden",
backgroundImage: `url(https://image.tmdb.org/t/p/original${item.backdrop_path})`,
backgroundRepeat: "no-repeat",
backgroundSize: "cover",
}}
className={styles.MovieEntryPrev}
>
<div className={styles.MovieEntry}>
<Image
src={`https://image.tmdb.org/t/p/original${item.poster_path}`}
width={200}
height={300}
alt="Movie Poster"
priority
></Image>
<p>{item.title}</p>
</div>
</div>
</Link>
))}
</section>
</main>
);
}

const get_popular = async () => {
const res = await fetch(POPULAR, { next: { revalidate: 21600 } });
const data = await res.json();
return data;
};
38 changes: 38 additions & 0 deletions src/app/movies/components/search.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"use client";

import { useState } from "react";
import styles from "../styles/search.module.css";
import { FaSearch } from "react-icons/fa";
import SearchResults from "./search_2";

export default function SEARCH_COMPONENT() {
const [title, setTitle] = useState("");
const [result, setResults] = useState(null);

const fetch_results = async (title) => {
setResults(await SearchResults(title));
};

return (
<main className={styles.Main}>
<section className={styles.InputContainer}>
<FaSearch
color="white"
className={styles.SearchIcon}
size={17}
/>
<input
placeholder="Enter movie 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>

<section className={styles.SearchResults}>{result}</section>
</main>
);
}
57 changes: 57 additions & 0 deletions src/app/movies/components/search_2.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"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);
return (
<div className={styles.MovieSearchResultsContainer}>
{data &&
data.results &&
data.results.map((item, index) => {
if (item.poster_path) {
return (
<Link
href={`/movies/${item.id}`}
key={index}
style={{
backgroundImage: `url(https://image.tmdb.org/t/p/original${item.backdrop_path})`,
backgroundRepeat: "no-repeat",
backgroundSize: "cover",
textDecoration: "none",
color: "white",
borderRadius: "0.5rem",
overflow: "hidden",
}}
className={styles.MovieResultsPrev}
>
<section className={styles.MovieEntry}>
<p>{item.title || item.original_title}</p>
<Image
src={`https://image.tmdb.org/t/p/original${item.poster_path}`}
width={130}
height={230}
alt="Movie Poster"
priority
/>
</section>
</Link>
);
}
})}
</div>
);
};

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;
57 changes: 57 additions & 0 deletions src/app/movies/components/trending.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
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 (
<main className={styles.Main}>
<h1>Trending Movies</h1>
<section className={styles.MovieContainer}>
{data &&
data.results &&
data.results.slice(0, 16).map((item, index) => (
<Link
href={`/movies/${item.id}`}
style={{
textDecoration: "none",
color: "white",
}}
key={index}
>
<div
style={{
borderRadius: "0.5rem",
overflow: "hidden",
backgroundImage: `url(https://image.tmdb.org/t/p/original${item.backdrop_path})`,
backgroundRepeat: "no-repeat",
backgroundSize: "cover",
}}
className={styles.MovieEntryPrev}
>
<div className={styles.MovieEntry}>
<Image
src={`https://image.tmdb.org/t/p/original${item.poster_path}`}
width={200}
height={300}
alt="Movie Poster"
></Image>
<p>{item.title}</p>
</div>
</div>
</Link>
))}
</section>
</main>
);
}

const get_popular = async () => {
const res = await fetch(TRENDING, { next: { revalidate: 21620 } });
const data = await res.json();
return data;
};
Loading