aboutsummaryrefslogtreecommitdiff
path: root/src/app/web-series/components
diff options
context:
space:
mode:
authorreal-zephex <[email protected]>2024-05-29 01:04:20 +0530
committerGitHub <[email protected]>2024-05-29 01:04:20 +0530
commite28fba92670b5c2775a512511346136991698cbc (patch)
tree5d40f1b802af30859b06e4c7f577fd50f3cc74cb /src/app/web-series/components
parentMerge pull request #39 from real-zephex/homepage-redesign (diff)
parent✨ feat(series): rewrite series page and drop manga support (diff)
downloaddramalama-e28fba92670b5c2775a512511346136991698cbc.tar.xz
dramalama-e28fba92670b5c2775a512511346136991698cbc.zip
Merge pull request #41 from real-zephex/series-overhaul
✨ feat(series): rewrite series page and drop manga support
Diffstat (limited to 'src/app/web-series/components')
-rw-r--r--src/app/web-series/components/HomePageModules.jsx56
-rw-r--r--src/app/web-series/components/descriptionTabs.jsx129
-rw-r--r--src/app/web-series/components/search.jsx57
-rw-r--r--src/app/web-series/components/searchBar.jsx49
-rw-r--r--src/app/web-series/components/searchResults.jsx35
-rw-r--r--src/app/web-series/components/seriesSearchFormatter.jsx49
-rw-r--r--src/app/web-series/components/videoPlayer.jsx100
7 files changed, 290 insertions, 185 deletions
diff --git a/src/app/web-series/components/HomePageModules.jsx b/src/app/web-series/components/HomePageModules.jsx
deleted file mode 100644
index 91d90bf..0000000
--- a/src/app/web-series/components/HomePageModules.jsx
+++ /dev/null
@@ -1,56 +0,0 @@
-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={180}
- height={300}
- 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/descriptionTabs.jsx b/src/app/web-series/components/descriptionTabs.jsx
new file mode 100644
index 0000000..ec6a78b
--- /dev/null
+++ b/src/app/web-series/components/descriptionTabs.jsx
@@ -0,0 +1,129 @@
+"use client";
+
+import {
+ Tabs,
+ Tab,
+ Card,
+ CardBody,
+ Link,
+ Image,
+ Chip,
+} 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 SeriesDescriptionTabs({ data: data }) {
+ return (
+ <div className="flex w-full flex-col">
+ <Tabs aria-label="Options" className={lexend.className}>
+ <Tab key="description" title="Description">
+ <Card>
+ <CardBody className={atkinson.className}>
+ {data.overview || "No description found"}
+ </CardBody>
+ </Card>
+ </Tab>
+ <Tab key="episodes" title="Details">
+ <Card>
+ <CardBody className={lexend.className}>
+ <h4>
+ <strong>Tagline</strong>:{" "}
+ <span>{data.tagline || "not sure"}</span>
+ </h4>
+ <h4>
+ <strong>Homepage</strong>:{" "}
+ <span>
+ <Link
+ color="warning"
+ isExternal
+ href={data.homepage || ""}
+ >
+ {data.homepage || "not sure"}
+ </Link>
+ </span>
+ </h4>
+ <h4>
+ <strong className="text-success">
+ Episodes:
+ </strong>{" "}
+ <span>
+ {data.number_of_episodes || "not sure"}
+ </span>
+ </h4>
+ <h4>
+ <strong className="text-secondary">
+ Seasons:
+ </strong>{" "}
+ <span>
+ {data.number_of_seasons || "not sure"}
+ </span>
+ </h4>
+ <h4>
+ <strong>Status</strong>:{" "}
+ <span>{data.status || "not sure"}</span>
+ </h4>
+ <h4>
+ <strong>Released on</strong>:{" "}
+ <span>{data.first_air_date || "not sure"}</span>
+ </h4>
+ <h4 className="flex items-center">
+ <strong>
+ <FiThumbsUp />
+ </strong>
+ <span className="ml-2">
+ {data.vote_count || "not sure"}
+ </span>
+ <strong className="ml-3">
+ <TiStarFullOutline />
+ </strong>
+ <span className="ml-2">
+ {data.vote_average || "not sure"}
+ </span>
+ </h4>
+ </CardBody>
+ </Card>
+ </Tab>
+ <Tab key="seasons" title="Seasons">
+ <Card>
+ <CardBody>
+ {data.seasons &&
+ data.seasons.map((item, index) => (
+ <Card
+ key={index}
+ className="flex flex-row items-center mb-1"
+ isPressable
+ shadow="lg"
+ >
+ <Image
+ src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=https://image.tmdb.org/t/p/original${item.poster_path}`}
+ width={100}
+ isBlurred
+ shadow="lg"
+ className="p-1"
+ ></Image>
+ <CardBody className="ml-1">
+ <p className="text-sky-400">
+ {item.name}
+ </p>
+ <Chip
+ color="warning"
+ size="sm"
+ variant="faded"
+ className="mt-1"
+ >
+ {item.air_date
+ ? item.air_date
+ : "TBD "}
+ </Chip>
+ </CardBody>
+ </Card>
+ ))}
+ </CardBody>
+ </Card>
+ </Tab>
+ </Tabs>
+ </div>
+ );
+}
diff --git a/src/app/web-series/components/search.jsx b/src/app/web-series/components/search.jsx
new file mode 100644
index 0000000..ecf392c
--- /dev/null
+++ b/src/app/web-series/components/search.jsx
@@ -0,0 +1,57 @@
+"use client";
+
+import { useState } from "react";
+import { Input, Progress } from "@nextui-org/react";
+
+import { SEARCH_TV } from "./data-fetch";
+import SeriesSearchFormatter from "./seriesSearchFormatter";
+import PreFecthSeriesInfo from "./cacher";
+// import { SearchMovie } from "./requestsHandler";
+// import MovieSearchFormatter from "./searchFormatter";
+
+const SeriesSearchBar = () => {
+ const [seriesTitle, setSeriesTitle] = useState("");
+ const [loading, setLoading] = useState(<></>);
+ const [seriesResults, setSeriesResults] = useState(<></>);
+
+ async function handleInputChange() {
+ setLoading(
+ <Progress
+ size="sm"
+ isIndeterminate
+ aria-label="Loading..."
+ className="w-full"
+ />
+ );
+ const data = await SEARCH_TV(seriesTitle);
+ PreFecthSeriesInfo(data);
+ setLoading(<></>);
+ setSeriesResults(await SeriesSearchFormatter(data));
+ }
+
+ return (
+ <section>
+ <div className="flex flex-col w-full md:flex-nowrap gap-2 lg:w-1/2">
+ <Input
+ type="text"
+ label="Search for series"
+ placeholder="Enter series title"
+ onChange={(event) => {
+ if (event.target.value.trim() !== "") {
+ setSeriesTitle(event.target.value);
+ }
+ }}
+ onKeyDown={async (event) => {
+ if (event.key === "Enter" || event.code === "Enter") {
+ await handleInputChange();
+ }
+ }}
+ />
+ {loading}
+ </div>
+ <div className="mt-2">{seriesResults}</div>
+ </section>
+ );
+};
+
+export default SeriesSearchBar;
diff --git a/src/app/web-series/components/searchBar.jsx b/src/app/web-series/components/searchBar.jsx
deleted file mode 100644
index 42531bc..0000000
--- a/src/app/web-series/components/searchBar.jsx
+++ /dev/null
@@ -1,49 +0,0 @@
-"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={22}
- />
- <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
deleted file mode 100644
index d1564e0..0000000
--- a/src/app/web-series/components/searchResults.jsx
+++ /dev/null
@@ -1,35 +0,0 @@
-"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/seriesSearchFormatter.jsx b/src/app/web-series/components/seriesSearchFormatter.jsx
new file mode 100644
index 0000000..408e7c0
--- /dev/null
+++ b/src/app/web-series/components/seriesSearchFormatter.jsx
@@ -0,0 +1,49 @@
+import { Card, CardHeader, CardBody } from "@nextui-org/react";
+import Link from "next/link";
+import Image from "next/image";
+
+import styles from "../../page.module.css";
+
+const SeriesSearchFormatter = async (data) => {
+ return (
+ <section
+ className={`flex items-center overflow-auto pb-2 mb-2 ${styles.ScrollBarAdjuster}`}
+ >
+ {data &&
+ data.results.map((item, index) => {
+ if (item.poster_path) {
+ return (
+ <Link
+ key={index}
+ href={`/web-series/${item.id}`}
+ aria-label="anime redirection links"
+ className="flex flex-col items-center mx-1 "
+ >
+ <Card className="overflow-hidden" isPressable>
+ <CardBody>
+ <Image
+ alt="Searched Movie Poster"
+ src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=https://image.tmdb.org/t/p/original${item.poster_path}`}
+ width={190}
+ height={120}
+ className="rounded-md h-64"
+ priority
+ />
+ </CardBody>
+ <CardHeader>
+ <h4
+ className={`antialiased text-small text-center uppercase w-44 overflow-hidden whitespace-nowrap text-ellipsis `}
+ >
+ {item.name}
+ </h4>
+ </CardHeader>
+ </Card>
+ </Link>
+ );
+ }
+ })}
+ </section>
+ );
+};
+
+export default SeriesSearchFormatter;
diff --git a/src/app/web-series/components/videoPlayer.jsx b/src/app/web-series/components/videoPlayer.jsx
index cc8feb3..50a703d 100644
--- a/src/app/web-series/components/videoPlayer.jsx
+++ b/src/app/web-series/components/videoPlayer.jsx
@@ -1,66 +1,76 @@
"use client";
-import { useState } from "react";
-import styles from "../styles/videoPlayer.module.css";
+import { useEffect, useState } from "react";
-const SeriesPlayer = ({ id: id }) => {
- const [iframe, iframeContent] = useState(null);
- const [episode, setEpisode] = useState("");
- const [season, setSeason] = useState("");
+import { Input } from "@nextui-org/react";
- async function VideoPlayerInitialize() {
- if (!episode || !season) {
- alert("Please provide the required episode and season number.");
+const SeriesVideoPlayer = ({ id: id }) => {
+ const [seasonNumber, setSeasonNumber] = useState("");
+ const [episodeNumber, setEpisodeNumber] = useState("");
+ const [videoFrame, setVideoFrame] = useState(<></>);
+
+ useEffect(() => {
+ setVideoFrame(VideoFrameGenerator(1, 1));
+ }, []);
+
+ const VideoFrameGenerator = (sea, epi) => {
+ return (
+ <iframe
+ src={`https://vidsrc.pro/embed/tv/${id}/${sea}/${epi}`}
+ allowFullScreen
+ referrerPolicy="origin"
+ height={720}
+ className="w-full h-[240px] lg:h-[720px]"
+ ></iframe>
+ );
+ };
+
+ function renderVideoFrame() {
+ if (seasonNumber === "" || episodeNumber === "") {
+ alert(
+ "Make sure that you have entered the episode number and the season number."
+ );
return;
}
- iframeContent(await iframeGenerator(id, season, episode));
- document.getElementById("video-player").style.display = "none";
+
+ setVideoFrame(VideoFrameGenerator(seasonNumber, episodeNumber));
}
return (
- <main className={styles.Main}>
- <div className={styles.EpisodeSeasonInput}>
- <input
- name="Season"
+ <div>
+ {videoFrame}
+ <div className="flex w-full items-center md:flex-nowrap gap-2 mt-2">
+ <Input
type="number"
+ label="Season"
placeholder="Season Number"
- onChange={(e) => {
- if (Number(e.target.value) > 0) {
- setSeason(e.target.value);
+ isRequired
+ onChange={(event) => {
+ setSeasonNumber(event.target.value);
+ }}
+ onKeyDown={(event) => {
+ if (event.key === "Enter" || event.code === "Enter") {
+ renderVideoFrame();
}
}}
- ></input>
- <input
- name="Episode"
+ />
+ <Input
type="number"
+ label="Episode"
placeholder="Episode Number"
- onChange={(e) => {
- if (Number(e.target.value) > 0) {
- setEpisode(e.target.value);
+ isRequired
+ onChange={(event) => {
+ setEpisodeNumber(event.target.value);
+ }}
+ onKeyDown={(event) => {
+ if (event.key === "Enter" || event.code === "Enter") {
+ renderVideoFrame();
}
}}
- ></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>
+ </div>
);
};
-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;
+export default SeriesVideoPlayer;