aboutsummaryrefslogtreecommitdiff
path: root/src/app/anime
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/anime')
-rw-r--r--src/app/anime/[id]/[animeId]/page.jsx56
-rw-r--r--src/app/anime/[id]/[animeId]/video.css30
-rw-r--r--src/app/anime/[id]/info.css83
-rw-r--r--src/app/anime/[id]/loading.css346
-rw-r--r--src/app/anime/[id]/loading.jsx9
-rw-r--r--src/app/anime/[id]/page.jsx50
-rw-r--r--src/app/anime/page.jsx6
-rw-r--r--src/app/anime/recent/page.jsx45
-rw-r--r--src/app/anime/recent/recent.css66
-rw-r--r--src/app/anime/search/components/fetchInfo.js14
-rw-r--r--src/app/anime/search/components/fetchedInfo.js44
-rw-r--r--src/app/anime/search/page.jsx67
-rw-r--r--src/app/anime/search/search.css80
-rw-r--r--src/app/anime/top-airing/page.jsx45
-rw-r--r--src/app/anime/top-airing/trending.css0
-rw-r--r--src/app/anime/video/loading.css346
-rw-r--r--src/app/anime/video/loading.jsx9
17 files changed, 1293 insertions, 3 deletions
diff --git a/src/app/anime/[id]/[animeId]/page.jsx b/src/app/anime/[id]/[animeId]/page.jsx
new file mode 100644
index 0000000..d59b0a0
--- /dev/null
+++ b/src/app/anime/[id]/[animeId]/page.jsx
@@ -0,0 +1,56 @@
+import { MediaPlayer, MediaProvider } from "@vidstack/react";
+import "@vidstack/react/player/styles/base.css";
+import "@vidstack/react/player/styles/plyr/theme.css";
+import {
+ PlyrLayout,
+ plyrLayoutIcons,
+} from "@vidstack/react/player/layouts/plyr";
+import "./video.css";
+import { redirect } from "next/navigation";
+
+export default async function Video({ params }) {
+ const id = params.animeId;
+
+ // Getting the episode number and the anime name. Kindly ignore!
+ const words = id.split("-");
+ const last_two = words.slice(-2).join(" ");
+ const remainingWords = words.slice(0, -2).join(" ");
+
+ const data = await getVideoLink(id);
+
+ if (data.message) {
+ redirect("/404");
+ }
+
+ const link = data.sources[4].url;
+
+ return (
+ <div>
+ <div className="video2">
+ <p>
+ {last_two} - {remainingWords}
+ </p>
+ <MediaPlayer
+ title={words}
+ src={link}
+ className="testPlayer"
+ playsInline
+ aspectRatio="16/9"
+ load="eager"
+ >
+ <MediaProvider />
+ <PlyrLayout icons={plyrLayoutIcons} />
+ </MediaPlayer>
+ </div>
+ </div>
+ );
+}
+
+async function getVideoLink(id) {
+ const res = await fetch(
+ "https://consumet-api-di2e.onrender.com/anime/gogoanime/watch/" + id,
+ { next: { revalidate: 3600 } } // Video links are revalidated after an hour
+ );
+ const data = res.json();
+ return data;
+}
diff --git a/src/app/anime/[id]/[animeId]/video.css b/src/app/anime/[id]/[animeId]/video.css
new file mode 100644
index 0000000..5ccb58f
--- /dev/null
+++ b/src/app/anime/[id]/[animeId]/video.css
@@ -0,0 +1,30 @@
+.video2 {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin: 0px auto;
+ width: 50%;
+}
+
+.testPlayer {
+ border-radius: 10px;
+}
+
+.video2 p {
+ color: white;
+ font-family: "Lato";
+ font-size: 20px;
+ text-align: center;
+}
+
+@media (prefers-color-scheme: light) {
+ .video2 p {
+ color: black;
+ }
+}
+
+@media screen and (max-width: 768px) {
+ .video2 {
+ width: 100%;
+ }
+} \ No newline at end of file
diff --git a/src/app/anime/[id]/info.css b/src/app/anime/[id]/info.css
new file mode 100644
index 0000000..2b070d0
--- /dev/null
+++ b/src/app/anime/[id]/info.css
@@ -0,0 +1,83 @@
+.dramaInfoContainer {
+ display: flex;
+ flex-direction: column;
+}
+
+.dramaInfo {
+ display: flex;
+ flex-direction: column;
+ width: 95%;
+ margin: 0px auto;
+}
+
+.titleContainer {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.titleContainer p {
+ color: var(--neon-green);
+ width: 60%;
+ font-family: "Kanit";
+ font-size: 24px;
+}
+
+.titleContainer img {
+ border-radius: 10px;
+}
+
+.animeDescription {
+ color: #ffffff81;
+ font-family: "Lato";
+ font-size: 16px;
+ max-height: 120px;
+ margin: 20px auto;
+ text-align: center;
+ overflow-y: auto;
+}
+
+.buttonContainer {
+ margin: 5px auto;
+ text-align: center;
+ max-height: 200px;
+ overflow-y: auto;
+}
+
+.dramaButton {
+ padding: 8px;
+ font-family: "Atkinson Hyperlegible";
+ font-size: 18px;
+ margin: 5px;
+ width: 50px;
+ border-radius: 5px;
+ border: none;
+ background-color: var(--light-green);
+ cursor: pointer;
+}
+
+.dramaButton:hover {
+ background-color: var(--soft-purple);
+}
+
+.infoPageContainer {
+ display: flex;
+ height: 100dvh;
+ justify-content: center;
+ align-items: center;
+}
+
+.infoPageContainer p {
+ color: white;
+}
+
+@media (prefers-color-scheme: light) {
+ .animeDescription {
+ color: black;
+ }
+
+ .infoPageContainer p {
+ color: black;
+ }
+
+} \ No newline at end of file
diff --git a/src/app/anime/[id]/loading.css b/src/app/anime/[id]/loading.css
new file mode 100644
index 0000000..aa3a519
--- /dev/null
+++ b/src/app/anime/[id]/loading.css
@@ -0,0 +1,346 @@
+.loadingContainer {
+ color: white;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 80dvh;
+}
+
+
+.text-flicker-in-glow {
+ -webkit-animation: text-flicker-in-glow 4s linear both;
+ animation: text-flicker-in-glow 4s linear both;
+ font-size: 36px;
+ font-family: "Kanit";
+}
+
+/* ----------------------------------------------
+ * Generated by Animista on 2024-3-21 9:58:16
+ * Licensed under FreeBSD License.
+ * See http://animista.net/license for more info.
+ * w: http://animista.net, t: @cssanimista
+ * ---------------------------------------------- */
+
+/**
+ * ----------------------------------------
+ * animation text-flicker-in-glow
+ * ----------------------------------------
+ */
+
+@-webkit-keyframes text-flicker-in-glow {
+ 0% {
+ opacity: 0;
+ }
+
+ 10% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 10.1% {
+ opacity: 1;
+ text-shadow: none;
+ }
+
+ 10.2% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 20% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 20.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.25);
+ }
+
+ 20.6% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 30% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 30.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 30.5% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 30.6% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 45% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 45.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 50% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 55% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 55.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 57% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 57.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35);
+ }
+
+ 60% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35);
+ }
+
+ 60.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 65% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 65.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 75% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 75.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 77% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 77.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.4), 0 0 110px rgba(255, 255, 255, 0.2), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 85% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.4), 0 0 110px rgba(255, 255, 255, 0.2), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 85.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 86% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 86.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.6), 0 0 60px rgba(255, 255, 255, 0.45), 0 0 110px rgba(255, 255, 255, 0.25), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 100% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.6), 0 0 60px rgba(255, 255, 255, 0.45), 0 0 110px rgba(255, 255, 255, 0.25), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+}
+
+@keyframes text-flicker-in-glow {
+ 0% {
+ opacity: 0;
+ }
+
+ 10% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 10.1% {
+ opacity: 1;
+ text-shadow: none;
+ }
+
+ 10.2% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 20% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 20.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.25);
+ }
+
+ 20.6% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 30% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 30.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 30.5% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 30.6% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 45% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 45.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 50% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 55% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 55.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 57% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 57.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35);
+ }
+
+ 60% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35);
+ }
+
+ 60.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 65% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 65.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 75% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 75.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 77% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 77.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.4), 0 0 110px rgba(255, 255, 255, 0.2), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 85% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.4), 0 0 110px rgba(255, 255, 255, 0.2), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 85.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 86% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 86.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.6), 0 0 60px rgba(255, 255, 255, 0.45), 0 0 110px rgba(255, 255, 255, 0.25), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 100% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.6), 0 0 60px rgba(255, 255, 255, 0.45), 0 0 110px rgba(255, 255, 255, 0.25), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+}
+
+@media (prefers-color-scheme: light) {
+ .loadingContainer {
+ color: black;
+ }
+} \ No newline at end of file
diff --git a/src/app/anime/[id]/loading.jsx b/src/app/anime/[id]/loading.jsx
new file mode 100644
index 0000000..dfa397c
--- /dev/null
+++ b/src/app/anime/[id]/loading.jsx
@@ -0,0 +1,9 @@
+import "./loading.css";
+
+export default function Loading() {
+ return (
+ <div className="loadingContainer">
+ <p className="text-flicker-in-glow">Loading</p>
+ </div>
+ );
+}
diff --git a/src/app/anime/[id]/page.jsx b/src/app/anime/[id]/page.jsx
new file mode 100644
index 0000000..3e2b1f0
--- /dev/null
+++ b/src/app/anime/[id]/page.jsx
@@ -0,0 +1,50 @@
+import "./info.css";
+import Image from "next/image";
+import Link from "next/link";
+
+export default async function AnimeInfo({ params }) {
+ let animeID = params.id;
+
+ const info = await getAnimeInfo(animeID);
+
+ return (
+ <div className="dramaInfoContainer">
+ <div className="dramaInfo">
+ {info && (
+ <div>
+ <div className="titleContainer">
+ <p>{info.title}</p>
+ <Image
+ src={info.image}
+ width={140}
+ height={190}
+ alt="Drama"
+ />
+ </div>
+ <p className="animeDescription">{info.description}</p>
+ </div>
+ )}
+
+ <div className="buttonContainer">
+ {info &&
+ info.episodes.map((item, index) => (
+ <Link href={`/anime/watch/${item.id}`} key={index}>
+ <button className="dramaButton">
+ {item.number}
+ </button>
+ </Link>
+ ))}
+ </div>
+ </div>
+ </div>
+ );
+}
+
+async function getAnimeInfo(anime_id) {
+ const res = await fetch(
+ "https://anime-sensei-api.vercel.app/anime/gogoanime/info/" + anime_id,
+ { next: { revalidate: 1800 } }
+ );
+ const data = res.json();
+ return data;
+}
diff --git a/src/app/anime/page.jsx b/src/app/anime/page.jsx
index 759619d..625dd83 100644
--- a/src/app/anime/page.jsx
+++ b/src/app/anime/page.jsx
@@ -1,7 +1,7 @@
import "./anime.css";
-import Trending from "../top-airing/page";
-import Releases from "../recent/page";
-import Input from "../search/page";
+import Trending from "./top-airing/page";
+import Releases from "./recent/page";
+import Input from "./search/page";
export default async function Anime() {
return (
diff --git a/src/app/anime/recent/page.jsx b/src/app/anime/recent/page.jsx
new file mode 100644
index 0000000..779f0d4
--- /dev/null
+++ b/src/app/anime/recent/page.jsx
@@ -0,0 +1,45 @@
+import "./recent.css";
+import Image from "next/image";
+import Link from "next/link";
+
+export default async function Releases() {
+ const data = await test();
+
+ return (
+ <div className="trendingContainer">
+ <p className="trendingText">Recent Releases</p>
+
+ <div className="trending">
+ {data &&
+ data.results.map((item, index) => (
+ <Link
+ key={index}
+ href={`/anime/${item.id}`}
+ style={{ textDecoration: "none" }}
+ >
+ <div className="trendingEntries">
+ <Image
+ src={item.image}
+ className="{trendingImage}"
+ width={160}
+ height={220}
+ alt="Drama"
+ priority
+ />
+ <p>{item.title}</p>
+ </div>
+ </Link>
+ ))}
+ </div>
+ </div>
+ );
+}
+
+async function test() {
+ const res = await fetch(
+ "https://consumet-api-di2e.onrender.com/anime/gogoanime/recent-episodes",
+ { cache: "force-cache" }
+ );
+ const data = res.json();
+ return data;
+}
diff --git a/src/app/anime/recent/recent.css b/src/app/anime/recent/recent.css
new file mode 100644
index 0000000..7d17143
--- /dev/null
+++ b/src/app/anime/recent/recent.css
@@ -0,0 +1,66 @@
+.trendingContainer {
+ display: flex;
+ flex-direction: column;
+}
+
+.trendingText {
+ color: #FEFFAC;
+ font-family: "Open Sans";
+ font-size: 26px;
+ margin: 10px;
+}
+
+.trending {
+ width: 98%;
+ display: flex;
+ flex-direction: row;
+ overflow-x: auto;
+ margin: 0px auto;
+}
+
+/* Customize scrollbar here */
+.trending::-webkit-scrollbar {
+ height: 5px;
+}
+
+.trendingEntries {
+ margin: 10px 10px 5px 5px;
+ text-align: center;
+ cursor: pointer;
+ transition: transform 0.2s ease;
+
+}
+
+.trendingEntries:hover {
+ transform: scale(1.03);
+}
+
+.trendingEntries img {
+ border-radius: 10px;
+ width: 150px;
+ height: 210px;
+}
+
+.trendingEntries p {
+ color: white;
+ max-height: 60px;
+ max-width: 150px;
+ overflow-y: auto;
+ font-family: "Lato";
+ margin: 10px auto;
+ font-size: 16px;
+}
+
+.trendingEntries p::-webkit-scrollbar {
+ width: 5px;
+}
+
+@media (prefers-color-scheme: light) {
+ .trendingText {
+ color: black;
+ }
+
+ .trendingEntries p {
+ color: black;
+ }
+} \ No newline at end of file
diff --git a/src/app/anime/search/components/fetchInfo.js b/src/app/anime/search/components/fetchInfo.js
new file mode 100644
index 0000000..07b203d
--- /dev/null
+++ b/src/app/anime/search/components/fetchInfo.js
@@ -0,0 +1,14 @@
+"use server";
+
+export default async function Results(id) {
+ return await testFunction(id);
+}
+
+async function testFunction(title) {
+ const res = await fetch(
+ "https://consumet-api-di2e.onrender.com/anime/gogoanime/" + title,
+ { cache: "force-cache" }
+ );
+ const data = await res.json();
+ return data;
+}
diff --git a/src/app/anime/search/components/fetchedInfo.js b/src/app/anime/search/components/fetchedInfo.js
new file mode 100644
index 0000000..17c9673
--- /dev/null
+++ b/src/app/anime/search/components/fetchedInfo.js
@@ -0,0 +1,44 @@
+import "../search.css";
+import Link from "next/link";
+import Image from "next/image";
+
+export default async function fetchedInfo(data) {
+ return (
+ <div className="animeEntry">
+ {data ? (
+ data.results && data.results.length > 0 ? (
+ data.results.map((item, index) => (
+ <Link
+ key={index}
+ href={`/anime/${item.id}`}
+ style={{ textDecoration: "none" }}
+ >
+ <div className="anime">
+ <p>{item.title}</p>
+ <Image
+ src={item.image}
+ className="animeImage"
+ width={120}
+ height={160}
+ alt="Drama Poster"
+ />
+ </div>
+ </Link>
+ ))
+ ) : (
+ <div style={{ margin: "0px auto" }}>
+ <p
+ style={{
+ color: "white",
+ fontFamily: "Kanit",
+ fontSize: 18,
+ }}
+ >
+ No results found
+ </p>
+ </div>
+ )
+ ) : null}
+ </div>
+ );
+}
diff --git a/src/app/anime/search/page.jsx b/src/app/anime/search/page.jsx
new file mode 100644
index 0000000..75f09bd
--- /dev/null
+++ b/src/app/anime/search/page.jsx
@@ -0,0 +1,67 @@
+"use client";
+
+import "./search.css";
+import { FaSearch } from "react-icons/fa"; // Import the search icon from react-icons library
+import { useState } from "react";
+import Results from "./components/fetchInfo";
+import fetchedInfo from "./components/fetchedInfo";
+
+export default function Input() {
+ const [searchedAnime, setSearchedAnime] = useState(null);
+ const [loading, setLoading] = useState(null);
+ const [info, setInfo] = useState(null);
+
+ const handleKeyPress = async (event) => {
+ if (
+ (event.code === "Enter" ||
+ event.key === "Enter" ||
+ event.code === 13) &&
+ searchedAnime !== ""
+ ) {
+ setLoading(true);
+ setInfo(await fetchedInfo(await Results(searchedAnime)));
+ setLoading(false);
+ } else if (
+ (event.code === "Enter" ||
+ event.key === "Enter" ||
+ event.code === 13) &&
+ searchedAnime === ""
+ ) {
+ alert("Input cannot be empty");
+ }
+ };
+
+ return (
+ <div>
+ <div className="inputContainer">
+ <div className="searchContainer">
+ <FaSearch className="searchIcon" />
+ <input
+ onChange={(event) => {
+ if (event.target.value.trim() !== "") {
+ setSearchedAnime(event.target.value);
+ }
+ }}
+ onKeyDown={(event) => handleKeyPress(event)}
+ placeholder="Enter anime title"
+ ></input>
+ </div>
+ </div>
+
+ {loading && (
+ <p
+ style={{
+ textAlign: "center",
+ fontFamily: "Kanit",
+ fontSize: 18,
+ color: "white",
+ }}
+ >
+ Please wait while we crunch all the data for you
+ </p>
+ )}
+
+ {info}
+ </div>
+ );
+}
diff --git a/src/app/anime/search/search.css b/src/app/anime/search/search.css
new file mode 100644
index 0000000..8afb508
--- /dev/null
+++ b/src/app/anime/search/search.css
@@ -0,0 +1,80 @@
+.inputContainer {
+ display: flex;
+ margin: 30px auto;
+}
+
+.searchContainer input {
+ border: none;
+ border-radius: 5px;
+ color: white;
+ outline: none;
+ background: none;
+ width: 100%;
+ font-family: "Lato";
+ font-size: 16px;
+}
+
+.searchContainer {
+ display: flex;
+ align-items: center;
+ margin: 0px auto;
+ background-color: #2c2c2c;
+ padding: 8px;
+ border-radius: 5px;
+ width: 20%;
+}
+
+.searchIcon {
+ color: white;
+ margin-right: 5px;
+}
+
+.animeEntry {
+ display: flex;
+ overflow-x: auto;
+}
+
+.animeEntry::-webkit-scrollbar {
+ height: 7px;
+}
+
+.animeEntry::-webkit-scrollbar-track {
+ background-color: #636363;
+ border-radius: 5px;
+}
+
+.animeEntry::-webkit-scrollbar-thumb {
+ background-color: rgba(196, 196, 196, 0.692);
+ border-radius: 5px;
+
+}
+
+.anime {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 10px;
+ border-style: dotted;
+ border-color: #636363;
+ margin: 10px;
+ border-radius: 10px;
+ border-width: 4px;
+}
+
+.anime p {
+ color: white;
+ width: 25dvh;
+ font-family: "Lato";
+ font-size: 18px;
+}
+
+.animeImage {
+ border-radius: 10px;
+ margin-left: 20px;
+}
+
+@media screen and (max-width: 768px) {
+ .searchContainer {
+ width: 70%;
+ }
+} \ No newline at end of file
diff --git a/src/app/anime/top-airing/page.jsx b/src/app/anime/top-airing/page.jsx
new file mode 100644
index 0000000..5536870
--- /dev/null
+++ b/src/app/anime/top-airing/page.jsx
@@ -0,0 +1,45 @@
+import "./trending.css";
+import Image from "next/image";
+import Link from "next/link";
+
+export default async function Trending() {
+ const data = await test();
+
+ return (
+ <div className="trendingContainer">
+ <p className="trendingText">Trending</p>
+
+ <div className="trending">
+ {data &&
+ data.results.map((item, index) => (
+ <Link
+ key={index}
+ href={`/anime/${item.id}`}
+ style={{ textDecoration: "none" }}
+ >
+ <div className="trendingEntries">
+ <Image
+ src={item.image}
+ className="{trendingImage}"
+ width={160}
+ height={220}
+ alt="Drama"
+ priority
+ />
+ <p>{item.title}</p>
+ </div>
+ </Link>
+ ))}
+ </div>
+ </div>
+ );
+}
+
+async function test() {
+ const res = await fetch(
+ "https://consumet-api-di2e.onrender.com/anime/gogoanime/top-airing",
+ { cache: "force-cache" }
+ );
+ const data = res.json();
+ return data;
+}
diff --git a/src/app/anime/top-airing/trending.css b/src/app/anime/top-airing/trending.css
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/app/anime/top-airing/trending.css
diff --git a/src/app/anime/video/loading.css b/src/app/anime/video/loading.css
new file mode 100644
index 0000000..aa3a519
--- /dev/null
+++ b/src/app/anime/video/loading.css
@@ -0,0 +1,346 @@
+.loadingContainer {
+ color: white;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 80dvh;
+}
+
+
+.text-flicker-in-glow {
+ -webkit-animation: text-flicker-in-glow 4s linear both;
+ animation: text-flicker-in-glow 4s linear both;
+ font-size: 36px;
+ font-family: "Kanit";
+}
+
+/* ----------------------------------------------
+ * Generated by Animista on 2024-3-21 9:58:16
+ * Licensed under FreeBSD License.
+ * See http://animista.net/license for more info.
+ * w: http://animista.net, t: @cssanimista
+ * ---------------------------------------------- */
+
+/**
+ * ----------------------------------------
+ * animation text-flicker-in-glow
+ * ----------------------------------------
+ */
+
+@-webkit-keyframes text-flicker-in-glow {
+ 0% {
+ opacity: 0;
+ }
+
+ 10% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 10.1% {
+ opacity: 1;
+ text-shadow: none;
+ }
+
+ 10.2% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 20% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 20.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.25);
+ }
+
+ 20.6% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 30% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 30.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 30.5% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 30.6% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 45% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 45.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 50% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 55% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 55.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 57% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 57.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35);
+ }
+
+ 60% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35);
+ }
+
+ 60.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 65% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 65.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 75% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 75.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 77% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 77.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.4), 0 0 110px rgba(255, 255, 255, 0.2), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 85% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.4), 0 0 110px rgba(255, 255, 255, 0.2), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 85.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 86% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 86.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.6), 0 0 60px rgba(255, 255, 255, 0.45), 0 0 110px rgba(255, 255, 255, 0.25), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 100% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.6), 0 0 60px rgba(255, 255, 255, 0.45), 0 0 110px rgba(255, 255, 255, 0.25), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+}
+
+@keyframes text-flicker-in-glow {
+ 0% {
+ opacity: 0;
+ }
+
+ 10% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 10.1% {
+ opacity: 1;
+ text-shadow: none;
+ }
+
+ 10.2% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 20% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 20.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.25);
+ }
+
+ 20.6% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 30% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 30.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 30.5% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 30.6% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 45% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 45.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 50% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 55% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 55.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 57% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 57.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35);
+ }
+
+ 60% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35);
+ }
+
+ 60.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 65% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 65.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 75% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 75.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 77% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 77.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.4), 0 0 110px rgba(255, 255, 255, 0.2), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 85% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.4), 0 0 110px rgba(255, 255, 255, 0.2), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 85.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 86% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 86.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.6), 0 0 60px rgba(255, 255, 255, 0.45), 0 0 110px rgba(255, 255, 255, 0.25), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 100% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.6), 0 0 60px rgba(255, 255, 255, 0.45), 0 0 110px rgba(255, 255, 255, 0.25), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+}
+
+@media (prefers-color-scheme: light) {
+ .loadingContainer {
+ color: black;
+ }
+} \ No newline at end of file
diff --git a/src/app/anime/video/loading.jsx b/src/app/anime/video/loading.jsx
new file mode 100644
index 0000000..dfa397c
--- /dev/null
+++ b/src/app/anime/video/loading.jsx
@@ -0,0 +1,9 @@
+import "./loading.css";
+
+export default function Loading() {
+ return (
+ <div className="loadingContainer">
+ <p className="text-flicker-in-glow">Loading</p>
+ </div>
+ );
+}