diff options
| author | zephex <[email protected]> | 2024-04-20 13:34:53 +0530 |
|---|---|---|
| committer | zephex <[email protected]> | 2024-04-20 13:34:53 +0530 |
| commit | d6780cf3dad729c69a102ba2940188cf1e6bcbf4 (patch) | |
| tree | d10a2aefef6664c42439f165c73722c514b032bc /src | |
| parent | feature added: tracker for mangas (diff) | |
| download | dramalama-d6780cf3dad729c69a102ba2940188cf1e6bcbf4.tar.xz dramalama-d6780cf3dad729c69a102ba2940188cf1e6bcbf4.zip | |
idk whats happening
Diffstat (limited to 'src')
58 files changed, 3044 insertions, 3044 deletions
diff --git a/src/app/anime/[id]/buttons.jsx b/src/app/anime/[id]/buttons.jsx index dd49d6e..660569e 100644 --- a/src/app/anime/[id]/buttons.jsx +++ b/src/app/anime/[id]/buttons.jsx @@ -1,112 +1,112 @@ -"use client"; - -import styles from "./info.module.css"; -import { useState } from "react"; -import { fetch_video_link } from "../videoLinkfetcher"; -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 { storeLocal } from "../history/storeData"; - -export default function Button({ data2: info }) { - const currentDate = new Date(); - const [videoLink, setVideoLink] = useState(null); - - async function video(id) { - const link = await fetch_video_link(id); - if (link === undefined) { - alert("Sorry, but not links were found"); - } else { - setVideoLink(link); - } - } - - function store_to_local(name, image, episode, id) { - let newData = { - name: name, - image: image, - episode: episode, - id: id, - type: "anime", - date: `${currentDate.getDate()}-${String( - currentDate.getMonth() + 1 - ).padStart(2, "0")}`, - time: `${currentDate.getHours()}:${String( - currentDate.getMinutes() - ).padStart(2, "0")}`, - }; - storeLocal(newData); - } - - return ( - <main> - <h2 className={styles.buttonHeader}>Episodes: </h2> - <div className={styles.buttonContainer}> - {info && - info.episodes && - info.episodes.map((item, index) => ( - <button - className={styles.dramaButton} - key={index} - onClick={(event) => { - event.target.style.backgroundColor = - "var(--soft-purple)"; - video(item.id); - store_to_local( - info.title, - info.image, - item.number, - info.id - ); - }} - > - {item.number} - </button> - ))} - </div> - - {videoLink && ( - <div - className={styles.videoPopUp} - id="popup" - onKeyDown={(event) => { - if (event.code === "Escape") { - setVideoLink(""); - } - }} - > - <div className={styles.video}> - <MediaPlayer - title="dramaPlayer" - src={videoLink} - aspectRatio="16/9" - load="eager" - className={styles.VideoPlayer} - playsInline - id="videoPlayer" - volume={0.2} - onQualityChange={(event) => - console.log("changed qualities", event) - } - > - <MediaProvider /> - <PlyrLayout icons={plyrLayoutIcons} /> - </MediaPlayer> - <button - className={styles.closeButton} - onClick={() => { - setVideoLink(""); - }} - > - Close - </button> - </div> - </div> - )} - </main> - ); -} +"use client";
+
+import styles from "./info.module.css";
+import { useState } from "react";
+import { fetch_video_link } from "../videoLinkfetcher";
+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 { storeLocal } from "../history/storeData";
+
+export default function Button({ data2: info }) {
+ const currentDate = new Date();
+ const [videoLink, setVideoLink] = useState(null);
+
+ async function video(id) {
+ const link = await fetch_video_link(id);
+ if (link === undefined) {
+ alert("Sorry, but not links were found");
+ } else {
+ setVideoLink(link);
+ }
+ }
+
+ function store_to_local(name, image, episode, id) {
+ let newData = {
+ name: name,
+ image: image,
+ episode: episode,
+ id: id,
+ type: "anime",
+ date: `${currentDate.getDate()}-${String(
+ currentDate.getMonth() + 1
+ ).padStart(2, "0")}`,
+ time: `${currentDate.getHours()}:${String(
+ currentDate.getMinutes()
+ ).padStart(2, "0")}`,
+ };
+ storeLocal(newData);
+ }
+
+ return (
+ <main>
+ <h2 className={styles.buttonHeader}>Episodes: </h2>
+ <div className={styles.buttonContainer}>
+ {info &&
+ info.episodes &&
+ info.episodes.map((item, index) => (
+ <button
+ className={styles.dramaButton}
+ key={index}
+ onClick={(event) => {
+ event.target.style.backgroundColor =
+ "var(--soft-purple)";
+ video(item.id);
+ store_to_local(
+ info.title,
+ info.image,
+ item.number,
+ info.id
+ );
+ }}
+ >
+ {item.number}
+ </button>
+ ))}
+ </div>
+
+ {videoLink && (
+ <div
+ className={styles.videoPopUp}
+ id="popup"
+ onKeyDown={(event) => {
+ if (event.code === "Escape") {
+ setVideoLink("");
+ }
+ }}
+ >
+ <div className={styles.video}>
+ <MediaPlayer
+ title="dramaPlayer"
+ src={videoLink}
+ aspectRatio="16/9"
+ load="eager"
+ className={styles.VideoPlayer}
+ playsInline
+ id="videoPlayer"
+ volume={0.2}
+ onQualityChange={(event) =>
+ console.log("changed qualities", event)
+ }
+ >
+ <MediaProvider />
+ <PlyrLayout icons={plyrLayoutIcons} />
+ </MediaPlayer>
+ <button
+ className={styles.closeButton}
+ onClick={() => {
+ setVideoLink("");
+ }}
+ >
+ Close
+ </button>
+ </div>
+ </div>
+ )}
+ </main>
+ );
+}
diff --git a/src/app/anime/[id]/info.module.css b/src/app/anime/[id]/info.module.css index c65e796..3b6e650 100644 --- a/src/app/anime/[id]/info.module.css +++ b/src/app/anime/[id]/info.module.css @@ -1,169 +1,169 @@ -.dramaInfoContainer { - display: flex; - flex-direction: column; -} - -.dramaInfo { - display: flex; - flex-direction: column; - width: 98%; - margin: 80px auto; -} - -.titleContainer { - display: flex; - justify-content: space-between; - align-items: center; -} - -.titleContainer p { - color: var(--neon-green); - width: 60%; - font-family: "Poppins"; - font-weight: 500; - font-size: 34px; -} - -.titleContainer img { - width: auto; - height: auto; - border-radius: 10px; -} - -.animeDescription h2 { - color: #ffffff81; - margin: 20px 0px -10px 0px; -} - -.animeDescription p { - font-family: "Atkinson Hyperlegible"; - color: rgba(255, 255, 255, 0.637); -} - -.buttonContainer { - margin: 0px; - height: 200px; - overflow-y: auto; - border-radius: 10px; -} - -.buttonHeader { - margin: 0px 10px 10px 0px; - color: #ffffff81 -} - -.buttonContainer button { - transition: transform 200ms ease-in-out; - -} - -.buttonContainer button:focus { - opacity: 0.7; - transition: transform 200ms ease-in; - background-color: var(--soft-purple); - transform: scale(0.9); -} - -.buttonContainer::-webkit-scrollbar-thumb { - background-color: var(--soft-purple); - border-radius: 5px; -} - -.dramaButton { - padding: 10px; - font-family: "Quicksand"; - font-size: 14px; - margin: 5px 5px 5px 5px; - width: 55px; - border-radius: 5px; - text-align: center; - border: none; - outline: none; - color: white; - background-color: #3d3d3d; - transition: background-color 200ms ease-in-out; - cursor: pointer; -} - -.dramaButton:hover { - background-color: #1f1f1f; - transition: background-color 200ms ease-in -} - -.infoPageContainer p { - color: white; -} - -.animeDetails { - color: white; -} - -.genreEntries { - margin: 3px; - padding: 4px; - border-radius: 5px; - color: var(--neon-green); - background-color: #303030; - cursor: pointer; - font-family: "Atkinson Hyperlegible"; -} - -.animeType span { - color: var(--light-green); -} - -.animeRelease span { - color: var(--soft-purple) -} - -.videoPopUp { - height: 100dvh; - width: 100dvw; - background-color: #1f1f1fd3; - position: fixed; - bottom: 0; - left: 0; - right: 0; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - z-index: 1; - overflow-y: auto; -} - - -.closeButton { - font-family: "Poppins", serif; - font-size: 16px; - background-color: var(--pastel-red); - padding: 0.5rem 1.5rem; - border: 0; - outline: 0; - border-radius: 0.5rem; - cursor: pointer; - margin: 5px; -} - -.video { - width: 60vw; -} - -.VideoPlayer { - width: 100%; -} - -@media screen and (max-width: 768px) { - - .titleContainer p { - font-size: 28px; - } - - .animeDetails { - font-size: 14px; - } - - .video { - width: 100%; - } +.dramaInfoContainer {
+ display: flex;
+ flex-direction: column;
+}
+
+.dramaInfo {
+ display: flex;
+ flex-direction: column;
+ width: 98%;
+ margin: 80px auto;
+}
+
+.titleContainer {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.titleContainer p {
+ color: var(--neon-green);
+ width: 60%;
+ font-family: "Poppins";
+ font-weight: 500;
+ font-size: 34px;
+}
+
+.titleContainer img {
+ width: auto;
+ height: auto;
+ border-radius: 10px;
+}
+
+.animeDescription h2 {
+ color: #ffffff81;
+ margin: 20px 0px -10px 0px;
+}
+
+.animeDescription p {
+ font-family: "Atkinson Hyperlegible";
+ color: rgba(255, 255, 255, 0.637);
+}
+
+.buttonContainer {
+ margin: 0px;
+ height: 200px;
+ overflow-y: auto;
+ border-radius: 10px;
+}
+
+.buttonHeader {
+ margin: 0px 10px 10px 0px;
+ color: #ffffff81
+}
+
+.buttonContainer button {
+ transition: transform 200ms ease-in-out;
+
+}
+
+.buttonContainer button:focus {
+ opacity: 0.7;
+ transition: transform 200ms ease-in;
+ background-color: var(--soft-purple);
+ transform: scale(0.9);
+}
+
+.buttonContainer::-webkit-scrollbar-thumb {
+ background-color: var(--soft-purple);
+ border-radius: 5px;
+}
+
+.dramaButton {
+ padding: 10px;
+ font-family: "Quicksand";
+ font-size: 14px;
+ margin: 5px 5px 5px 5px;
+ width: 55px;
+ border-radius: 5px;
+ text-align: center;
+ border: none;
+ outline: none;
+ color: white;
+ background-color: #3d3d3d;
+ transition: background-color 200ms ease-in-out;
+ cursor: pointer;
+}
+
+.dramaButton:hover {
+ background-color: #1f1f1f;
+ transition: background-color 200ms ease-in
+}
+
+.infoPageContainer p {
+ color: white;
+}
+
+.animeDetails {
+ color: white;
+}
+
+.genreEntries {
+ margin: 3px;
+ padding: 4px;
+ border-radius: 5px;
+ color: var(--neon-green);
+ background-color: #303030;
+ cursor: pointer;
+ font-family: "Atkinson Hyperlegible";
+}
+
+.animeType span {
+ color: var(--light-green);
+}
+
+.animeRelease span {
+ color: var(--soft-purple)
+}
+
+.videoPopUp {
+ height: 100dvh;
+ width: 100dvw;
+ background-color: #1f1f1fd3;
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ z-index: 1;
+ overflow-y: auto;
+}
+
+
+.closeButton {
+ font-family: "Poppins", serif;
+ font-size: 16px;
+ background-color: var(--pastel-red);
+ padding: 0.5rem 1.5rem;
+ border: 0;
+ outline: 0;
+ border-radius: 0.5rem;
+ cursor: pointer;
+ margin: 5px;
+}
+
+.video {
+ width: 60vw;
+}
+
+.VideoPlayer {
+ width: 100%;
+}
+
+@media screen and (max-width: 768px) {
+
+ .titleContainer p {
+ font-size: 28px;
+ }
+
+ .animeDetails {
+ font-size: 14px;
+ }
+
+ .video {
+ width: 100%;
+ }
}
\ No newline at end of file diff --git a/src/app/anime/[id]/loading.jsx b/src/app/anime/[id]/loading.jsx index 24e8c83..12876eb 100644 --- a/src/app/anime/[id]/loading.jsx +++ b/src/app/anime/[id]/loading.jsx @@ -1,9 +1,9 @@ -import styles from "./loading.module.css"; - -export default async function Loading() { - return ( - <div className={styles.Main}> - <div className={styles.LoadingContainer}></div> - </div> - ); -} +import styles from "./loading.module.css";
+
+export default async function Loading() {
+ return (
+ <div className={styles.Main}>
+ <div className={styles.LoadingContainer}></div>
+ </div>
+ );
+}
diff --git a/src/app/anime/[id]/loading.module.css b/src/app/anime/[id]/loading.module.css index 14dfcf3..2bcedaa 100644 --- a/src/app/anime/[id]/loading.module.css +++ b/src/app/anime/[id]/loading.module.css @@ -1,22 +1,22 @@ -.Main { - height: 100vh; - width: 100vw; - display: flex; - justify-content: center; - align-items: center; -} - -.LoadingContainer { - width: 50px; - height: 50px; - border-radius: 50%; - border: 8px solid; - border-color: #F4F4F4 #0000; - animation: s1 1s infinite; -} - -@keyframes s1 { - to { - transform: rotate(.5turn) - } +.Main {
+ height: 100vh;
+ width: 100vw;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.LoadingContainer {
+ width: 50px;
+ height: 50px;
+ border-radius: 50%;
+ border: 8px solid;
+ border-color: #F4F4F4 #0000;
+ animation: s1 1s infinite;
+}
+
+@keyframes s1 {
+ to {
+ transform: rotate(.5turn)
+ }
}
\ No newline at end of file diff --git a/src/app/anime/[id]/page.jsx b/src/app/anime/[id]/page.jsx index ed8b1de..59ebe6a 100644 --- a/src/app/anime/[id]/page.jsx +++ b/src/app/anime/[id]/page.jsx @@ -1,67 +1,67 @@ -import styles from "./info.module.css"; -import Image from "next/image"; -import Button from "./buttons"; -import { preFetchAnimeLinks } from "../videoLinkfetcher"; - -export default async function AnimeInfo({ params }) { - let animeID = params.id; - - const info = await getAnimeInfo(animeID); - - preFetchAnimeLinks(info); - - return ( - <div className={styles.dramaInfoContainer}> - <div className={styles.dramaInfo}> - {info && ( - <div> - <div className={styles.titleContainer}> - <p>{info.title}</p> - <Image - src={info.image} - width={175} - height={256} - alt="Drama" - priority - /> - </div> - <div className={styles.animeDescription}> - <h2>Description</h2> - <p>{info.description}</p> - </div> - </div> - )} - - <div className={styles.animeDetails}> - <span className={styles.genre}>Genres: </span> - {info.genres && - info.genres.map((item, index) => ( - <span className={styles.genreEntries} key={index}> - {item} - </span> - ))} - <p className={styles.animeType}> - Type: <span>{info && info.type}</span> - </p> - <p className={styles.animeRelease}> - Release year: - <span> - {info && info.releaseDate}, {info && info.status} - </span> - </p> - </div> - - <Button data2={info} /> - </div> - </div> - ); -} - -async function getAnimeInfo(anime_id) { - const res = await fetch( - "https://anime-sensei-api.vercel.app/anime/gogoanime/info/" + anime_id, - { next: { revalidate: 7200 } } - ); - const data = await res.json(); - return data; -} +import styles from "./info.module.css";
+import Image from "next/image";
+import Button from "./buttons";
+import { preFetchAnimeLinks } from "../videoLinkfetcher";
+
+export default async function AnimeInfo({ params }) {
+ let animeID = params.id;
+
+ const info = await getAnimeInfo(animeID);
+
+ preFetchAnimeLinks(info);
+
+ return (
+ <div className={styles.dramaInfoContainer}>
+ <div className={styles.dramaInfo}>
+ {info && (
+ <div>
+ <div className={styles.titleContainer}>
+ <p>{info.title}</p>
+ <Image
+ src={info.image}
+ width={175}
+ height={256}
+ alt="Drama"
+ priority
+ />
+ </div>
+ <div className={styles.animeDescription}>
+ <h2>Description</h2>
+ <p>{info.description}</p>
+ </div>
+ </div>
+ )}
+
+ <div className={styles.animeDetails}>
+ <span className={styles.genre}>Genres: </span>
+ {info.genres &&
+ info.genres.map((item, index) => (
+ <span className={styles.genreEntries} key={index}>
+ {item}
+ </span>
+ ))}
+ <p className={styles.animeType}>
+ Type: <span>{info && info.type}</span>
+ </p>
+ <p className={styles.animeRelease}>
+ Release year:
+ <span>
+ {info && info.releaseDate}, {info && info.status}
+ </span>
+ </p>
+ </div>
+
+ <Button data2={info} />
+ </div>
+ </div>
+ );
+}
+
+async function getAnimeInfo(anime_id) {
+ const res = await fetch(
+ "https://anime-sensei-api.vercel.app/anime/gogoanime/info/" + anime_id,
+ { next: { revalidate: 7200 } }
+ );
+ const data = await res.json();
+ return data;
+}
diff --git a/src/app/anime/anime.module.css b/src/app/anime/anime.module.css index 63f2993..f243298 100644 --- a/src/app/anime/anime.module.css +++ b/src/app/anime/anime.module.css @@ -1,4 +1,4 @@ -.main { - margin: 80px auto; - max-width: 98%; +.main {
+ margin: 80px auto;
+ max-width: 98%;
}
\ No newline at end of file diff --git a/src/app/anime/history/continueWatching/cw.module.css b/src/app/anime/history/continueWatching/cw.module.css index d8062ac..2b2c6b0 100644 --- a/src/app/anime/history/continueWatching/cw.module.css +++ b/src/app/anime/history/continueWatching/cw.module.css @@ -1,59 +1,59 @@ -.main { - width: 99%; - margin: 80px auto; -} - -.mainText { - color: var(--light-green); - font-family: "Poppins", serif; - font-size: 24px; -} - -.animeContainer { - font-family: "Poppins", serif; - font-size: 18px; - margin: 0px; -} - -.animeEntry { - display: flex; - align-items: center; - justify-content: space-between; - padding: 5px; - margin-bottom: 0.5rem; - border-radius: 1rem; - background-color: #1f1f1f; -} - -.animeEntry img { - width: auto; - height: auto; - max-height: 40dvh; - border-radius: 0.8rem; -} - -.titleContainer { - color: white; - margin-left: 0.2rem; -} - -.titleContainer h3 { - margin: 0px; -} - -.EpisodeCount { - color: var(--soft-purple); - margin: 0px; -} - -.date { - color: var(--neon-yellow); - margin: 0px; -} - -@media screen and (max-width: 768px) { - .animeContainer { - font-size: 14px; - - } +.main {
+ width: 99%;
+ margin: 80px auto;
+}
+
+.mainText {
+ color: var(--light-green);
+ font-family: "Poppins", serif;
+ font-size: 24px;
+}
+
+.animeContainer {
+ font-family: "Poppins", serif;
+ font-size: 18px;
+ margin: 0px;
+}
+
+.animeEntry {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 5px;
+ margin-bottom: 0.5rem;
+ border-radius: 1rem;
+ background-color: #1f1f1f;
+}
+
+.animeEntry img {
+ width: auto;
+ height: auto;
+ max-height: 40dvh;
+ border-radius: 0.8rem;
+}
+
+.titleContainer {
+ color: white;
+ margin-left: 0.2rem;
+}
+
+.titleContainer h3 {
+ margin: 0px;
+}
+
+.EpisodeCount {
+ color: var(--soft-purple);
+ margin: 0px;
+}
+
+.date {
+ color: var(--neon-yellow);
+ margin: 0px;
+}
+
+@media screen and (max-width: 768px) {
+ .animeContainer {
+ font-size: 14px;
+
+ }
}
\ No newline at end of file diff --git a/src/app/anime/history/continueWatching/page.jsx b/src/app/anime/history/continueWatching/page.jsx index cab834c..d9bc6d1 100644 --- a/src/app/anime/history/continueWatching/page.jsx +++ b/src/app/anime/history/continueWatching/page.jsx @@ -1,65 +1,65 @@ -"use client"; - -import React, { useState, useEffect } from "react"; -import Image from "next/image"; -import styles from "./cw.module.css"; -import Link from "next/link"; - -const ContinueWatching = () => { - const [localItems, setLocalItems] = useState(null); - - useEffect(() => { - const newData = get_local(); - setLocalItems(newData); - }, []); // Empty dependency array means this effect runs only once after the initial render - - function get_local() { - try { - const data = localStorage.getItem("data"); - return JSON.parse(data); - } catch (error) { - console.log("error", error); - return false; - } - } - - return ( - <main className={styles.main}> - <p className={styles.mainText}>Continue Watching</p> - {localItems && ( - <div className={styles.animeContainer}> - {localItems.watchHis && - localItems.watchHis.map((item, index) => ( - <Link - href={`/${item.type}/${item.id}`} - style={{ textDecoration: "none" }} - key={index} - > - <div className={styles.animeEntry}> - <div className={styles.titleContainer}> - <h3>{item.name}</h3> - <p className={styles.EpisodeCount}> - Episode watching: {item.episode} - </p> - <p className={styles.date}> - Last watched on: {item.date} at{" "} - {item.time} - </p> - </div> - <Image - src={item.image} - width={140} - height={210} - alt="Continue anime poster" - priority - /> - </div> - </Link> - ))} - </div> - )} - </main> - ); -}; - -export default ContinueWatching; +"use client";
+
+import React, { useState, useEffect } from "react";
+import Image from "next/image";
+import styles from "./cw.module.css";
+import Link from "next/link";
+
+const ContinueWatching = () => {
+ const [localItems, setLocalItems] = useState(null);
+
+ useEffect(() => {
+ const newData = get_local();
+ setLocalItems(newData);
+ }, []); // Empty dependency array means this effect runs only once after the initial render
+
+ function get_local() {
+ try {
+ const data = localStorage.getItem("data");
+ return JSON.parse(data);
+ } catch (error) {
+ console.log("error", error);
+ return false;
+ }
+ }
+
+ return (
+ <main className={styles.main}>
+ <p className={styles.mainText}>Continue Watching</p>
+ {localItems && (
+ <div className={styles.animeContainer}>
+ {localItems.watchHis &&
+ localItems.watchHis.map((item, index) => (
+ <Link
+ href={`/${item.type}/${item.id}`}
+ style={{ textDecoration: "none" }}
+ key={index}
+ >
+ <div className={styles.animeEntry}>
+ <div className={styles.titleContainer}>
+ <h3>{item.name}</h3>
+ <p className={styles.EpisodeCount}>
+ Episode watching: {item.episode}
+ </p>
+ <p className={styles.date}>
+ Last watched on: {item.date} at{" "}
+ {item.time}
+ </p>
+ </div>
+ <Image
+ src={item.image}
+ width={140}
+ height={210}
+ alt="Continue anime poster"
+ priority
+ />
+ </div>
+ </Link>
+ ))}
+ </div>
+ )}
+ </main>
+ );
+};
+
+export default ContinueWatching;
diff --git a/src/app/anime/history/storeData.js b/src/app/anime/history/storeData.js index ae5f9d4..b748d3b 100644 --- a/src/app/anime/history/storeData.js +++ b/src/app/anime/history/storeData.js @@ -1,26 +1,26 @@ -"use client"; - -export function storeLocal(watchData) { - const jsonData = localStorage.getItem("data"); - const dataObject = jsonData ? JSON.parse(jsonData) : {}; - - if (!dataObject.watchHis) { - dataObject.watchHis = []; - } - - let found = false; - dataObject.watchHis.forEach((element) => { - if (element.name === watchData.name) { - let episode = watchData.episode; - element.episode = episode; - found = true; - } - }); - - if (!found) { - dataObject.watchHis.push(watchData); - } - - let updatedData = JSON.stringify(dataObject); - localStorage.setItem("data", updatedData); -} +"use client";
+
+export function storeLocal(watchData) {
+ const jsonData = localStorage.getItem("data");
+ const dataObject = jsonData ? JSON.parse(jsonData) : {};
+
+ if (!dataObject.watchHis) {
+ dataObject.watchHis = [];
+ }
+
+ let found = false;
+ dataObject.watchHis.forEach((element) => {
+ if (element.name === watchData.name) {
+ let episode = watchData.episode;
+ element.episode = episode;
+ found = true;
+ }
+ });
+
+ if (!found) {
+ dataObject.watchHis.push(watchData);
+ }
+
+ let updatedData = JSON.stringify(dataObject);
+ localStorage.setItem("data", updatedData);
+}
diff --git a/src/app/anime/page.jsx b/src/app/anime/page.jsx index 7480ae2..33a3373 100644 --- a/src/app/anime/page.jsx +++ b/src/app/anime/page.jsx @@ -1,14 +1,14 @@ -import styles from "./anime.module.css"; -import Trending from "./top-airing/page"; -import Releases from "./recent/page"; -import Input from "./search/page"; - -export default async function Anime() { - return ( - <div className={styles.main}> - <Input /> - <Trending /> - <Releases /> - </div> - ); -} +import styles from "./anime.module.css";
+import Trending from "./top-airing/page";
+import Releases from "./recent/page";
+import Input from "./search/page";
+
+export default async function Anime() {
+ return (
+ <div className={styles.main}>
+ <Input />
+ <Trending />
+ <Releases />
+ </div>
+ );
+}
diff --git a/src/app/anime/recent/page.jsx b/src/app/anime/recent/page.jsx index 471dfed..38aaeb0 100644 --- a/src/app/anime/recent/page.jsx +++ b/src/app/anime/recent/page.jsx @@ -1,49 +1,49 @@ -import Image from "next/image"; -import Link from "next/link"; -import styles from "./recent.module.css"; -import { preFetchAnimeInfo } from "../videoLinkfetcher"; - -export default async function Releases() { - const data = await fetchRecentEpisodes(); - preFetchAnimeInfo(data); - - return ( - <div className={styles.RecentContainer}> - <div className={styles.RecentText}> - <p>Recent Releases</p> - </div> - - <div className={styles.Recent}> - {data && - data.results.map((item, index) => ( - <Link - key={index} - href={`/anime/${item.id}`} - style={{ textDecoration: "none", color: "white" }} - > - <div className={styles.RecentEntries}> - <Image - src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${item.image}`} - className={styles.RecentImage} - width={150} - height={230} - alt="Drama" - priority - /> - <p>{item.title}</p> - </div> - </Link> - ))} - </div> - </div> - ); -} - -async function fetchRecentEpisodes() { - const res = await fetch( - "https://consumet-jade.vercel.app/anime/gogoanime/recent-episodes", - { next: { revalidate: 86400 } } - ); - const data = res.json(); - return data; -} +import Image from "next/image";
+import Link from "next/link";
+import styles from "./recent.module.css";
+import { preFetchAnimeInfo } from "../videoLinkfetcher";
+
+export default async function Releases() {
+ const data = await fetchRecentEpisodes();
+ preFetchAnimeInfo(data);
+
+ return (
+ <div className={styles.RecentContainer}>
+ <div className={styles.RecentText}>
+ <p>Recent Releases</p>
+ </div>
+
+ <div className={styles.Recent}>
+ {data &&
+ data.results.map((item, index) => (
+ <Link
+ key={index}
+ href={`/anime/${item.id}`}
+ style={{ textDecoration: "none", color: "white" }}
+ >
+ <div className={styles.RecentEntries}>
+ <Image
+ src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${item.image}`}
+ className={styles.RecentImage}
+ width={150}
+ height={230}
+ alt="Drama"
+ priority
+ />
+ <p>{item.title}</p>
+ </div>
+ </Link>
+ ))}
+ </div>
+ </div>
+ );
+}
+
+async function fetchRecentEpisodes() {
+ const res = await fetch(
+ "https://consumet-jade.vercel.app/anime/gogoanime/recent-episodes",
+ { next: { revalidate: 86400 } }
+ );
+ const data = res.json();
+ return data;
+}
diff --git a/src/app/anime/recent/recent.module.css b/src/app/anime/recent/recent.module.css index 59b794d..ca88518 100644 --- a/src/app/anime/recent/recent.module.css +++ b/src/app/anime/recent/recent.module.css @@ -1,73 +1,73 @@ -.RecentText { - display: flex; - align-items: center; -} - -.RecentText p { - font-size: 28px; - margin: 5px; - color: var(--soft-purple); - font-family: "Poppins"; - font-weight: 500; -} - -.RecentText span { - margin-top: 6px; -} - -.Recent { - display: flex; - overflow-x: auto; -} - -.RecentContainer:hover .RecentEntries { - opacity: 0.4; -} - -.RecentContainer:hover:hover .RecentEntries:hover { - opacity: 1; - transform: scale(1.02); -} - -.Recent::-webkit-scrollbar { - height: 5px; - width: 0px; -} - -.Recent::-webkit-scrollbar-thumb { - background-color: #444444; - border-radius: 5px; -} - -.RecentEntries { - margin: 4px; - background-color: #1f1f1fbb; - padding: 0.5rem; - border-radius: 1rem; - transition: opacity 400ms ease, transform 400ms ease; - -} - -.RecentEntries p { - text-align: center; - margin: 5px auto; - width: 140px; - font-family: "Atkinson Hyperlegible"; - height: 80px; - overflow-y: auto; - transition: font-size 400ms ease; -} - -.RecentEntries p::-webkit-scrollbar { - width: 2px; -} - -.Recent p::-webkit-scrollbar-thumb { - background-color: #444444; - border-radius: 5px; -} - -.RecentImage { - border-radius: 1rem; - aspect-ratio: auto; +.RecentText {
+ display: flex;
+ align-items: center;
+}
+
+.RecentText p {
+ font-size: 28px;
+ margin: 5px;
+ color: var(--soft-purple);
+ font-family: "Poppins";
+ font-weight: 500;
+}
+
+.RecentText span {
+ margin-top: 6px;
+}
+
+.Recent {
+ display: flex;
+ overflow-x: auto;
+}
+
+.RecentContainer:hover .RecentEntries {
+ opacity: 0.4;
+}
+
+.RecentContainer:hover:hover .RecentEntries:hover {
+ opacity: 1;
+ transform: scale(1.02);
+}
+
+.Recent::-webkit-scrollbar {
+ height: 5px;
+ width: 0px;
+}
+
+.Recent::-webkit-scrollbar-thumb {
+ background-color: #444444;
+ border-radius: 5px;
+}
+
+.RecentEntries {
+ margin: 4px;
+ background-color: #1f1f1fbb;
+ padding: 0.5rem;
+ border-radius: 1rem;
+ transition: opacity 400ms ease, transform 400ms ease;
+
+}
+
+.RecentEntries p {
+ text-align: center;
+ margin: 5px auto;
+ width: 140px;
+ font-family: "Atkinson Hyperlegible";
+ height: 80px;
+ overflow-y: auto;
+ transition: font-size 400ms ease;
+}
+
+.RecentEntries p::-webkit-scrollbar {
+ width: 2px;
+}
+
+.Recent p::-webkit-scrollbar-thumb {
+ background-color: #444444;
+ border-radius: 5px;
+}
+
+.RecentImage {
+ border-radius: 1rem;
+ aspect-ratio: auto;
}
\ No newline at end of file diff --git a/src/app/anime/search/components/fetchInfo.js b/src/app/anime/search/components/fetchInfo.js index a458607..f14ea5e 100644 --- a/src/app/anime/search/components/fetchInfo.js +++ b/src/app/anime/search/components/fetchInfo.js @@ -1,14 +1,14 @@ -"use server"; - -export default async function Results(id) { - return await testFunction(id); -} - -async function testFunction(title) { - const res = await fetch( - "https://consumet-jade.vercel.app/anime/gogoanime/" + title, - { cache: "force-cache" } - ); - const data = await res.json(); - return data; -} +"use server";
+
+export default async function Results(id) {
+ return await testFunction(id);
+}
+
+async function testFunction(title) {
+ const res = await fetch(
+ "https://consumet-jade.vercel.app/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 index aa3ffb1..d88797b 100644 --- a/src/app/anime/search/components/fetchedInfo.js +++ b/src/app/anime/search/components/fetchedInfo.js @@ -1,46 +1,46 @@ -import styles from "../search.module.css"; -import Link from "next/link"; -import Image from "next/image"; -import { preFetchAnimeInfo } from "../../videoLinkfetcher"; - -export default async function fetchedInfo(data) { - preFetchAnimeInfo(data); - return ( - <div className={styles.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={styles.anime}> - <p>{item.title}</p> - <Image - src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${item.image}`} - className={styles.animeImage} - width={120} - height={180} - 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> - ); -} +import styles from "../search.module.css";
+import Link from "next/link";
+import Image from "next/image";
+import { preFetchAnimeInfo } from "../../videoLinkfetcher";
+
+export default async function fetchedInfo(data) {
+ preFetchAnimeInfo(data);
+ return (
+ <div className={styles.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={styles.anime}>
+ <p>{item.title}</p>
+ <Image
+ src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${item.image}`}
+ className={styles.animeImage}
+ width={120}
+ height={180}
+ 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 index 43b5cd7..7ec2d2d 100644 --- a/src/app/anime/search/page.jsx +++ b/src/app/anime/search/page.jsx @@ -1,67 +1,67 @@ -"use client"; - -import styles from "./search.module.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"; -import Link from "next/link"; - -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={styles.inputContainer}> - <div className={styles.searchContainer}> - <FaSearch className={styles.searchIcon} /> - <input - onChange={(event) => { - if (event.target.value.trim() !== "") { - setSearchedAnime(event.target.value); - } - }} - onKeyDown={(event) => handleKeyPress(event)} - placeholder="Enter anime title" - className={styles.SearchInput} - ></input> - </div> - <button> - <Link href={"/anime/history/continueWatching"}> - Watch History - </Link> - </button> - </div> - - {loading && ( - <p className={styles.waitWhileLoading}> - Please wait while we crunch all the data for you - </p> - )} - - {info} - </div> - ); -} +"use client";
+
+import styles from "./search.module.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";
+import Link from "next/link";
+
+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={styles.inputContainer}>
+ <div className={styles.searchContainer}>
+ <FaSearch className={styles.searchIcon} />
+ <input
+ onChange={(event) => {
+ if (event.target.value.trim() !== "") {
+ setSearchedAnime(event.target.value);
+ }
+ }}
+ onKeyDown={(event) => handleKeyPress(event)}
+ placeholder="Enter anime title"
+ className={styles.SearchInput}
+ ></input>
+ </div>
+ <button>
+ <Link href={"/anime/history/continueWatching"}>
+ Watch History
+ </Link>
+ </button>
+ </div>
+
+ {loading && (
+ <p className={styles.waitWhileLoading}>
+ Please wait while we crunch all the data for you
+ </p>
+ )}
+
+ {info}
+ </div>
+ );
+}
diff --git a/src/app/anime/search/search.module.css b/src/app/anime/search/search.module.css index e91133f..306daae 100644 --- a/src/app/anime/search/search.module.css +++ b/src/app/anime/search/search.module.css @@ -1,118 +1,118 @@ -.waitWhileLoading { - font-size: 18px; - font-family: "Kanit"; - text-align: center; - color: white; -} - -.inputContainer { - display: flex; - align-items: center; -} - -.inputContainer button { - margin: 5px; - background-color: #121212; - padding: 10px; - border-radius: 10px; - outline: none; - border: none; - color: white; - font-family: "Atkinson Hyperlegible"; -} - -.inputContainer button a { - text-decoration: none; - color: white; -} - -.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: 20px 0px 20px 0px; - background-color: #121212; - padding: 10px; - border-radius: 10px; - width: 30%; -} - -.searchIcon { - color: white; - margin-right: 5px; -} - -.animeEntry { - display: flex; - overflow-x: auto; -} - -.animeEntry:hover .anime { - opacity: 0.4; -} - -.animeEntry:hover .anime:hover { - opacity: 1; -} - -.animeEntry::-webkit-scrollbar { - height: 5px; -} - -.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: 5px; - border-style: dotted; - border-color: #636363; - margin: 10px 10px 0px 0px; - border-radius: 10px; - border-width: 4px; - transition: opacity 200ms ease-in; - background-color: #353535a6; - -} - -.anime p { - color: white; - width: 20dvw; - font-family: "Atkinson Hyperlegible"; - font-size: 18px; -} - -.animeImage { - border-radius: 10px; - margin-left: 20px; -} - -@media screen and (max-width: 768px) { - .searchContainer { - width: 70%; - } - - .anime p { - width: 50dvw; - } +.waitWhileLoading {
+ font-size: 18px;
+ font-family: "Kanit";
+ text-align: center;
+ color: white;
+}
+
+.inputContainer {
+ display: flex;
+ align-items: center;
+}
+
+.inputContainer button {
+ margin: 5px;
+ background-color: #121212;
+ padding: 10px;
+ border-radius: 10px;
+ outline: none;
+ border: none;
+ color: white;
+ font-family: "Atkinson Hyperlegible";
+}
+
+.inputContainer button a {
+ text-decoration: none;
+ color: white;
+}
+
+.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: 20px 0px 20px 0px;
+ background-color: #121212;
+ padding: 10px;
+ border-radius: 10px;
+ width: 30%;
+}
+
+.searchIcon {
+ color: white;
+ margin-right: 5px;
+}
+
+.animeEntry {
+ display: flex;
+ overflow-x: auto;
+}
+
+.animeEntry:hover .anime {
+ opacity: 0.4;
+}
+
+.animeEntry:hover .anime:hover {
+ opacity: 1;
+}
+
+.animeEntry::-webkit-scrollbar {
+ height: 5px;
+}
+
+.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: 5px;
+ border-style: dotted;
+ border-color: #636363;
+ margin: 10px 10px 0px 0px;
+ border-radius: 10px;
+ border-width: 4px;
+ transition: opacity 200ms ease-in;
+ background-color: #353535a6;
+
+}
+
+.anime p {
+ color: white;
+ width: 20dvw;
+ font-family: "Atkinson Hyperlegible";
+ font-size: 18px;
+}
+
+.animeImage {
+ border-radius: 10px;
+ margin-left: 20px;
+}
+
+@media screen and (max-width: 768px) {
+ .searchContainer {
+ width: 70%;
+ }
+
+ .anime p {
+ width: 50dvw;
+ }
}
\ No newline at end of file diff --git a/src/app/anime/top-airing/page.jsx b/src/app/anime/top-airing/page.jsx index 1d270f0..40a742c 100644 --- a/src/app/anime/top-airing/page.jsx +++ b/src/app/anime/top-airing/page.jsx @@ -1,48 +1,48 @@ -import styles from "./trending.module.css"; -import Image from "next/image"; -import Link from "next/link"; -import { preFetchAnimeInfo } from "../videoLinkfetcher"; - -export default async function Trending() { - const data = await test(); - preFetchAnimeInfo(data); - return ( - <div className={styles.TrendingContainer}> - <div className={styles.TrendingText}> - <p>Trending</p> - </div> - - <div className={styles.trending}> - {data && - data.results.map((item, index) => ( - <Link - key={index} - href={`/anime/${item.id}`} - style={{ textDecoration: "none", color: "white" }} - > - <div className={styles.trendingEntries}> - <Image - src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${item.image}`} - className={styles.trendingImage} - width={150} - height={230} - alt="Drama" - priority - /> - <p>{item.title}</p> - </div> - </Link> - ))} - </div> - </div> - ); -} - -async function test() { - const res = await fetch( - "https://consumet-jade.vercel.app/anime/gogoanime/top-airing", - { next: { revalidate: 86400 } } - ); - const data = res.json(); - return data; -} +import styles from "./trending.module.css";
+import Image from "next/image";
+import Link from "next/link";
+import { preFetchAnimeInfo } from "../videoLinkfetcher";
+
+export default async function Trending() {
+ const data = await test();
+ preFetchAnimeInfo(data);
+ return (
+ <div className={styles.TrendingContainer}>
+ <div className={styles.TrendingText}>
+ <p>Trending</p>
+ </div>
+
+ <div className={styles.trending}>
+ {data &&
+ data.results.map((item, index) => (
+ <Link
+ key={index}
+ href={`/anime/${item.id}`}
+ style={{ textDecoration: "none", color: "white" }}
+ >
+ <div className={styles.trendingEntries}>
+ <Image
+ src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${item.image}`}
+ className={styles.trendingImage}
+ width={150}
+ height={230}
+ alt="Drama"
+ priority
+ />
+ <p>{item.title}</p>
+ </div>
+ </Link>
+ ))}
+ </div>
+ </div>
+ );
+}
+
+async function test() {
+ const res = await fetch(
+ "https://consumet-jade.vercel.app/anime/gogoanime/top-airing",
+ { next: { revalidate: 86400 } }
+ );
+ const data = res.json();
+ return data;
+}
diff --git a/src/app/anime/top-airing/trending.module.css b/src/app/anime/top-airing/trending.module.css index 9d03384..d8f1ed6 100644 --- a/src/app/anime/top-airing/trending.module.css +++ b/src/app/anime/top-airing/trending.module.css @@ -1,72 +1,72 @@ -.TrendingText { - display: flex; - align-items: center; -} - -.TrendingText p { - font-size: 28px; - margin: 5px; - color: var(--soft-purple); - font-family: "Poppins"; - font-weight: 500; -} - -.TrendingText span { - margin-top: 6px; -} - -.trending { - display: flex; - overflow-x: auto; -} - -.TrendingContainer:hover .trendingEntries { - opacity: 0.5; -} - -.TrendingContainer:hover .trendingEntries:hover { - opacity: 1; - transform: scale(1.02); -} - -.trending::-webkit-scrollbar { - height: 5px; - width: 0px; -} - -.trending::-webkit-scrollbar-thumb { - background-color: #444444; - border-radius: 5px; -} - -.trendingEntries { - margin: 4px; - transition: transform 400ms ease; - background-color: #1f1f1fbb; - padding: 0.5rem; - border-radius: 1rem; - transition: opacity 400ms ease, transform 400ms ease; -} - -.trendingEntries p { - text-align: center; - margin: 5px auto; - width: 140px; - font-family: "Atkinson Hyperlegible"; - height: 80px; - overflow-y: auto; -} - -.trendingEntries p::-webkit-scrollbar { - width: 2px; -} - -.trendingEntries p::-webkit-scrollbar-thumb { - background-color: #444444; - border-radius: 5px; -} - -.trendingImage { - border-radius: 1rem; - aspect-ratio: auto; +.TrendingText {
+ display: flex;
+ align-items: center;
+}
+
+.TrendingText p {
+ font-size: 28px;
+ margin: 5px;
+ color: var(--soft-purple);
+ font-family: "Poppins";
+ font-weight: 500;
+}
+
+.TrendingText span {
+ margin-top: 6px;
+}
+
+.trending {
+ display: flex;
+ overflow-x: auto;
+}
+
+.TrendingContainer:hover .trendingEntries {
+ opacity: 0.5;
+}
+
+.TrendingContainer:hover .trendingEntries:hover {
+ opacity: 1;
+ transform: scale(1.02);
+}
+
+.trending::-webkit-scrollbar {
+ height: 5px;
+ width: 0px;
+}
+
+.trending::-webkit-scrollbar-thumb {
+ background-color: #444444;
+ border-radius: 5px;
+}
+
+.trendingEntries {
+ margin: 4px;
+ transition: transform 400ms ease;
+ background-color: #1f1f1fbb;
+ padding: 0.5rem;
+ border-radius: 1rem;
+ transition: opacity 400ms ease, transform 400ms ease;
+}
+
+.trendingEntries p {
+ text-align: center;
+ margin: 5px auto;
+ width: 140px;
+ font-family: "Atkinson Hyperlegible";
+ height: 80px;
+ overflow-y: auto;
+}
+
+.trendingEntries p::-webkit-scrollbar {
+ width: 2px;
+}
+
+.trendingEntries p::-webkit-scrollbar-thumb {
+ background-color: #444444;
+ border-radius: 5px;
+}
+
+.trendingImage {
+ border-radius: 1rem;
+ aspect-ratio: auto;
}
\ No newline at end of file diff --git a/src/app/anime/videoLinkfetcher.js b/src/app/anime/videoLinkfetcher.js index a2f4f80..a718534 100644 --- a/src/app/anime/videoLinkfetcher.js +++ b/src/app/anime/videoLinkfetcher.js @@ -1,46 +1,46 @@ -"use server"; -export async function fetch_video_link(id) { - try { - const res = await fetch( - `https://consumet-jade.vercel.app/anime/gogoanime/watch/${id}`, - { cache: "force-cache" } - ); - const data = await res.json(); - let vidLink = data.sources[data.sources.length - 2].url; - return vidLink; - } catch (error) { - console.log("Mehh Error", error); - } -} - -export async function preFetchAnimeLinks(data, n = 40) { - const limit = Math.min(n, data.episodes.length); - - try { - const fetchPromises = []; - for (let i = 0; i < limit; i++) { - const element = data.episodes[i]; - const link = `https://consumet-jade.vercel.app/anime/gogoanime/watch/${element.id}`; - fetchPromises.push(fetch(link, { cache: "force-cache" })); - } - - await Promise.all(fetchPromises); - console.log("Video links pre-fetched successfully!"); - } catch (error) { - console.error("Error occurred while pre-fetching video links:", error); - } -} - -export async function preFetchAnimeInfo(data) { - try { - const fetchPromises = data.results.map(async (element) => { - const link = `https://anime-sensei-api.vercel.app/anime/gogoanime/info/${element.id}`; - await fetch(link, { next: { revalidate: 86400 } }); - }); - - await Promise.all(fetchPromises); - console.log("Anime info pre-fetched successfully!"); - } catch (error) { - console.error("Error occurred while pre-fetching anime info: ", error); - } -} +"use server";
+export async function fetch_video_link(id) {
+ try {
+ const res = await fetch(
+ `https://consumet-jade.vercel.app/anime/gogoanime/watch/${id}`,
+ { cache: "force-cache" }
+ );
+ const data = await res.json();
+ let vidLink = data.sources[data.sources.length - 2].url;
+ return vidLink;
+ } catch (error) {
+ console.log("Mehh Error", error);
+ }
+}
+
+export async function preFetchAnimeLinks(data, n = 40) {
+ const limit = Math.min(n, data.episodes.length);
+
+ try {
+ const fetchPromises = [];
+ for (let i = 0; i < limit; i++) {
+ const element = data.episodes[i];
+ const link = `https://consumet-jade.vercel.app/anime/gogoanime/watch/${element.id}`;
+ fetchPromises.push(fetch(link, { cache: "force-cache" }));
+ }
+
+ await Promise.all(fetchPromises);
+ console.log("Video links pre-fetched successfully!");
+ } catch (error) {
+ console.error("Error occurred while pre-fetching video links:", error);
+ }
+}
+
+export async function preFetchAnimeInfo(data) {
+ try {
+ const fetchPromises = data.results.map(async (element) => {
+ const link = `https://anime-sensei-api.vercel.app/anime/gogoanime/info/${element.id}`;
+ await fetch(link, { next: { revalidate: 86400 } });
+ });
+
+ await Promise.all(fetchPromises);
+ console.log("Anime info pre-fetched successfully!");
+ } catch (error) {
+ console.error("Error occurred while pre-fetching anime info: ", error);
+ }
+}
diff --git a/src/app/components/footer/page.jsx b/src/app/components/footer/page.jsx index 08a7c73..2bc3add 100644 --- a/src/app/components/footer/page.jsx +++ b/src/app/components/footer/page.jsx @@ -1,11 +1,11 @@ -import styles from "../../page.module.css"; - -export default async function Footer() { - return ( - <main className={styles.main}> - <div className={styles.footer}> - <p>Made with :3 by zephex</p> - </div> - </main> - ); -} +import styles from "../../page.module.css";
+
+export default async function Footer() {
+ return (
+ <main className={styles.main}>
+ <div className={styles.footer}>
+ <p>Made with :3 by zephex</p>
+ </div>
+ </main>
+ );
+}
diff --git a/src/app/components/header/header.jsx b/src/app/components/header/header.jsx index 42978dd..9be6de2 100644 --- a/src/app/components/header/header.jsx +++ b/src/app/components/header/header.jsx @@ -1,24 +1,24 @@ -import Link from "next/link"; -import styles from "../../page.module.css"; - -export default function Header() { - return ( - <main className={styles.main}> - <div className={styles.header}> - <div className={styles.left}> - <Link - href={"/"} - style={{ textDecoration: "none", color: "white" }} - > - <p>Dramalama</p> - </Link> - </div> - <div className={styles.right}> - <Link href="/anime">Anime</Link> - <Link href="/kdrama">Kdrama</Link> - <Link href="/manga">Manga</Link> - </div> - </div> - </main> - ); -} +import Link from "next/link";
+import styles from "../../page.module.css";
+
+export default function Header() {
+ return (
+ <main className={styles.main}>
+ <div className={styles.header}>
+ <div className={styles.left}>
+ <Link
+ href={"/"}
+ style={{ textDecoration: "none", color: "white" }}
+ >
+ <p>Dramalama</p>
+ </Link>
+ </div>
+ <div className={styles.right}>
+ <Link href="/anime">Anime</Link>
+ <Link href="/kdrama">Kdrama</Link>
+ <Link href="/manga">Manga</Link>
+ </div>
+ </div>
+ </main>
+ );
+}
diff --git a/src/app/error.jsx b/src/app/error.jsx index 7060187..7549925 100644 --- a/src/app/error.jsx +++ b/src/app/error.jsx @@ -1,24 +1,24 @@ -"use client"; // Error components must be Client Components - -import { useEffect } from "react"; -import styles from "./globals.module.css"; - -export default function Error({ error, reset }) { - useEffect(() => { - console.log(error); - }, [error]); - - return ( - <div className={styles.ErrorContainer}> - <p>Something went wrong!</p> - <button - onClick={ - // Attempt to recover by trying to re-render the segment - () => reset() - } - > - Try again - </button> - </div> - ); -} +"use client"; // Error components must be Client Components
+
+import { useEffect } from "react";
+import styles from "./globals.module.css";
+
+export default function Error({ error, reset }) {
+ useEffect(() => {
+ console.log(error);
+ }, [error]);
+
+ return (
+ <div className={styles.ErrorContainer}>
+ <p>Something went wrong!</p>
+ <button
+ onClick={
+ // Attempt to recover by trying to re-render the segment
+ () => reset()
+ }
+ >
+ Try again
+ </button>
+ </div>
+ );
+}
diff --git a/src/app/globals.css b/src/app/globals.css index 7b5d384..a30325c 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,21 +1,21 @@ -@import url('https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:ital,wght@0,400;0,700;1,400;1,700&family=Lexend+Deca&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap'); - -:root { - --neon-green: #45FFCA; - --neon-yellow: #FEFFAC; - --light-green: #DCFFB7; - --pastel-red: #FF6868; - --soft-purple: #BEADFA; - --softer-purple: #D0BFFF; -} - - -body { - margin: 0; - padding: 0; - background-color: #1a1a1a; -} - -body::-webkit-scrollbar { - width: 0; +@import url('https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:ital,wght@0,400;0,700;1,400;1,700&family=Lexend+Deca&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap');
+
+:root {
+ --neon-green: #45FFCA;
+ --neon-yellow: #FEFFAC;
+ --light-green: #DCFFB7;
+ --pastel-red: #FF6868;
+ --soft-purple: #BEADFA;
+ --softer-purple: #D0BFFF;
+}
+
+
+body {
+ margin: 0;
+ padding: 0;
+ background-color: #1a1a1a;
+}
+
+body::-webkit-scrollbar {
+ width: 0;
}
\ No newline at end of file diff --git a/src/app/globals.module.css b/src/app/globals.module.css index dd29ada..73483ea 100644 --- a/src/app/globals.module.css +++ b/src/app/globals.module.css @@ -1,18 +1,18 @@ -.ErrorContainer { - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; - height: 100dvh; - color: white; - font-family: "Kanit"; - font-size: 20px; -} - -.ErrorContainer button { - border-radius: 5px; - padding: 3px; - font-family: "Lato"; - border: 0; - outline: 0; +.ErrorContainer {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
+ height: 100dvh;
+ color: white;
+ font-family: "Kanit";
+ font-size: 20px;
+}
+
+.ErrorContainer button {
+ border-radius: 5px;
+ padding: 3px;
+ font-family: "Lato";
+ border: 0;
+ outline: 0;
}
\ No newline at end of file diff --git a/src/app/kdrama/[id]/buttons.jsx b/src/app/kdrama/[id]/buttons.jsx index a7d0f60..53ae594 100644 --- a/src/app/kdrama/[id]/buttons.jsx +++ b/src/app/kdrama/[id]/buttons.jsx @@ -1,82 +1,82 @@ -"use client"; -import styles from "../styles/info.module.css"; -import getVideoLink from "../components/videoLink"; -import React, { useEffect, useState } from "react"; -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"; - -export default function EpisodesButtons({ data: episodeData, id: dramaId }) { - const [videoLink, setVideoLink] = useState(null); - const [episode, setEpisode] = useState(""); - - async function test(a, b, episodeText) { - let link = await getVideoLink(a, b); - setVideoLink(link); - setEpisode(episodeText); - } - - // Auto loads the first episode - useEffect(() => { - const fetchData = async () => { - try { - let firstVideoLink = episodeData[0].id; - let firstLink = await getVideoLink(firstVideoLink, dramaId); - setVideoLink(firstLink); - setEpisode("Episode 1"); - } catch (error) { - console.log("Some error occured", error); - return; - } - }; - - fetchData(); - }, []); - - return ( - <div> - <div className={styles.EpisodesContainer}> - <h2>Episodes</h2> - <div className={styles.EpisodeButtons}> - {episodeData && - episodeData.map((item, index) => ( - <button - key={index} - onClick={(event) => { - test(item.id, dramaId, item.title); - event.target.style.backgroundColor = - "var(--soft-purple)"; - }} - > - {item.title} - </button> - ))} - </div> - </div> - - <div className={styles.VideoContainer}> - {videoLink && ( - <div className={styles.Video}> - <MediaPlayer - title="dramaPlayer" - src={videoLink} - aspectRatio="16/9" - load="eager" - className={styles.VideoPlayer} - playsInline - volume={0.5} - > - <MediaProvider /> - <PlyrLayout icons={plyrLayoutIcons} /> - </MediaPlayer> - <p>{episode}</p> - </div> - )} - </div> - </div> - ); -} +"use client";
+import styles from "../styles/info.module.css";
+import getVideoLink from "../components/videoLink";
+import React, { useEffect, useState } from "react";
+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";
+
+export default function EpisodesButtons({ data: episodeData, id: dramaId }) {
+ const [videoLink, setVideoLink] = useState(null);
+ const [episode, setEpisode] = useState("");
+
+ async function test(a, b, episodeText) {
+ let link = await getVideoLink(a, b);
+ setVideoLink(link);
+ setEpisode(episodeText);
+ }
+
+ // Auto loads the first episode
+ useEffect(() => {
+ const fetchData = async () => {
+ try {
+ let firstVideoLink = episodeData[0].id;
+ let firstLink = await getVideoLink(firstVideoLink, dramaId);
+ setVideoLink(firstLink);
+ setEpisode("Episode 1");
+ } catch (error) {
+ console.log("Some error occured", error);
+ return;
+ }
+ };
+
+ fetchData();
+ }, []);
+
+ return (
+ <div>
+ <div className={styles.EpisodesContainer}>
+ <h2>Episodes</h2>
+ <div className={styles.EpisodeButtons}>
+ {episodeData &&
+ episodeData.map((item, index) => (
+ <button
+ key={index}
+ onClick={(event) => {
+ test(item.id, dramaId, item.title);
+ event.target.style.backgroundColor =
+ "var(--soft-purple)";
+ }}
+ >
+ {item.title}
+ </button>
+ ))}
+ </div>
+ </div>
+
+ <div className={styles.VideoContainer}>
+ {videoLink && (
+ <div className={styles.Video}>
+ <MediaPlayer
+ title="dramaPlayer"
+ src={videoLink}
+ aspectRatio="16/9"
+ load="eager"
+ className={styles.VideoPlayer}
+ playsInline
+ volume={0.5}
+ >
+ <MediaProvider />
+ <PlyrLayout icons={plyrLayoutIcons} />
+ </MediaPlayer>
+ <p>{episode}</p>
+ </div>
+ )}
+ </div>
+ </div>
+ );
+}
diff --git a/src/app/kdrama/[id]/page.jsx b/src/app/kdrama/[id]/page.jsx index 5625bd4..9a49c94 100644 --- a/src/app/kdrama/[id]/page.jsx +++ b/src/app/kdrama/[id]/page.jsx @@ -1,70 +1,70 @@ -import styles from "../styles/info.module.css"; -import Image from "next/image"; -import EpisodesButtons from "./buttons"; -import { PreFetchVideoLinks } from "../components/cacher"; - -export default async function DramaInfo({ params }) { - const id = decodeURIComponent(params.id); - const info = await getDramaInfo(id); - - PreFetchVideoLinks(info.episodes, id); - - return ( - <div className={styles.Main}> - {info && ( - <div className={styles.DramaInfoContainer}> - <div className={styles.TitleContainer}> - <p>{info.title}</p> - <Image - src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${info.image}`} - width={160} - height={240} - alt="Drama Poster" - priority - /> - </div> - - {/* Drama description */} - <div className={styles.DramaDescription}> - <h2>Description</h2> - <p>{info.description}</p> - </div> - - {/* Genres */} - <div className={styles.DramaGenre}> - <span className={styles.genreMain}>Genres: </span> - {info.genres && - info.genres.map((item, index) => ( - <span key={index} className={styles.genreEntry}> - {item} - </span> - ))} - </div> - - {/* Other names */} - <div className={styles.DramaGenre}> - <span className={styles.genreMain}>AKA: </span> - {info.otherNames && - info.otherNames.map((item, index) => ( - <span key={index} className={styles.genreEntry}> - {item} - </span> - ))} - </div> - - {/* Episodes Buttons */} - <EpisodesButtons data={info.episodes} id={id} /> - </div> - )} - </div> - ); -} - -async function getDramaInfo(id) { - const res = await fetch( - `https://consumet-jade.vercel.app/movies/dramacool/info?id=${id}`, - { next: { revalidate: 86400 } } - ); - const data = await res.json(); - return data; -} +import styles from "../styles/info.module.css";
+import Image from "next/image";
+import EpisodesButtons from "./buttons";
+import { PreFetchVideoLinks } from "../components/cacher";
+
+export default async function DramaInfo({ params }) {
+ const id = decodeURIComponent(params.id);
+ const info = await getDramaInfo(id);
+
+ PreFetchVideoLinks(info.episodes, id);
+
+ return (
+ <div className={styles.Main}>
+ {info && (
+ <div className={styles.DramaInfoContainer}>
+ <div className={styles.TitleContainer}>
+ <p>{info.title}</p>
+ <Image
+ src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${info.image}`}
+ width={160}
+ height={240}
+ alt="Drama Poster"
+ priority
+ />
+ </div>
+
+ {/* Drama description */}
+ <div className={styles.DramaDescription}>
+ <h2>Description</h2>
+ <p>{info.description}</p>
+ </div>
+
+ {/* Genres */}
+ <div className={styles.DramaGenre}>
+ <span className={styles.genreMain}>Genres: </span>
+ {info.genres &&
+ info.genres.map((item, index) => (
+ <span key={index} className={styles.genreEntry}>
+ {item}
+ </span>
+ ))}
+ </div>
+
+ {/* Other names */}
+ <div className={styles.DramaGenre}>
+ <span className={styles.genreMain}>AKA: </span>
+ {info.otherNames &&
+ info.otherNames.map((item, index) => (
+ <span key={index} className={styles.genreEntry}>
+ {item}
+ </span>
+ ))}
+ </div>
+
+ {/* Episodes Buttons */}
+ <EpisodesButtons data={info.episodes} id={id} />
+ </div>
+ )}
+ </div>
+ );
+}
+
+async function getDramaInfo(id) {
+ const res = await fetch(
+ `https://consumet-jade.vercel.app/movies/dramacool/info?id=${id}`,
+ { next: { revalidate: 86400 } }
+ );
+ const data = await res.json();
+ return data;
+}
diff --git a/src/app/kdrama/components/cacher.js b/src/app/kdrama/components/cacher.js index 1bb159e..ff76e0a 100644 --- a/src/app/kdrama/components/cacher.js +++ b/src/app/kdrama/components/cacher.js @@ -1,30 +1,30 @@ -// This function pre-fetches all the video links for a drama in the background -"use server"; - -export async function PreFetchVideoLinks(data, dramaId) { - try { - const fetchPromises = data.map(async (element) => { - const link = `https://consumet-jade.vercel.app/movies/dramacool/watch?episodeId=${element.id}&mediaId=${dramaId}`; - await fetch(link, { cache: "force-cache" }); - }); - - await Promise.all(fetchPromises); - console.log("Video links pre-fetched successfully!"); - } catch (error) { - console.error("Error occurred while pre-fetching video links:", error); - } -} - -export async function PreFetchAnimeInfo(data) { - try { - const fetchPromises = data.results.map(async (element) => { - const link = `https://consumet-jade.vercel.app/movies/dramacool/info?id=${element.id}`; - await fetch(link, { next: { revalidate: 86400 } }); - }); - - await Promise.all(fetchPromises); - console.log("Drama info fetched successfully."); - } catch (error) { - console.error("Error occurred while pre-fetching video links:", error); - } -} +// This function pre-fetches all the video links for a drama in the background
+"use server";
+
+export async function PreFetchVideoLinks(data, dramaId) {
+ try {
+ const fetchPromises = data.map(async (element) => {
+ const link = `https://consumet-jade.vercel.app/movies/dramacool/watch?episodeId=${element.id}&mediaId=${dramaId}`;
+ await fetch(link, { cache: "force-cache" });
+ });
+
+ await Promise.all(fetchPromises);
+ console.log("Video links pre-fetched successfully!");
+ } catch (error) {
+ console.error("Error occurred while pre-fetching video links:", error);
+ }
+}
+
+export async function PreFetchAnimeInfo(data) {
+ try {
+ const fetchPromises = data.results.map(async (element) => {
+ const link = `https://consumet-jade.vercel.app/movies/dramacool/info?id=${element.id}`;
+ await fetch(link, { next: { revalidate: 86400 } });
+ });
+
+ await Promise.all(fetchPromises);
+ console.log("Drama info fetched successfully.");
+ } catch (error) {
+ console.error("Error occurred while pre-fetching video links:", error);
+ }
+}
diff --git a/src/app/kdrama/components/popular.jsx b/src/app/kdrama/components/popular.jsx index 4f9a1d2..f652d57 100644 --- a/src/app/kdrama/components/popular.jsx +++ b/src/app/kdrama/components/popular.jsx @@ -1,44 +1,44 @@ -import styles from "../styles/popular.module.css"; -import Image from "next/image"; -import Link from "next/link"; -import { PreFetchAnimeInfo } from "./cacher"; - -export default async function PopularDramas() { - const popular = await getPopular(); - PreFetchAnimeInfo(popular); - - return ( - <div className={styles.Main}> - <p className={styles.popDramasText}>Trending Dramas</p> - - <div className={styles.AnimeContainer}> - {popular && - popular.results.map((item, index) => ( - <Link - href={`/kdrama/${encodeURIComponent(item.id)}`} - key={index} - style={{ textDecoration: "none" }} - > - <div className={styles.AnimeEntry}> - <Image - src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${item.image}`} - width={150} - height={230} - alt="Drama Poster" - /> - <p>{item.title}</p> - </div> - </Link> - ))} - </div> - </div> - ); -} - -async function getPopular() { - const res = await fetch("https://dramacool-scraper.vercel.app/popular", { - next: { revalidate: 33200 }, - }); - const data = await res.json(); - return data; -} +import styles from "../styles/popular.module.css";
+import Image from "next/image";
+import Link from "next/link";
+import { PreFetchAnimeInfo } from "./cacher";
+
+export default async function PopularDramas() {
+ const popular = await getPopular();
+ PreFetchAnimeInfo(popular);
+
+ return (
+ <div className={styles.Main}>
+ <p className={styles.popDramasText}>Trending Dramas</p>
+
+ <div className={styles.AnimeContainer}>
+ {popular &&
+ popular.results.map((item, index) => (
+ <Link
+ href={`/kdrama/${encodeURIComponent(item.id)}`}
+ key={index}
+ style={{ textDecoration: "none" }}
+ >
+ <div className={styles.AnimeEntry}>
+ <Image
+ src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${item.image}`}
+ width={150}
+ height={230}
+ alt="Drama Poster"
+ />
+ <p>{item.title}</p>
+ </div>
+ </Link>
+ ))}
+ </div>
+ </div>
+ );
+}
+
+async function getPopular() {
+ const res = await fetch("https://dramacool-scraper.vercel.app/popular", {
+ next: { revalidate: 33200 },
+ });
+ const data = await res.json();
+ return data;
+}
diff --git a/src/app/kdrama/components/recent.jsx b/src/app/kdrama/components/recent.jsx index e69e32a..eec4354 100644 --- a/src/app/kdrama/components/recent.jsx +++ b/src/app/kdrama/components/recent.jsx @@ -1,43 +1,43 @@ -import styles from "../styles/popular.module.css"; -import Image from "next/image"; -import Link from "next/link"; -import { PreFetchAnimeInfo } from "./cacher"; - -export default async function RecentDramas() { - const popular = await getPopular(); - PreFetchAnimeInfo(popular); - return ( - <div className={styles.Main}> - <p className={styles.popDramasText}>Recently Released</p> - - <div className={styles.AnimeContainer}> - {popular && - popular.results.map((item, index) => ( - <Link - href={`/kdrama/${encodeURIComponent(item.id)}`} - key={index} - style={{ textDecoration: "none" }} - > - <div className={styles.AnimeEntry}> - <Image - src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${item.image}`} - width={160} - height={240} - alt="Drama Poster" - /> - <p>{item.title}</p> - </div> - </Link> - ))} - </div> - </div> - ); -} - -async function getPopular() { - const res = await fetch("https://dramacool-scraper.vercel.app/recent", { - next: { revalidate: 86400 }, - }); - const data = await res.json(); - return data; -} +import styles from "../styles/popular.module.css";
+import Image from "next/image";
+import Link from "next/link";
+import { PreFetchAnimeInfo } from "./cacher";
+
+export default async function RecentDramas() {
+ const popular = await getPopular();
+ PreFetchAnimeInfo(popular);
+ return (
+ <div className={styles.Main}>
+ <p className={styles.popDramasText}>Recently Released</p>
+
+ <div className={styles.AnimeContainer}>
+ {popular &&
+ popular.results.map((item, index) => (
+ <Link
+ href={`/kdrama/${encodeURIComponent(item.id)}`}
+ key={index}
+ style={{ textDecoration: "none" }}
+ >
+ <div className={styles.AnimeEntry}>
+ <Image
+ src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${item.image}`}
+ width={160}
+ height={240}
+ alt="Drama Poster"
+ />
+ <p>{item.title}</p>
+ </div>
+ </Link>
+ ))}
+ </div>
+ </div>
+ );
+}
+
+async function getPopular() {
+ const res = await fetch("https://dramacool-scraper.vercel.app/recent", {
+ next: { revalidate: 86400 },
+ });
+ const data = await res.json();
+ return data;
+}
diff --git a/src/app/kdrama/components/search.jsx b/src/app/kdrama/components/search.jsx index 0dac544..4b31f3f 100644 --- a/src/app/kdrama/components/search.jsx +++ b/src/app/kdrama/components/search.jsx @@ -1,65 +1,65 @@ -"use client"; - -import styles from "../styles/search.module.css"; -import { useState } from "react"; -import { FaSearch } from "react-icons/fa"; -import FetchSearchTitle from "./searchQuery"; -import Image from "next/image"; -import Link from "next/link"; -import { PreFetchAnimeInfo } from "./cacher"; - -export default function DramaSearch() { - const [title, setTitle] = useState(""); - const [infoTitle, setInfoTitle] = useState(null); - const [loadingText, setLoadingText] = useState(null); - - const handleSearch = async (title) => { - setLoadingText(true); - const data = await FetchSearchTitle(title); - PreFetchAnimeInfo(data); - setLoadingText(false); - setInfoTitle(data); - }; - - return ( - <div className={styles.SearchContainer}> - <div className={styles.Search}> - <FaSearch color="white" size={16} /> - <input - placeholder="Search for drama" - onChange={(event) => setTitle(event.target.value)} - onKeyDown={async (e) => { - if ((e.key === "Enter" || e.code === 13) && title) { - await handleSearch(e.target.value); - } - }} - ></input> - </div> - - {loadingText && ( - <p className={styles.LoadingText}>Wait a moment...</p> - )} - - <div className={styles.SearchResults}> - {infoTitle && - infoTitle.results.map((item, index) => ( - <Link - href={`/kdrama/${encodeURIComponent(item.id)}`} - style={{ textDecoration: "none" }} - key={index} - > - <div className={styles.SearchEntry}> - <p>{item.title}</p> - <Image - src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${item.image}`} - width={110} - height={180} - alt="Drama Poster" - /> - </div> - </Link> - ))} - </div> - </div> - ); -} +"use client";
+
+import styles from "../styles/search.module.css";
+import { useState } from "react";
+import { FaSearch } from "react-icons/fa";
+import FetchSearchTitle from "./searchQuery";
+import Image from "next/image";
+import Link from "next/link";
+import { PreFetchAnimeInfo } from "./cacher";
+
+export default function DramaSearch() {
+ const [title, setTitle] = useState("");
+ const [infoTitle, setInfoTitle] = useState(null);
+ const [loadingText, setLoadingText] = useState(null);
+
+ const handleSearch = async (title) => {
+ setLoadingText(true);
+ const data = await FetchSearchTitle(title);
+ PreFetchAnimeInfo(data);
+ setLoadingText(false);
+ setInfoTitle(data);
+ };
+
+ return (
+ <div className={styles.SearchContainer}>
+ <div className={styles.Search}>
+ <FaSearch color="white" size={16} />
+ <input
+ placeholder="Search for drama"
+ onChange={(event) => setTitle(event.target.value)}
+ onKeyDown={async (e) => {
+ if ((e.key === "Enter" || e.code === 13) && title) {
+ await handleSearch(e.target.value);
+ }
+ }}
+ ></input>
+ </div>
+
+ {loadingText && (
+ <p className={styles.LoadingText}>Wait a moment...</p>
+ )}
+
+ <div className={styles.SearchResults}>
+ {infoTitle &&
+ infoTitle.results.map((item, index) => (
+ <Link
+ href={`/kdrama/${encodeURIComponent(item.id)}`}
+ style={{ textDecoration: "none" }}
+ key={index}
+ >
+ <div className={styles.SearchEntry}>
+ <p>{item.title}</p>
+ <Image
+ src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${item.image}`}
+ width={110}
+ height={180}
+ alt="Drama Poster"
+ />
+ </div>
+ </Link>
+ ))}
+ </div>
+ </div>
+ );
+}
diff --git a/src/app/kdrama/components/searchQuery.js b/src/app/kdrama/components/searchQuery.js index b67cf08..18c06a9 100644 --- a/src/app/kdrama/components/searchQuery.js +++ b/src/app/kdrama/components/searchQuery.js @@ -1,10 +1,10 @@ -"use server"; - -export default async function FetchSearchTitle(title) { - const res = await fetch( - `https://consumet-jade.vercel.app/movies/dramacool/${title}`, - { cache: "force-cache" } - ); - const data = await res.json(); - return data; -} +"use server";
+
+export default async function FetchSearchTitle(title) {
+ const res = await fetch(
+ `https://consumet-jade.vercel.app/movies/dramacool/${title}`,
+ { cache: "force-cache" }
+ );
+ const data = await res.json();
+ return data;
+}
diff --git a/src/app/kdrama/components/videoLink.js b/src/app/kdrama/components/videoLink.js index db1b885..e49ca18 100644 --- a/src/app/kdrama/components/videoLink.js +++ b/src/app/kdrama/components/videoLink.js @@ -1,11 +1,11 @@ -"use server"; -export default async function getVideoLink(epiId, mediaId) { - let videoLink; - const res = await fetch( - `https://consumet-jade.vercel.app/movies/dramacool/watch?episodeId=${epiId}&mediaId=${mediaId}`, - { cache: "force-cache" } - ); - const data = await res.json(); - videoLink = data.sources[0].url; - return videoLink; -} +"use server";
+export default async function getVideoLink(epiId, mediaId) {
+ let videoLink;
+ const res = await fetch(
+ `https://consumet-jade.vercel.app/movies/dramacool/watch?episodeId=${epiId}&mediaId=${mediaId}`,
+ { cache: "force-cache" }
+ );
+ const data = await res.json();
+ videoLink = data.sources[0].url;
+ return videoLink;
+}
diff --git a/src/app/kdrama/loading.jsx b/src/app/kdrama/loading.jsx index 9d5b702..4d5e9bd 100644 --- a/src/app/kdrama/loading.jsx +++ b/src/app/kdrama/loading.jsx @@ -1,9 +1,9 @@ -import styles from "./styles/loading.module.css"; - -export default async function Loading() { - return ( - <div className={styles.Main}> - <div className={styles.LoadingContainer}></div> - </div> - ); -} +import styles from "./styles/loading.module.css";
+
+export default async function Loading() {
+ return (
+ <div className={styles.Main}>
+ <div className={styles.LoadingContainer}></div>
+ </div>
+ );
+}
diff --git a/src/app/kdrama/page.jsx b/src/app/kdrama/page.jsx index 44f8eb9..ab5ec3c 100644 --- a/src/app/kdrama/page.jsx +++ b/src/app/kdrama/page.jsx @@ -1,14 +1,14 @@ -import styles from "./styles/kdrama.module.css"; -import PopularDramas from "./components/popular"; -import RecentDramas from "./components/recent"; -import DramaSearch from "./components/search"; - -export default async function Kdrama() { - return ( - <div className={styles.Main}> - <DramaSearch /> - <PopularDramas /> - <RecentDramas /> - </div> - ); -} +import styles from "./styles/kdrama.module.css";
+import PopularDramas from "./components/popular";
+import RecentDramas from "./components/recent";
+import DramaSearch from "./components/search";
+
+export default async function Kdrama() {
+ return (
+ <div className={styles.Main}>
+ <DramaSearch />
+ <PopularDramas />
+ <RecentDramas />
+ </div>
+ );
+}
diff --git a/src/app/kdrama/styles/info.module.css b/src/app/kdrama/styles/info.module.css index f61d90f..1857eb3 100644 --- a/src/app/kdrama/styles/info.module.css +++ b/src/app/kdrama/styles/info.module.css @@ -1,122 +1,122 @@ -.Main { - max-width: 98%; - margin: 80px auto; -} - -.TitleContainer { - display: flex; - align-items: center; - justify-content: space-between; -} - -.TitleContainer p { - color: white; - font-family: "Poppins"; - font-size: 32px; -} - -.TitleContainer img { - width: auto; - /* height: auto; */ - border-radius: 10px; -} - -.DramaDescription h2 { - color: gray; - font-family: "Poppins"; -} - -.DramaDescription p { - font-family: "Atkinson Hyperlegible"; - color: white; - margin-top: -10px; -} - -.DramaGenre { - display: flex; - align-items: center; - overflow-x: auto; -} - -.genreMain { - font-family: "Poppins"; - color: var(--neon-green); - font-size: 18px; -} - -.genreEntry { - background-color: #31313141; - color: white; - padding: 5px; - margin: 3px; - border-radius: 5px; - font-family: "Atkinson Hyperlegible"; - cursor: crosshair; -} - -.EpisodesContainer { - margin-top: -10px; -} - -.EpisodesContainer h2 { - color: gray; - font-family: "Poppins"; -} - -.EpisodeButtons { - margin: -10px 5px; -} - -.EpisodeButtons button { - margin: 3px; - padding: 5px; - border: none; - outline: none; - font-family: "Atkinson Hyperlegible"; - font-size: 16px; - border-radius: 5px; - background-color: #3d3d3d; - transition: background-color 0.2s linear; - color: white; - cursor: pointer; - width: 100px; -} - -.EpisodeButtons button:hover { - background-color: #1f1f1f; - transition: background-color 0.2s linear -} - -.VideoContainer { - margin-top: 20px; -} - -.Video { - display: flex; - flex-direction: column; - align-items: center; - width: 70dvw; - margin: 0px auto; -} - -.Video p { - color: white; - font-family: "Atkinson Hyperlegible"; - color: var(--pastel-red); -} - -.VideoPlayer { - margin: 0px auto; -} - -@media screen and (max-width: 768px) { - .Video { - width: 100%; - } - - .EpisodeButtons button { - font-size: 14px; - width: 80px; - } - +.Main {
+ max-width: 98%;
+ margin: 80px auto;
+}
+
+.TitleContainer {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.TitleContainer p {
+ color: white;
+ font-family: "Poppins";
+ font-size: 32px;
+}
+
+.TitleContainer img {
+ width: auto;
+ /* height: auto; */
+ border-radius: 10px;
+}
+
+.DramaDescription h2 {
+ color: gray;
+ font-family: "Poppins";
+}
+
+.DramaDescription p {
+ font-family: "Atkinson Hyperlegible";
+ color: white;
+ margin-top: -10px;
+}
+
+.DramaGenre {
+ display: flex;
+ align-items: center;
+ overflow-x: auto;
+}
+
+.genreMain {
+ font-family: "Poppins";
+ color: var(--neon-green);
+ font-size: 18px;
+}
+
+.genreEntry {
+ background-color: #31313141;
+ color: white;
+ padding: 5px;
+ margin: 3px;
+ border-radius: 5px;
+ font-family: "Atkinson Hyperlegible";
+ cursor: crosshair;
+}
+
+.EpisodesContainer {
+ margin-top: -10px;
+}
+
+.EpisodesContainer h2 {
+ color: gray;
+ font-family: "Poppins";
+}
+
+.EpisodeButtons {
+ margin: -10px 5px;
+}
+
+.EpisodeButtons button {
+ margin: 3px;
+ padding: 5px;
+ border: none;
+ outline: none;
+ font-family: "Atkinson Hyperlegible";
+ font-size: 16px;
+ border-radius: 5px;
+ background-color: #3d3d3d;
+ transition: background-color 0.2s linear;
+ color: white;
+ cursor: pointer;
+ width: 100px;
+}
+
+.EpisodeButtons button:hover {
+ background-color: #1f1f1f;
+ transition: background-color 0.2s linear
+}
+
+.VideoContainer {
+ margin-top: 20px;
+}
+
+.Video {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 70dvw;
+ margin: 0px auto;
+}
+
+.Video p {
+ color: white;
+ font-family: "Atkinson Hyperlegible";
+ color: var(--pastel-red);
+}
+
+.VideoPlayer {
+ margin: 0px auto;
+}
+
+@media screen and (max-width: 768px) {
+ .Video {
+ width: 100%;
+ }
+
+ .EpisodeButtons button {
+ font-size: 14px;
+ width: 80px;
+ }
+
}
\ No newline at end of file diff --git a/src/app/kdrama/styles/kdrama.module.css b/src/app/kdrama/styles/kdrama.module.css index 9cfc377..9bb987c 100644 --- a/src/app/kdrama/styles/kdrama.module.css +++ b/src/app/kdrama/styles/kdrama.module.css @@ -1,4 +1,4 @@ -.Main { - max-width: 98%; - margin: 80px auto; +.Main {
+ max-width: 98%;
+ margin: 80px auto;
}
\ No newline at end of file diff --git a/src/app/kdrama/styles/loading.module.css b/src/app/kdrama/styles/loading.module.css index 557f50a..011240e 100644 --- a/src/app/kdrama/styles/loading.module.css +++ b/src/app/kdrama/styles/loading.module.css @@ -1,21 +1,21 @@ -.Main { - height: 100dvh; - display: flex; - justify-content: center; - align-items: center; -} - -.LoadingContainer { - width: 50px; - height: 50px; - border-radius: 50%; - border: 8px solid; - border-color: #F4F4F4 #0000; - animation: s1 1s infinite; -} - -@keyframes s1 { - to { - transform: rotate(.5turn) - } +.Main {
+ height: 100dvh;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.LoadingContainer {
+ width: 50px;
+ height: 50px;
+ border-radius: 50%;
+ border: 8px solid;
+ border-color: #F4F4F4 #0000;
+ animation: s1 1s infinite;
+}
+
+@keyframes s1 {
+ to {
+ transform: rotate(.5turn)
+ }
}
\ No newline at end of file diff --git a/src/app/kdrama/styles/popular.module.css b/src/app/kdrama/styles/popular.module.css index 3e09953..053c558 100644 --- a/src/app/kdrama/styles/popular.module.css +++ b/src/app/kdrama/styles/popular.module.css @@ -1,63 +1,63 @@ -.popDramasText { - color: var(--soft-purple); - font-family: "Poppins"; - font-size: 28px; - margin-bottom: 10px; - font-weight: 500; -} - -.AnimeContainer { - display: flex; - overflow-x: auto; - overflow-y: hidden; -} - -.AnimeContainer::-webkit-scrollbar { - height: 5px; -} - -.AnimeContainer::-webkit-scrollbar-track { - background-color: #3333339d; - border-radius: 5px; -} - -.AnimeContainer::-webkit-scrollbar-thumb { - background-color: rgb(68, 68, 68); - border-radius: 5px; -} - -.AnimeContainer:hover .AnimeEntry { - opacity: 0.3; -} - -.AnimeContainer:hover .AnimeEntry:hover { - opacity: 1; - transform: scale(1.02); -} - -/* Format the scrollbar later */ - -.AnimeEntry { - display: flex; - flex-direction: column; - align-items: center; - margin: 4px; - background-color: #1f1f1fbb; - padding: 0.5rem; - transition: opacity 400ms ease, transform 400ms ease; - cursor: grab; - border-radius: 1rem; -} - -.AnimeEntry img { - border-radius: 1rem; -} - -.AnimeEntry p { - text-align: center; - color: white; - font-family: "Atkinson Hyperlegible"; - width: 140px; - height: 60px; - overflow-y: auto; +.popDramasText {
+ color: var(--soft-purple);
+ font-family: "Poppins";
+ font-size: 28px;
+ margin-bottom: 10px;
+ font-weight: 500;
+}
+
+.AnimeContainer {
+ display: flex;
+ overflow-x: auto;
+ overflow-y: hidden;
+}
+
+.AnimeContainer::-webkit-scrollbar {
+ height: 5px;
+}
+
+.AnimeContainer::-webkit-scrollbar-track {
+ background-color: #3333339d;
+ border-radius: 5px;
+}
+
+.AnimeContainer::-webkit-scrollbar-thumb {
+ background-color: rgb(68, 68, 68);
+ border-radius: 5px;
+}
+
+.AnimeContainer:hover .AnimeEntry {
+ opacity: 0.3;
+}
+
+.AnimeContainer:hover .AnimeEntry:hover {
+ opacity: 1;
+ transform: scale(1.02);
+}
+
+/* Format the scrollbar later */
+
+.AnimeEntry {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin: 4px;
+ background-color: #1f1f1fbb;
+ padding: 0.5rem;
+ transition: opacity 400ms ease, transform 400ms ease;
+ cursor: grab;
+ border-radius: 1rem;
+}
+
+.AnimeEntry img {
+ border-radius: 1rem;
+}
+
+.AnimeEntry p {
+ text-align: center;
+ color: white;
+ font-family: "Atkinson Hyperlegible";
+ width: 140px;
+ height: 60px;
+ overflow-y: auto;
}
\ No newline at end of file diff --git a/src/app/kdrama/styles/search.module.css b/src/app/kdrama/styles/search.module.css index fcf75b0..54175ce 100644 --- a/src/app/kdrama/styles/search.module.css +++ b/src/app/kdrama/styles/search.module.css @@ -1,83 +1,83 @@ -.SearchContainer { - margin: 20px 0px -20px 0px; -} - -.LoadingText { - color: white; - font-family: "Atkinson Hyperlegible"; - text-align: center; -} - -.Search { - padding: 5px; - background-color: #121212; - display: flex; - align-items: center; - max-width: 30%; - border-radius: 10px; -} - -.SearchContainer input { - margin-left: 5px; - padding: 5px; - border: none; - outline: none; - background-color: #121212; - font-size: 16px; - font-family: "Atkinson Hyperlegible"; - color: white; - width: 100%; -} - -.SearchResults { - display: flex; - margin-top: 10px; - overflow-x: auto; -} - -.SearchResults::-webkit-scrollbar { - height: 5px; -} - -.SearchResults::-webkit-scrollbar-track { - background-color: #3333339d; - border-radius: 5px; -} - -.SearchResults::-webkit-scrollbar-thumb { - background-color: rgb(68, 68, 68); - border-radius: 5px; -} - -.SearchEntry { - display: flex; - align-items: center; - justify-content: space-between; - margin: 5px; - padding: 6px; - background-color: #2e2e2eab; - border-radius: 10px; - cursor: pointer; - transition: transform 0.2s linear; -} - -.SearchEntry:hover { - transition: transform 0.2s linear; - transform: scale(1.01); -} - -.SearchEntry p { - color: white; - font-family: "Atkinson Hyperlegible"; - width: 40vh; -} - -.SearchEntry img { - border-radius: 10px; -} - -@media screen and (max-width: 768px) { - .Search { - max-width: 100%; - } +.SearchContainer {
+ margin: 20px 0px -20px 0px;
+}
+
+.LoadingText {
+ color: white;
+ font-family: "Atkinson Hyperlegible";
+ text-align: center;
+}
+
+.Search {
+ padding: 5px;
+ background-color: #121212;
+ display: flex;
+ align-items: center;
+ max-width: 30%;
+ border-radius: 10px;
+}
+
+.SearchContainer input {
+ margin-left: 5px;
+ padding: 5px;
+ border: none;
+ outline: none;
+ background-color: #121212;
+ font-size: 16px;
+ font-family: "Atkinson Hyperlegible";
+ color: white;
+ width: 100%;
+}
+
+.SearchResults {
+ display: flex;
+ margin-top: 10px;
+ overflow-x: auto;
+}
+
+.SearchResults::-webkit-scrollbar {
+ height: 5px;
+}
+
+.SearchResults::-webkit-scrollbar-track {
+ background-color: #3333339d;
+ border-radius: 5px;
+}
+
+.SearchResults::-webkit-scrollbar-thumb {
+ background-color: rgb(68, 68, 68);
+ border-radius: 5px;
+}
+
+.SearchEntry {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin: 5px;
+ padding: 6px;
+ background-color: #2e2e2eab;
+ border-radius: 10px;
+ cursor: pointer;
+ transition: transform 0.2s linear;
+}
+
+.SearchEntry:hover {
+ transition: transform 0.2s linear;
+ transform: scale(1.01);
+}
+
+.SearchEntry p {
+ color: white;
+ font-family: "Atkinson Hyperlegible";
+ width: 40vh;
+}
+
+.SearchEntry img {
+ border-radius: 10px;
+}
+
+@media screen and (max-width: 768px) {
+ .Search {
+ max-width: 100%;
+ }
}
\ No newline at end of file diff --git a/src/app/manga/[title]/[id]/[read]/currentReading.jsx b/src/app/manga/[title]/[id]/[read]/currentReading.jsx index 0050d61..5205ea9 100644 --- a/src/app/manga/[title]/[id]/[read]/currentReading.jsx +++ b/src/app/manga/[title]/[id]/[read]/currentReading.jsx @@ -1,34 +1,34 @@ -"use client"; - -import styles from "./read.module.css"; -import { useEffect } from "react"; - -function get_current_info(title) { - let req = {}; - - useEffect(() => { - const data = JSON.parse(localStorage.getItem("mangaData")); - data.watchHis.forEach((element) => { - if (element.title === title) { - req.chapter = element.chapter; - req.volume = element.volume; - } - }); - }, []); - - return req || false; -} - -export default function Current({ name: title }) { - let data = get_current_info(title); - if (!data) { - return; - } - - return ( - <section className={styles.CurrentMain}> - <p className={styles.CurrentChapter}>{data.chapter}</p> - <p className={styles.CurrentVolume}>{data.volume}</p> - </section> - ); -} +"use client";
+
+import styles from "./read.module.css";
+import { useEffect } from "react";
+
+function get_current_info(title) {
+ let req = {};
+
+ useEffect(() => {
+ const data = JSON.parse(localStorage.getItem("mangaData"));
+ data.watchHis.forEach((element) => {
+ if (element.title === title) {
+ req.chapter = element.chapter;
+ req.volume = element.volume;
+ }
+ });
+ }, []);
+
+ return req || false;
+}
+
+export default function Current({ name: title }) {
+ let data = get_current_info(title);
+ if (!data) {
+ return;
+ }
+
+ return (
+ <section className={styles.CurrentMain}>
+ <p className={styles.CurrentChapter}>{data.chapter}</p>
+ <p className={styles.CurrentVolume}>{data.volume}</p>
+ </section>
+ );
+}
diff --git a/src/app/manga/[title]/[id]/[read]/download.jsx b/src/app/manga/[title]/[id]/[read]/download.jsx index e7a20ee..bddf6d3 100644 --- a/src/app/manga/[title]/[id]/[read]/download.jsx +++ b/src/app/manga/[title]/[id]/[read]/download.jsx @@ -1,21 +1,21 @@ -"use client"; - -import styles from "./read.module.css"; - -export default function DownloadManga({ chapterId: id }) { - return ( - <div className={styles.DownloadMain}> - <a - href={`https://manga-downloader-7nca.onrender.com/download?id=${id}`} - style={{ textDecoration: "none" }} - onClick={() => - alert( - "Downloads are not instant. It might take some time to prepare your file. Thank you for your patience" - ) - } - > - <button title="should work just fine">Download - Beta</button> - </a> - </div> - ); -} +"use client";
+
+import styles from "./read.module.css";
+
+export default function DownloadManga({ chapterId: id }) {
+ return (
+ <div className={styles.DownloadMain}>
+ <a
+ href={`https://manga-downloader-7nca.onrender.com/download?id=${id}`}
+ style={{ textDecoration: "none" }}
+ onClick={() =>
+ alert(
+ "Downloads are not instant. It might take some time to prepare your file. Thank you for your patience"
+ )
+ }
+ >
+ <button title="should work just fine">Download - Beta</button>
+ </a>
+ </div>
+ );
+}
diff --git a/src/app/manga/[title]/[id]/[read]/page.jsx b/src/app/manga/[title]/[id]/[read]/page.jsx index dbba6e0..a4181d7 100644 --- a/src/app/manga/[title]/[id]/[read]/page.jsx +++ b/src/app/manga/[title]/[id]/[read]/page.jsx @@ -1,56 +1,56 @@ -import styles from "./read.module.css"; -import Image from "next/image"; -import DownloadManga from "./download"; - -export default async function Read({ params }) { - const chapterId = params.read; - const results = await getPages(chapterId); - const image_base_url = results.baseUrl + "/data/" + results.chapter.hash; - - if (results.length === 0) { - return ( - <div className={styles.NotFound}> - <p> - This chapter has no content. Please check the next chapter. - </p> - </div> - ); - } - - let images = []; - for (var i = 0; i < results.chapter.data.length; i++) { - var imgUrl = image_base_url + "/" + results.chapter.data[i]; - images.push(imgUrl); - } - - return ( - <div className={styles.Main}> - <div className={styles.ImageContainer}> - <DownloadManga chapterId={chapterId} /> - <p>Total pages: {images.length}</p> - {images && - images.map((item, index) => ( - <div className={styles.Image} key={index}> - <Image - src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${item}`} - key={index} - alt="Pages" - width={800} - height={1000} - priority - quality={100} - unoptimized - /> - <p>{index + 1}</p> - </div> - ))} - </div> - </div> - ); -} - -async function getPages(id) { - const res = await fetch(`https://api.mangadex.org/at-home/server/${id}`); - const data = await res.json(); - return data; -} +import styles from "./read.module.css";
+import Image from "next/image";
+import DownloadManga from "./download";
+
+export default async function Read({ params }) {
+ const chapterId = params.read;
+ const results = await getPages(chapterId);
+ const image_base_url = results.baseUrl + "/data/" + results.chapter.hash;
+
+ if (results.length === 0) {
+ return (
+ <div className={styles.NotFound}>
+ <p>
+ This chapter has no content. Please check the next chapter.
+ </p>
+ </div>
+ );
+ }
+
+ let images = [];
+ for (var i = 0; i < results.chapter.data.length; i++) {
+ var imgUrl = image_base_url + "/" + results.chapter.data[i];
+ images.push(imgUrl);
+ }
+
+ return (
+ <div className={styles.Main}>
+ <div className={styles.ImageContainer}>
+ <DownloadManga chapterId={chapterId} />
+ <p>Total pages: {images.length}</p>
+ {images &&
+ images.map((item, index) => (
+ <div className={styles.Image} key={index}>
+ <Image
+ src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${item}`}
+ key={index}
+ alt="Pages"
+ width={800}
+ height={1000}
+ priority
+ quality={100}
+ unoptimized
+ />
+ <p>{index + 1}</p>
+ </div>
+ ))}
+ </div>
+ </div>
+ );
+}
+
+async function getPages(id) {
+ const res = await fetch(`https://api.mangadex.org/at-home/server/${id}`);
+ const data = await res.json();
+ return data;
+}
diff --git a/src/app/manga/[title]/[id]/[read]/read.module.css b/src/app/manga/[title]/[id]/[read]/read.module.css index 420fff8..0133232 100644 --- a/src/app/manga/[title]/[id]/[read]/read.module.css +++ b/src/app/manga/[title]/[id]/[read]/read.module.css @@ -1,65 +1,65 @@ -.Main { - margin: 80px auto; -} - -.Image { - display: flex; - flex-direction: column; - align-items: center; - background-color: #1b1b1b; - border-radius: 10px; - width: 50%; - margin: 10px auto; -} - -.ImageContainer img { - max-width: auto; - height: auto; - border-radius: 5px; - margin-top: 10px; -} - -.ImageContainer p { - text-align: center; - color: white; - font-family: "Atkinson Hyperlegible", serif; - font-size: 16px; - margin: 5px; -} - -.NotFound { - text-align: center; - color: white; - font-family: "Atkinson Hyperlegible", serif; - font-size: 20px; -} - -.DownloadMain { - text-align: center; -} - -.DownloadMain button { - border: none; - outline: none; - border-radius: 5px; - padding: 5px; - font-family: "Atkinson Hyperlegible", serif; - font-size: 16px; - background-color: var(--light-green); - cursor: pointer; -} - -.DownloadMain button:hover { - background-color: var(--pastel-red); -} - -@media screen and (max-width: 768px) { - .ImageContainer img { - width: 95%; - align-items: center; - } - - .Image { - width: 100%; - } +.Main {
+ margin: 80px auto;
+}
+
+.Image {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ background-color: #1b1b1b;
+ border-radius: 10px;
+ width: 50%;
+ margin: 10px auto;
+}
+
+.ImageContainer img {
+ max-width: auto;
+ height: auto;
+ border-radius: 5px;
+ margin-top: 10px;
+}
+
+.ImageContainer p {
+ text-align: center;
+ color: white;
+ font-family: "Atkinson Hyperlegible", serif;
+ font-size: 16px;
+ margin: 5px;
+}
+
+.NotFound {
+ text-align: center;
+ color: white;
+ font-family: "Atkinson Hyperlegible", serif;
+ font-size: 20px;
+}
+
+.DownloadMain {
+ text-align: center;
+}
+
+.DownloadMain button {
+ border: none;
+ outline: none;
+ border-radius: 5px;
+ padding: 5px;
+ font-family: "Atkinson Hyperlegible", serif;
+ font-size: 16px;
+ background-color: var(--light-green);
+ cursor: pointer;
+}
+
+.DownloadMain button:hover {
+ background-color: var(--pastel-red);
+}
+
+@media screen and (max-width: 768px) {
+ .ImageContainer img {
+ width: 95%;
+ align-items: center;
+ }
+
+ .Image {
+ width: 100%;
+ }
}
\ No newline at end of file diff --git a/src/app/manga/[title]/[id]/buttons.jsx b/src/app/manga/[title]/[id]/buttons.jsx index 4c11705..a6c8d75 100644 --- a/src/app/manga/[title]/[id]/buttons.jsx +++ b/src/app/manga/[title]/[id]/buttons.jsx @@ -1,54 +1,54 @@ -"use client"; - -import styles from "./info.module.css"; -import Link from "next/link"; -import { storeLocal } from "../../history/storeData"; - -export default function Buttons({ content: data }) { - function store_to_local(title, chapter, volume, image, id, id2) { - let data = { - title: title, - chapter: chapter, - volume: volume, - image: image, - id: id, - mangaId: id2, - }; - storeLocal(data); - } - - return ( - <div className={styles.ChapterContainer}> - {data.chapters && - data.chapters.map((item, index) => { - if (item.pages !== 0) { - return ( - <Link - key={index} - href={{ - pathname: `/manga/info/read/${item.id}`, - }} - onClick={() => { - store_to_local( - data.title.english || data.title.romaji, - parseInt(item.chapterNumber), - parseInt(item.volumeNumber), - data.image, - item.id, - data.id - ); - }} - > - <button key={index}> - <div> - <p>Chapter: {item.chapterNumber}</p> - <p>Volume: {item.volumeNumber}</p> - </div> - </button> - </Link> - ); - } - })} - </div> - ); -} +"use client";
+
+import styles from "./info.module.css";
+import Link from "next/link";
+import { storeLocal } from "../../history/storeData";
+
+export default function Buttons({ content: data }) {
+ function store_to_local(title, chapter, volume, image, id, id2) {
+ let data = {
+ title: title,
+ chapter: chapter,
+ volume: volume,
+ image: image,
+ id: id,
+ mangaId: id2,
+ };
+ storeLocal(data);
+ }
+
+ return (
+ <div className={styles.ChapterContainer}>
+ {data.chapters &&
+ data.chapters.map((item, index) => {
+ if (item.pages !== 0) {
+ return (
+ <Link
+ key={index}
+ href={{
+ pathname: `/manga/info/read/${item.id}`,
+ }}
+ onClick={() => {
+ store_to_local(
+ data.title.english || data.title.romaji,
+ parseInt(item.chapterNumber),
+ parseInt(item.volumeNumber),
+ data.image,
+ item.id,
+ data.id
+ );
+ }}
+ >
+ <button key={index}>
+ <div>
+ <p>Chapter: {item.chapterNumber}</p>
+ <p>Volume: {item.volumeNumber}</p>
+ </div>
+ </button>
+ </Link>
+ );
+ }
+ })}
+ </div>
+ );
+}
diff --git a/src/app/manga/[title]/[id]/info.module.css b/src/app/manga/[title]/[id]/info.module.css index b1b76f4..bc22f49 100644 --- a/src/app/manga/[title]/[id]/info.module.css +++ b/src/app/manga/[title]/[id]/info.module.css @@ -1,224 +1,224 @@ -.MangaInfoContainer { - margin: 68px auto; -} - -.MangaHero { - display: flex; - flex-direction: column; - justify-content: center; -} - -.TitleContainer { - display: flex; - justify-content: space-between; - align-items: center; - padding: 5px; - background-color: #2c2c2c9c; - backdrop-filter: blur(5px); - -} - -.TitleContainer p { - font-family: "Lexend Deca", serif; - font-size: 40px; - font-weight: 1000; -} - -.TitleContainer img { - border-radius: 10px; - margin-left: 5px; -} - -.MangaDescription { - color: white; - font-family: "Atkinson Hyperlegible", serif; - max-width: 98%; - margin: -10px auto; -} - -.Description h2 { - font-family: "Lexend Deca", serif; - color: gray; -} - -.Description p { - margin-top: -10px; -} - -.MangaReleaseYear { - margin-top: 10px; - font-family: "Poppins", serif; -} - -.GenreContainer { - margin-top: 5px; - display: flex; - align-items: center; - font-family: "Poppins", serif; -} - -.GenreText { - color: var(--neon-green); -} - -.GenreContainer { - margin-top: 10px; -} - -.genres { - display: flex; - align-items: center; - overflow-x: auto; -} - -.MangaGenre { - background-color: #5f5f5f5d; - border-radius: 5px; - padding: 2px 5px; - cursor: pointer; - margin: 2px; -} - -.MangaRatings { - display: flex; - margin-top: 10px; - font-family: "Poppins", serif; - /* justify-content: center; */ -} - -.MangaRatings span { - margin-right: 2px; - margin-left: 2px; - color: var(--light-green); -} - -.CharactersContainer { - max-width: 98%; - margin: 20px auto; -} - -.CharactersContainer h2 { - color: gray; - font-family: "Lexend Deca", serif; -} - -.Character { - display: flex; - flex-direction: row; - overflow-x: auto; - margin-top: -10px; -} - -.Character::-webkit-scrollbar { - height: 5px; -} - -.Character::-webkit-scrollbar-thumb { - background-color: #31363F; - border-radius: 5px; -} - -.CharacterEntry { - display: flex; - flex-direction: column; - align-items: center; - width: auto; - margin: 5px; -} - -.CharacterEntry p { - margin: 10px auto; - text-align: center; - width: 110px; - color: white; - font-family: "Atkinson Hyperlegible", serif; -} - -.CharacterEntry img { - border-radius: 10px; -} - -/* Chapters Buttons */ - -.Chapters { - display: flex; - align-items: center; - justify-content: space-between; - max-width: 90%; - margin: 20px auto; -} - -.ChapterTitle { - color: white; - font-family: "Lexend Deca", serif; - font-size: 32px; -} - -.ChapterContainer { - width: 50dvw; - text-align: center; - height: 300px; - overflow-y: auto; -} - -.ChapterContainer::-webkit-scrollbar { - width: 5px; - height: 0px; -} - -.ChapterContainer::-webkit-scrollbar-thumb { - background-color: #31363F; - border-radius: 5px; -} - -.ChapterContainer button { - width: 130px; - height: auto; - padding: 10px; - margin: 5px; - border-radius: 5px; - font-size: 16px; - border: none; - outline: none; - color: white; - background-color: #3d3d3d; - cursor: pointer; - transition: background-color 100ms ease-in-out; -} - -.ChapterContainer button p { - font-family: "Atkinson Hyperlegible", serif; - margin: 2px; -} - -.ChapterContainer button:hover { - background-color: #1f1f1f; - transition: background-color 50ms ease-in -} - -.ChapterContainer button:focus { - opacity: 0.7; - transition: transform 0.2s linear; - background-color: var(--pastel-red); - transform: scale(0.9); -} - -@media screen and (max-width: 768px) { - .MangaInfoContainer { - max-width: 100%; - } - - .TitleContainer p { - font-size: 28px; - } - - .ChapterContainer button { - width: 120px; - - } - - .ChapterContainer button p { - font-size: 14px; - } - +.MangaInfoContainer {
+ margin: 68px auto;
+}
+
+.MangaHero {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+}
+
+.TitleContainer {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px;
+ background-color: #2c2c2c9c;
+ backdrop-filter: blur(5px);
+
+}
+
+.TitleContainer p {
+ font-family: "Lexend Deca", serif;
+ font-size: 40px;
+ font-weight: 1000;
+}
+
+.TitleContainer img {
+ border-radius: 10px;
+ margin-left: 5px;
+}
+
+.MangaDescription {
+ color: white;
+ font-family: "Atkinson Hyperlegible", serif;
+ max-width: 98%;
+ margin: -10px auto;
+}
+
+.Description h2 {
+ font-family: "Lexend Deca", serif;
+ color: gray;
+}
+
+.Description p {
+ margin-top: -10px;
+}
+
+.MangaReleaseYear {
+ margin-top: 10px;
+ font-family: "Poppins", serif;
+}
+
+.GenreContainer {
+ margin-top: 5px;
+ display: flex;
+ align-items: center;
+ font-family: "Poppins", serif;
+}
+
+.GenreText {
+ color: var(--neon-green);
+}
+
+.GenreContainer {
+ margin-top: 10px;
+}
+
+.genres {
+ display: flex;
+ align-items: center;
+ overflow-x: auto;
+}
+
+.MangaGenre {
+ background-color: #5f5f5f5d;
+ border-radius: 5px;
+ padding: 2px 5px;
+ cursor: pointer;
+ margin: 2px;
+}
+
+.MangaRatings {
+ display: flex;
+ margin-top: 10px;
+ font-family: "Poppins", serif;
+ /* justify-content: center; */
+}
+
+.MangaRatings span {
+ margin-right: 2px;
+ margin-left: 2px;
+ color: var(--light-green);
+}
+
+.CharactersContainer {
+ max-width: 98%;
+ margin: 20px auto;
+}
+
+.CharactersContainer h2 {
+ color: gray;
+ font-family: "Lexend Deca", serif;
+}
+
+.Character {
+ display: flex;
+ flex-direction: row;
+ overflow-x: auto;
+ margin-top: -10px;
+}
+
+.Character::-webkit-scrollbar {
+ height: 5px;
+}
+
+.Character::-webkit-scrollbar-thumb {
+ background-color: #31363F;
+ border-radius: 5px;
+}
+
+.CharacterEntry {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: auto;
+ margin: 5px;
+}
+
+.CharacterEntry p {
+ margin: 10px auto;
+ text-align: center;
+ width: 110px;
+ color: white;
+ font-family: "Atkinson Hyperlegible", serif;
+}
+
+.CharacterEntry img {
+ border-radius: 10px;
+}
+
+/* Chapters Buttons */
+
+.Chapters {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ max-width: 90%;
+ margin: 20px auto;
+}
+
+.ChapterTitle {
+ color: white;
+ font-family: "Lexend Deca", serif;
+ font-size: 32px;
+}
+
+.ChapterContainer {
+ width: 50dvw;
+ text-align: center;
+ height: 300px;
+ overflow-y: auto;
+}
+
+.ChapterContainer::-webkit-scrollbar {
+ width: 5px;
+ height: 0px;
+}
+
+.ChapterContainer::-webkit-scrollbar-thumb {
+ background-color: #31363F;
+ border-radius: 5px;
+}
+
+.ChapterContainer button {
+ width: 130px;
+ height: auto;
+ padding: 10px;
+ margin: 5px;
+ border-radius: 5px;
+ font-size: 16px;
+ border: none;
+ outline: none;
+ color: white;
+ background-color: #3d3d3d;
+ cursor: pointer;
+ transition: background-color 100ms ease-in-out;
+}
+
+.ChapterContainer button p {
+ font-family: "Atkinson Hyperlegible", serif;
+ margin: 2px;
+}
+
+.ChapterContainer button:hover {
+ background-color: #1f1f1f;
+ transition: background-color 50ms ease-in
+}
+
+.ChapterContainer button:focus {
+ opacity: 0.7;
+ transition: transform 0.2s linear;
+ background-color: var(--pastel-red);
+ transform: scale(0.9);
+}
+
+@media screen and (max-width: 768px) {
+ .MangaInfoContainer {
+ max-width: 100%;
+ }
+
+ .TitleContainer p {
+ font-size: 28px;
+ }
+
+ .ChapterContainer button {
+ width: 120px;
+
+ }
+
+ .ChapterContainer button p {
+ font-size: 14px;
+ }
+
}
\ No newline at end of file diff --git a/src/app/manga/[title]/[id]/page.jsx b/src/app/manga/[title]/[id]/page.jsx index d743f4d..ffd962d 100644 --- a/src/app/manga/[title]/[id]/page.jsx +++ b/src/app/manga/[title]/[id]/page.jsx @@ -1,136 +1,136 @@ -import styles from "./info.module.css"; -import Image from "next/image"; -import Buttons from "./buttons"; -import { redirect } from "next/navigation"; -import { FaStar } from "react-icons/fa"; -import { PreFetchChaterLinks } from "../../cacher"; - -export default async function MangaInfo({ params }) { - const id = params.id; - const data = await getMangaInfo(id); - - if (data.message) { - redirect("/404"); - } - - PreFetchChaterLinks(data.chapters); - - return ( - <div className={styles.MangaInfoContainer}> - {data && ( - <div className={styles.MangaInfo}> - <div - className={styles.MangaHero} - style={{ - backgroundImage: `url(${data.cover})`, - backgroundSize: "cover", - backgroundRepeat: "no-repeat", - borderRadius: 10, - }} - > - <div className={styles.TitleContainer}> - <p - style={{ - color: data.color, - borderRadius: 10, - padding: 5, - }} - > - {data.title["english"] || data.title["romaji"]} - </p> - <Image - src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${data.image}`} - width={200} - height={310} - alt="Manga Poster" - priority - /> - </div> - </div> - - <div className={styles.MangaDescription}> - <div className={styles.Description}> - <h2>Description</h2> - <p>{data.description.split("<br")[0]}</p> - </div> - - <div className={styles.MangaReleaseYear}> - <span style={{ color: "#A3FFD6" }}> - Started on: {data.startDate["day"]}- - {data.startDate["month"]}- - {data.startDate["year"]} - </span> - <span style={{ color: "white", margin: 10 }}> - | - </span> - <span style={{ color: "var(--pastel-red)" }}> - Ended on: {data.endDate["day"]}- - {data.endDate["month"]}-{data.endDate["year"]} - </span> - </div> - - <div className={styles.GenreContainer}> - <span className={styles.GenreText}>Genres: </span> - <div className={styles.genres}> - {data.genres && - data.genres.map((item, index) => ( - <span - key={index} - className={styles.MangaGenre} - > - {item} - </span> - ))} - </div> - </div> - - <div className={styles.MangaRatings}> - <span>Ratings: {data.rating / 10}</span> - <span> - <FaStar /> - </span> - </div> - </div> - - <div className={styles.CharactersContainer}> - <h2>Characters</h2> - <div className={styles.Character}> - {data.characters && - data.characters.map((item, index) => ( - <div - key={index} - className={styles.CharacterEntry} - > - <Image - src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${item.image}`} - width={140} - height={200} - alt="Character Poster" - /> - <p> - {item.name.full} ({item.role}) - </p> - </div> - ))} - </div> - </div> - <div className={styles.Chapters}> - <p className={styles.ChapterTitle}> - Chapters & Volumes - </p> - <Buttons content={data} /> - </div> - </div> - )} - </div> - ); -} - -async function getMangaInfo(id) { - const res = await fetch( - `https://consumet-jade.vercel.app/meta/anilist-manga/info/${id}?provider=mangadex`, - { next: { revalidate: 86400 } } - ); - const data = await res.json(); - return data; -} +import styles from "./info.module.css";
+import Image from "next/image";
+import Buttons from "./buttons";
+import { redirect } from "next/navigation";
+import { FaStar } from "react-icons/fa";
+import { PreFetchChaterLinks } from "../../cacher";
+
+export default async function MangaInfo({ params }) {
+ const id = params.id;
+ const data = await getMangaInfo(id);
+
+ if (data.message) {
+ redirect("/404");
+ }
+
+ PreFetchChaterLinks(data.chapters);
+
+ return (
+ <div className={styles.MangaInfoContainer}>
+ {data && (
+ <div className={styles.MangaInfo}>
+ <div
+ className={styles.MangaHero}
+ style={{
+ backgroundImage: `url(${data.cover})`,
+ backgroundSize: "cover",
+ backgroundRepeat: "no-repeat",
+ borderRadius: 10,
+ }}
+ >
+ <div className={styles.TitleContainer}>
+ <p
+ style={{
+ color: data.color,
+ borderRadius: 10,
+ padding: 5,
+ }}
+ >
+ {data.title["english"] || data.title["romaji"]}
+ </p>
+ <Image
+ src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${data.image}`}
+ width={200}
+ height={310}
+ alt="Manga Poster"
+ priority
+ />
+ </div>
+ </div>
+
+ <div className={styles.MangaDescription}>
+ <div className={styles.Description}>
+ <h2>Description</h2>
+ <p>{data.description.split("<br")[0]}</p>
+ </div>
+
+ <div className={styles.MangaReleaseYear}>
+ <span style={{ color: "#A3FFD6" }}>
+ Started on: {data.startDate["day"]}-
+ {data.startDate["month"]}-
+ {data.startDate["year"]}
+ </span>
+ <span style={{ color: "white", margin: 10 }}>
+ |
+ </span>
+ <span style={{ color: "var(--pastel-red)" }}>
+ Ended on: {data.endDate["day"]}-
+ {data.endDate["month"]}-{data.endDate["year"]}
+ </span>
+ </div>
+
+ <div className={styles.GenreContainer}>
+ <span className={styles.GenreText}>Genres: </span>
+ <div className={styles.genres}>
+ {data.genres &&
+ data.genres.map((item, index) => (
+ <span
+ key={index}
+ className={styles.MangaGenre}
+ >
+ {item}
+ </span>
+ ))}
+ </div>
+ </div>
+
+ <div className={styles.MangaRatings}>
+ <span>Ratings: {data.rating / 10}</span>
+ <span>
+ <FaStar />
+ </span>
+ </div>
+ </div>
+
+ <div className={styles.CharactersContainer}>
+ <h2>Characters</h2>
+ <div className={styles.Character}>
+ {data.characters &&
+ data.characters.map((item, index) => (
+ <div
+ key={index}
+ className={styles.CharacterEntry}
+ >
+ <Image
+ src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${item.image}`}
+ width={140}
+ height={200}
+ alt="Character Poster"
+ />
+ <p>
+ {item.name.full} ({item.role})
+ </p>
+ </div>
+ ))}
+ </div>
+ </div>
+ <div className={styles.Chapters}>
+ <p className={styles.ChapterTitle}>
+ Chapters & Volumes
+ </p>
+ <Buttons content={data} />
+ </div>
+ </div>
+ )}
+ </div>
+ );
+}
+
+async function getMangaInfo(id) {
+ const res = await fetch(
+ `https://consumet-jade.vercel.app/meta/anilist-manga/info/${id}?provider=mangadex`,
+ { next: { revalidate: 86400 } }
+ );
+ const data = await res.json();
+ return data;
+}
diff --git a/src/app/manga/[title]/page.jsx b/src/app/manga/[title]/page.jsx index 589ff53..4446d05 100644 --- a/src/app/manga/[title]/page.jsx +++ b/src/app/manga/[title]/page.jsx @@ -1,78 +1,78 @@ -import styles from "./title.module.css"; -import Image from "next/image"; -import Link from "next/link"; -import { PreFetchMangaInfo } from "../cacher"; - -// This page displays all the available mangas or manhwas when the user searches for one/ - -export default async function MangaInfo({ params }) { - const title = params.title; - const data = await GetSearchedAnime(title); - - PreFetchMangaInfo(data); - - return ( - <div className={styles.Main}> - <div className={styles.MangaContainer}> - {title && ( - <div className={styles.SearchedFor}> - <p>Searched for: {decodeURIComponent(title)}</p> - </div> - )} - {data && - data.results.map(async (item, index) => { - let desc = item.description || ""; // Ensure desc is not null - if (desc === "") { - desc = "Not found"; // If desc is empty, set it to "Not found" - } - return ( - <Link - href={`./info/${item.id}`} - style={{ textDecoration: "none" }} - key={index} - > - <div className={styles.MangaEntries}> - <Image - src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${item.image}`} - width={160} - height={250} - alt="Manga Poster" - style={{ borderRadius: 10 }} - /> - <div className={styles.MangaInfo}> - <p className={styles.MangaTitle}> - {item.title["english"] || - item.title["romaji"]} - </p> - <p className={styles.MangaDescription}> - {desc.includes && - desc.includes("<br") - ? desc.split("<b")[0] - : desc} - </p> - <p className={styles.MangaStatus}> - {item.status} - </p> - <p className={styles.MangaChapters}> - Chapters: {item.totalChapters} - </p> - <p className={styles.MangaVolume}> - Volumes: {item.volumes} - </p> - </div> - </div> - </Link> - ); - })} - </div> - </div> - ); -} - -async function GetSearchedAnime(title) { - const res = await fetch( - "https://consumet-jade.vercel.app/meta/anilist-manga/" + title - ); - const data = await res.json(); - return data; -} +import styles from "./title.module.css";
+import Image from "next/image";
+import Link from "next/link";
+import { PreFetchMangaInfo } from "../cacher";
+
+// This page displays all the available mangas or manhwas when the user searches for one/
+
+export default async function MangaInfo({ params }) {
+ const title = params.title;
+ const data = await GetSearchedAnime(title);
+
+ PreFetchMangaInfo(data);
+
+ return (
+ <div className={styles.Main}>
+ <div className={styles.MangaContainer}>
+ {title && (
+ <div className={styles.SearchedFor}>
+ <p>Searched for: {decodeURIComponent(title)}</p>
+ </div>
+ )}
+ {data &&
+ data.results.map(async (item, index) => {
+ let desc = item.description || ""; // Ensure desc is not null
+ if (desc === "") {
+ desc = "Not found"; // If desc is empty, set it to "Not found"
+ }
+ return (
+ <Link
+ href={`./info/${item.id}`}
+ style={{ textDecoration: "none" }}
+ key={index}
+ >
+ <div className={styles.MangaEntries}>
+ <Image
+ src={`https://sup-proxy.zephex0-f6c.workers.dev/api-content?url=${item.image}`}
+ width={160}
+ height={250}
+ alt="Manga Poster"
+ style={{ borderRadius: 10 }}
+ />
+ <div className={styles.MangaInfo}>
+ <p className={styles.MangaTitle}>
+ {item.title["english"] ||
+ item.title["romaji"]}
+ </p>
+ <p className={styles.MangaDescription}>
+ {desc.includes &&
+ desc.includes("<br")
+ ? desc.split("<b")[0]
+ : desc}
+ </p>
+ <p className={styles.MangaStatus}>
+ {item.status}
+ </p>
+ <p className={styles.MangaChapters}>
+ Chapters: {item.totalChapters}
+ </p>
+ <p className={styles.MangaVolume}>
+ Volumes: {item.volumes}
+ </p>
+ </div>
+ </div>
+ </Link>
+ );
+ })}
+ </div>
+ </div>
+ );
+}
+
+async function GetSearchedAnime(title) {
+ const res = await fetch(
+ "https://consumet-jade.vercel.app/meta/anilist-manga/" + title
+ );
+ const data = await res.json();
+ return data;
+}
diff --git a/src/app/manga/[title]/title.module.css b/src/app/manga/[title]/title.module.css index e7842d5..737fd92 100644 --- a/src/app/manga/[title]/title.module.css +++ b/src/app/manga/[title]/title.module.css @@ -1,75 +1,75 @@ -.Main { - max-width: 95%; - margin: 60px auto; -} - -.MangaContainer { - display: flex; - flex-direction: column; -} - -.SearchedFor { - color: white; - text-align: center; - font-family: "Lexend Deca", serif; - font-size: 26px; -} - -.MangaEntries { - display: flex; - flex-direction: row; - margin: 0px 10px 10px 10px; - padding: 10px; - border-style: dotted; - border-color: #363636 #474747; - border-radius: 10px; - border-width: 4px; - align-items: center; - cursor: pointer; - transition: opacity 200ms linear, transform 200ms linear; -} - -/* THIS WORKS*/ -.MangaContainer:hover .MangaEntries { - opacity: 0.5; -} - -.MangaContainer:hover .MangaEntries:hover { - opacity: 1; - transform: scale(1.01); -} - -.MangaInfo { - color: white; - margin-left: 20px; - font-family: "Atkinson Hyperlegible"; -} - -.MangaTitle { - font-family: "Lexend Deca", serif; - margin: 0px; - font-size: 22px; - color: var(--neon-green); -} - -.MangaStatus { - color: var(--soft-purple); - font-family: "Poppins", serif; - -} - -.MangaVolume { - color: #FFACAC; - font-family: "Poppins", serif; -} - -.MangaChapters { - color: #FFEBB4; - font-family: "Poppins", serif; -} - -@media screen and (max-width: 768px) { - .Main { - max-width: 100%; - } +.Main {
+ max-width: 95%;
+ margin: 60px auto;
+}
+
+.MangaContainer {
+ display: flex;
+ flex-direction: column;
+}
+
+.SearchedFor {
+ color: white;
+ text-align: center;
+ font-family: "Lexend Deca", serif;
+ font-size: 26px;
+}
+
+.MangaEntries {
+ display: flex;
+ flex-direction: row;
+ margin: 0px 10px 10px 10px;
+ padding: 10px;
+ border-style: dotted;
+ border-color: #363636 #474747;
+ border-radius: 10px;
+ border-width: 4px;
+ align-items: center;
+ cursor: pointer;
+ transition: opacity 200ms linear, transform 200ms linear;
+}
+
+/* THIS WORKS*/
+.MangaContainer:hover .MangaEntries {
+ opacity: 0.5;
+}
+
+.MangaContainer:hover .MangaEntries:hover {
+ opacity: 1;
+ transform: scale(1.01);
+}
+
+.MangaInfo {
+ color: white;
+ margin-left: 20px;
+ font-family: "Atkinson Hyperlegible";
+}
+
+.MangaTitle {
+ font-family: "Lexend Deca", serif;
+ margin: 0px;
+ font-size: 22px;
+ color: var(--neon-green);
+}
+
+.MangaStatus {
+ color: var(--soft-purple);
+ font-family: "Poppins", serif;
+
+}
+
+.MangaVolume {
+ color: #FFACAC;
+ font-family: "Poppins", serif;
+}
+
+.MangaChapters {
+ color: #FFEBB4;
+ font-family: "Poppins", serif;
+}
+
+@media screen and (max-width: 768px) {
+ .Main {
+ max-width: 100%;
+ }
}
\ No newline at end of file diff --git a/src/app/manga/cacher.js b/src/app/manga/cacher.js index 7f047ab..6059674 100644 --- a/src/app/manga/cacher.js +++ b/src/app/manga/cacher.js @@ -1,32 +1,32 @@ -// This function pre-fetches all the chapter pages links for a manga in the background -"use server"; - -export async function PreFetchChaterLinks(data) { - try { - const fetchPromises = data.map(async (element) => { - const link = `https://consumet-jade.vercel.app/meta/anilist-manga/read?chapterId=${element.id}&provider=mangadex`; - await fetch(link, { cache: "force-cache" }); - }); - - await Promise.all(fetchPromises); - console.log("Chapter links pre-fetched successfully!"); - } catch (error) { - console.error( - "Error occurred while pre-fetching chapter links:", - error - ); - } -} - -export async function PreFetchMangaInfo(data) { - try { - const fetchPromises = data.results.map(async (element) => { - const link = `https://consumet-jade.vercel.app/meta/anilist-manga/${element.id}?provider=mangadex`; - await fetch(link, { next: { revalidate: 86400 } }); - }); - await Promise.all(fetchPromises); - console.log("Manga info pre-fetched successfully!"); - } catch (error) { - console.error("error", error); - } -} +// This function pre-fetches all the chapter pages links for a manga in the background
+"use server";
+
+export async function PreFetchChaterLinks(data) {
+ try {
+ const fetchPromises = data.map(async (element) => {
+ const link = `https://consumet-jade.vercel.app/meta/anilist-manga/read?chapterId=${element.id}&provider=mangadex`;
+ await fetch(link, { cache: "force-cache" });
+ });
+
+ await Promise.all(fetchPromises);
+ console.log("Chapter links pre-fetched successfully!");
+ } catch (error) {
+ console.error(
+ "Error occurred while pre-fetching chapter links:",
+ error
+ );
+ }
+}
+
+export async function PreFetchMangaInfo(data) {
+ try {
+ const fetchPromises = data.results.map(async (element) => {
+ const link = `https://consumet-jade.vercel.app/meta/anilist-manga/${element.id}?provider=mangadex`;
+ await fetch(link, { next: { revalidate: 86400 } });
+ });
+ await Promise.all(fetchPromises);
+ console.log("Manga info pre-fetched successfully!");
+ } catch (error) {
+ console.error("error", error);
+ }
+}
diff --git a/src/app/manga/history/continueWatching/cw.module.css b/src/app/manga/history/continueWatching/cw.module.css index 3641e84..645f45a 100644 --- a/src/app/manga/history/continueWatching/cw.module.css +++ b/src/app/manga/history/continueWatching/cw.module.css @@ -1,75 +1,75 @@ -.main { - width: 99%; - margin: 80px auto; -} - -.mainText { - color: var(--light-green); - font-family: "Poppins", serif; - font-size: 24px; -} - -.animeContainer { - font-family: "Poppins", serif; - font-size: 18px; - margin: 0px; -} - -.animeEntry { - display: flex; - align-items: center; - justify-content: space-between; - padding: 5px; - margin-bottom: 0.5rem; - border-radius: 1rem; - background-color: #1f1f1f; -} - -.animeEntry img { - width: auto; - height: auto; - max-height: 40dvh; - border-radius: 0.8rem; -} - -.titleContainer { - color: white; - margin-left: 0.2rem; -} - -.titleContainer h3 { - margin: 0px; -} - -.EpisodeCount { - color: var(--soft-purple); - margin: 0px; -} - -.date { - color: var(--neon-yellow); - margin: 0px; -} - -.redirects { - margin: 5px 0 0 0; -} - -.redirects button { - outline: none; - border: none; - margin-right: 0.4rem; - border-radius: 0.2rem; - padding: 0.2rem; - font-family: "Atkinson Hyperlegible", serif; - background-color: #303030; - color: white; - cursor: pointer; -} - -@media screen and (max-width: 768px) { - .animeContainer { - font-size: 14px; - - } +.main {
+ width: 99%;
+ margin: 80px auto;
+}
+
+.mainText {
+ color: var(--light-green);
+ font-family: "Poppins", serif;
+ font-size: 24px;
+}
+
+.animeContainer {
+ font-family: "Poppins", serif;
+ font-size: 18px;
+ margin: 0px;
+}
+
+.animeEntry {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 5px;
+ margin-bottom: 0.5rem;
+ border-radius: 1rem;
+ background-color: #1f1f1f;
+}
+
+.animeEntry img {
+ width: auto;
+ height: auto;
+ max-height: 40dvh;
+ border-radius: 0.8rem;
+}
+
+.titleContainer {
+ color: white;
+ margin-left: 0.2rem;
+}
+
+.titleContainer h3 {
+ margin: 0px;
+}
+
+.EpisodeCount {
+ color: var(--soft-purple);
+ margin: 0px;
+}
+
+.date {
+ color: var(--neon-yellow);
+ margin: 0px;
+}
+
+.redirects {
+ margin: 5px 0 0 0;
+}
+
+.redirects button {
+ outline: none;
+ border: none;
+ margin-right: 0.4rem;
+ border-radius: 0.2rem;
+ padding: 0.2rem;
+ font-family: "Atkinson Hyperlegible", serif;
+ background-color: #303030;
+ color: white;
+ cursor: pointer;
+}
+
+@media screen and (max-width: 768px) {
+ .animeContainer {
+ font-size: 14px;
+
+ }
}
\ No newline at end of file diff --git a/src/app/manga/history/continueWatching/page.jsx b/src/app/manga/history/continueWatching/page.jsx index 0d0a02e..92cc27e 100644 --- a/src/app/manga/history/continueWatching/page.jsx +++ b/src/app/manga/history/continueWatching/page.jsx @@ -1,70 +1,70 @@ -"use client"; - -import React, { useState, useEffect } from "react"; -import Image from "next/image"; -import styles from "./cw.module.css"; -import Link from "next/link"; - -const ContinueWatching = () => { - const [localItems, setLocalItems] = useState(null); - - useEffect(() => { - const newData = get_local(); - setLocalItems(newData); - }, []); // Empty dependency array means this effect runs only once after the initial render - - function get_local() { - try { - const data = localStorage.getItem("mangaData"); - return JSON.parse(data); - } catch (error) { - console.log("error", error); - return false; - } - } - - return ( - <main className={styles.main}> - <p className={styles.mainText}>Continue Watching</p> - {localItems && ( - <div className={styles.animeContainer}> - {localItems.watchHis && - localItems.watchHis.map((item, index) => ( - <div key={index} className={styles.animeEntry}> - <div className={styles.titleContainer}> - <h3>{item.title}</h3> - <p className={styles.EpisodeCount}> - Currently reading: Volume {item.volume}{" "} - Chapter {item.chapter} - </p> - <div className={styles.redirects}> - <Link - href={`/manga/info/${item.mangaId}`} - > - <button>Info Page</button> - </Link> - <Link - href={`/manga/info/read/${item.id}`} - > - <button> - Read current chapter - </button> - </Link> - </div> - </div> - <Image - src={item.image} - width={140} - height={210} - alt="Continue anime poster" - priority - /> - </div> - ))} - </div> - )} - </main> - ); -}; - -export default ContinueWatching; +"use client";
+
+import React, { useState, useEffect } from "react";
+import Image from "next/image";
+import styles from "./cw.module.css";
+import Link from "next/link";
+
+const ContinueWatching = () => {
+ const [localItems, setLocalItems] = useState(null);
+
+ useEffect(() => {
+ const newData = get_local();
+ setLocalItems(newData);
+ }, []); // Empty dependency array means this effect runs only once after the initial render
+
+ function get_local() {
+ try {
+ const data = localStorage.getItem("mangaData");
+ return JSON.parse(data);
+ } catch (error) {
+ console.log("error", error);
+ return false;
+ }
+ }
+
+ return (
+ <main className={styles.main}>
+ <p className={styles.mainText}>Continue Watching</p>
+ {localItems && (
+ <div className={styles.animeContainer}>
+ {localItems.watchHis &&
+ localItems.watchHis.map((item, index) => (
+ <div key={index} className={styles.animeEntry}>
+ <div className={styles.titleContainer}>
+ <h3>{item.title}</h3>
+ <p className={styles.EpisodeCount}>
+ Currently reading: Volume {item.volume}{" "}
+ Chapter {item.chapter}
+ </p>
+ <div className={styles.redirects}>
+ <Link
+ href={`/manga/info/${item.mangaId}`}
+ >
+ <button>Info Page</button>
+ </Link>
+ <Link
+ href={`/manga/info/read/${item.id}`}
+ >
+ <button>
+ Read current chapter
+ </button>
+ </Link>
+ </div>
+ </div>
+ <Image
+ src={item.image}
+ width={140}
+ height={210}
+ alt="Continue anime poster"
+ priority
+ />
+ </div>
+ ))}
+ </div>
+ )}
+ </main>
+ );
+};
+
+export default ContinueWatching;
diff --git a/src/app/manga/history/storeData.js b/src/app/manga/history/storeData.js index 1fd7607..8d82a97 100644 --- a/src/app/manga/history/storeData.js +++ b/src/app/manga/history/storeData.js @@ -1,28 +1,28 @@ -"use client"; - -export function storeLocal(watchData) { - const jsonData = localStorage.getItem("mangaData"); - const dataObject = jsonData ? JSON.parse(jsonData) : {}; - - if (!dataObject.watchHis) { - dataObject.watchHis = []; - } - - let found = false; - dataObject.watchHis.forEach((element) => { - if (element.title === watchData.title) { - let chapter = watchData.chapter; - let volume = watchData.volume; - element.chapter = chapter; - element.volume = volume; - found = true; - } - }); - - if (!found) { - dataObject.watchHis.push(watchData); - } - - let updatedData = JSON.stringify(dataObject); - localStorage.setItem("mangaData", updatedData); -} +"use client";
+
+export function storeLocal(watchData) {
+ const jsonData = localStorage.getItem("mangaData");
+ const dataObject = jsonData ? JSON.parse(jsonData) : {};
+
+ if (!dataObject.watchHis) {
+ dataObject.watchHis = [];
+ }
+
+ let found = false;
+ dataObject.watchHis.forEach((element) => {
+ if (element.title === watchData.title) {
+ let chapter = watchData.chapter;
+ let volume = watchData.volume;
+ element.chapter = chapter;
+ element.volume = volume;
+ found = true;
+ }
+ });
+
+ if (!found) {
+ dataObject.watchHis.push(watchData);
+ }
+
+ let updatedData = JSON.stringify(dataObject);
+ localStorage.setItem("mangaData", updatedData);
+}
diff --git a/src/app/manga/loading.jsx b/src/app/manga/loading.jsx index 8f7f837..f96f0dc 100644 --- a/src/app/manga/loading.jsx +++ b/src/app/manga/loading.jsx @@ -1,9 +1,9 @@ -import styles from "./loading.module.css"; - -export default function Loading() { - return ( - <div className={styles.Main}> - <div className={styles.LoadingContainer}></div> - </div> - ); -} +import styles from "./loading.module.css";
+
+export default function Loading() {
+ return (
+ <div className={styles.Main}>
+ <div className={styles.LoadingContainer}></div>
+ </div>
+ );
+}
diff --git a/src/app/manga/loading.module.css b/src/app/manga/loading.module.css index 148d8b8..18b1cf0 100644 --- a/src/app/manga/loading.module.css +++ b/src/app/manga/loading.module.css @@ -1,22 +1,22 @@ -.Main { - height: 100dvh; - width: 100dvw; - display: flex; - justify-content: center; - align-items: center; -} - -.LoadingContainer { - width: 50px; - height: 50px; - border-radius: 50%; - border: 8px solid; - border-color: #F4F4F4 #0000; - animation: s1 1s infinite; -} - -@keyframes s1 { - to { - transform: rotate(.5turn) - } +.Main {
+ height: 100dvh;
+ width: 100dvw;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.LoadingContainer {
+ width: 50px;
+ height: 50px;
+ border-radius: 50%;
+ border: 8px solid;
+ border-color: #F4F4F4 #0000;
+ animation: s1 1s infinite;
+}
+
+@keyframes s1 {
+ to {
+ transform: rotate(.5turn)
+ }
}
\ No newline at end of file diff --git a/src/app/manga/manga.module.css b/src/app/manga/manga.module.css index 8dd72d0..9124198 100644 --- a/src/app/manga/manga.module.css +++ b/src/app/manga/manga.module.css @@ -1,63 +1,63 @@ -.Main { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100dvh; - width: 100dvw; -} - -.MangaSVG { - height: auto; - width: auto; -} - -.searchMain { - display: flex; - align-items: center; -} - -.searchMain button { - margin: 10px 5px 0px 5px; - padding: 4px; - border-radius: 0.3rem; - border: none; - outline: none; - font-family: "Atkinson Hyperlegible", serif; - background: #1f1f1f; - color: white; -} - -.SearchBar { - display: flex; - align-items: center; - background: #1f1f1f; - margin-top: 10px; - border-style: dotted; - border-color: rgb(63, 63, 63); - border-width: 2px; - width: 20dvw; - border-radius: 1rem; -} - -.SearchBar input { - background: none; - outline: none; - border: none; - margin-left: 5px; - padding: 4px; - width: 100%; - color: white; - font-family: "Lexend Deca", serif; - font-size: 16px; -} - -@media screen and (max-width: 768px) { - .MangaSVG { - width: 100%; - } - - .SearchBar { - width: 50dvw; - } +.Main {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 100dvh;
+ width: 100dvw;
+}
+
+.MangaSVG {
+ height: auto;
+ width: auto;
+}
+
+.searchMain {
+ display: flex;
+ align-items: center;
+}
+
+.searchMain button {
+ margin: 10px 5px 0px 5px;
+ padding: 4px;
+ border-radius: 0.3rem;
+ border: none;
+ outline: none;
+ font-family: "Atkinson Hyperlegible", serif;
+ background: #1f1f1f;
+ color: white;
+}
+
+.SearchBar {
+ display: flex;
+ align-items: center;
+ background: #1f1f1f;
+ margin-top: 10px;
+ border-style: dotted;
+ border-color: rgb(63, 63, 63);
+ border-width: 2px;
+ width: 20dvw;
+ border-radius: 1rem;
+}
+
+.SearchBar input {
+ background: none;
+ outline: none;
+ border: none;
+ margin-left: 5px;
+ padding: 4px;
+ width: 100%;
+ color: white;
+ font-family: "Lexend Deca", serif;
+ font-size: 16px;
+}
+
+@media screen and (max-width: 768px) {
+ .MangaSVG {
+ width: 100%;
+ }
+
+ .SearchBar {
+ width: 50dvw;
+ }
}
\ No newline at end of file diff --git a/src/app/manga/page.jsx b/src/app/manga/page.jsx index bab74a7..a7b3cde 100644 --- a/src/app/manga/page.jsx +++ b/src/app/manga/page.jsx @@ -1,20 +1,20 @@ -import styles from "./manga.module.css"; -import Image from "next/image"; -import SearchBar from "./searchBar"; - -// This is the landing page for the manga section. Nothing much here but my only complaint is the loading time for the svg. It's too big but idk how to fix it. I mean I could use a png but then the quality is not good. Will keep it like this for the time being - -export default async function Manga() { - return ( - <div className={styles.Main}> - <Image - src="/manga.svg" - width={480} - height={200} - className={styles.MangaSVG} - alt="Manga SVG" - /> - <SearchBar /> - </div> - ); -} +import styles from "./manga.module.css";
+import Image from "next/image";
+import SearchBar from "./searchBar";
+
+// This is the landing page for the manga section. Nothing much here but my only complaint is the loading time for the svg. It's too big but idk how to fix it. I mean I could use a png but then the quality is not good. Will keep it like this for the time being
+
+export default async function Manga() {
+ return (
+ <div className={styles.Main}>
+ <Image
+ src="/manga.svg"
+ width={480}
+ height={200}
+ className={styles.MangaSVG}
+ alt="Manga SVG"
+ />
+ <SearchBar />
+ </div>
+ );
+}
diff --git a/src/app/manga/searchBar.jsx b/src/app/manga/searchBar.jsx index bffb957..763f383 100644 --- a/src/app/manga/searchBar.jsx +++ b/src/app/manga/searchBar.jsx @@ -1,45 +1,45 @@ -"use client"; - -import { FaSearch } from "react-icons/fa"; -import styles from "./manga.module.css"; -import { useState } from "react"; -import { useRouter } from "next/navigation"; -import Link from "next/link"; - -// This is the search bar for the mangapage. Nothing extraordinary but just an input box and a search icon. Gets the work done. - -export default function SearchBar() { - const router = useRouter(); - - const [title, setMangaTitle] = useState(""); - - return ( - <main className={styles.searchMain}> - <div className={styles.SearchBar}> - <FaSearch color="white" style={{ marginLeft: 5 }} /> - <input - type="text" - name="manga" - placeholder="Enter manga title" - autoComplete="off" - onChange={(e) => setMangaTitle(e.target.value)} - onKeyDown={(event) => { - if ( - (event.key === "Enter" || - event.code === 13 || - event.code === "Enter") && - title !== "" - ) { - router.push(`/manga/${title}`); - } - }} - ></input> - </div> - <div> - <Link href={"/manga/history/continueWatching/"}> - <button>History</button> - </Link> - </div> - </main> - ); -} +"use client";
+
+import { FaSearch } from "react-icons/fa";
+import styles from "./manga.module.css";
+import { useState } from "react";
+import { useRouter } from "next/navigation";
+import Link from "next/link";
+
+// This is the search bar for the mangapage. Nothing extraordinary but just an input box and a search icon. Gets the work done.
+
+export default function SearchBar() {
+ const router = useRouter();
+
+ const [title, setMangaTitle] = useState("");
+
+ return (
+ <main className={styles.searchMain}>
+ <div className={styles.SearchBar}>
+ <FaSearch color="white" style={{ marginLeft: 5 }} />
+ <input
+ type="text"
+ name="manga"
+ placeholder="Enter manga title"
+ autoComplete="off"
+ onChange={(e) => setMangaTitle(e.target.value)}
+ onKeyDown={(event) => {
+ if (
+ (event.key === "Enter" ||
+ event.code === 13 ||
+ event.code === "Enter") &&
+ title !== ""
+ ) {
+ router.push(`/manga/${title}`);
+ }
+ }}
+ ></input>
+ </div>
+ <div>
+ <Link href={"/manga/history/continueWatching/"}>
+ <button>History</button>
+ </Link>
+ </div>
+ </main>
+ );
+}
diff --git a/src/app/page.module.css b/src/app/page.module.css index 3a7031f..7524dea 100644 --- a/src/app/page.module.css +++ b/src/app/page.module.css @@ -1,109 +1,109 @@ -.newbg { - background: rgb(37, 37, 37); - background: radial-gradient(circle, rgb(41, 41, 41) 2%, rgb(12, 12, 12) 30%); -} - -.header { - position: fixed; - top: 0; - width: 100%; - display: flex; - align-items: center; - justify-content: space-between; - background-color: #121212; - font-family: "Lexend Deca", serif; - z-index: 2; -} - -.left { - color: white; - font-size: 24px; -} - -.left p { - margin: 0; - padding: 1rem; -} - -.right a { - text-decoration: none; - color: white; - margin: 0 0.4rem 0 0.5rem; - transition: opacity 400ms ease; - font-size: 16px; -} - -.header:hover>.right a { - opacity: 0.5; -} - -.header:hover>.right a:hover { - opacity: 1; - cursor: pointer; -} - -.footer { - bottom: 0; - width: 100%; - position: fixed; - background-color: #121212; - color: white; - font-family: "Poppins", serif; - z-index: 2; -} - -.footer p { - text-align: center; - font-size: 14px; - margin: 0; - padding: 0.6rem; - font-family: "Poppins", serif; -} - -.content { - height: 100vh; - display: flex; - align-items: center; - justify-content: center; -} - -.contentContainer { - display: block; -} - -.contentContainer a { - text-decoration: none; - color: white; -} - -.manga, -.anime, -.kdrama { - background-color: #121212e0; - color: white; - margin-top: 5px; - border-radius: 5px; - transition: opacity 400ms ease; - padding: 0.4rem 2rem; - font-family: "Lexend Deca", serif; -} - -.content:hover>.contentContainer div { - opacity: 0.5; -} - -.content:hover>.contentContainer div:hover { - opacity: 1; - cursor: pointer; -} - -.netlifyLogo { - position: fixed; - bottom: 0; - margin: 0rem 0.4rem 1rem 0.4rem; - height: 8.2rem; -} - -.netlifyLogo img { - aspect-ratio: 16 / 9; +.newbg {
+ background: rgb(37, 37, 37);
+ background: radial-gradient(circle, rgb(41, 41, 41) 2%, rgb(12, 12, 12) 30%);
+}
+
+.header {
+ position: fixed;
+ top: 0;
+ width: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ background-color: #121212;
+ font-family: "Lexend Deca", serif;
+ z-index: 2;
+}
+
+.left {
+ color: white;
+ font-size: 24px;
+}
+
+.left p {
+ margin: 0;
+ padding: 1rem;
+}
+
+.right a {
+ text-decoration: none;
+ color: white;
+ margin: 0 0.4rem 0 0.5rem;
+ transition: opacity 400ms ease;
+ font-size: 16px;
+}
+
+.header:hover>.right a {
+ opacity: 0.5;
+}
+
+.header:hover>.right a:hover {
+ opacity: 1;
+ cursor: pointer;
+}
+
+.footer {
+ bottom: 0;
+ width: 100%;
+ position: fixed;
+ background-color: #121212;
+ color: white;
+ font-family: "Poppins", serif;
+ z-index: 2;
+}
+
+.footer p {
+ text-align: center;
+ font-size: 14px;
+ margin: 0;
+ padding: 0.6rem;
+ font-family: "Poppins", serif;
+}
+
+.content {
+ height: 100vh;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.contentContainer {
+ display: block;
+}
+
+.contentContainer a {
+ text-decoration: none;
+ color: white;
+}
+
+.manga,
+.anime,
+.kdrama {
+ background-color: #121212e0;
+ color: white;
+ margin-top: 5px;
+ border-radius: 5px;
+ transition: opacity 400ms ease;
+ padding: 0.4rem 2rem;
+ font-family: "Lexend Deca", serif;
+}
+
+.content:hover>.contentContainer div {
+ opacity: 0.5;
+}
+
+.content:hover>.contentContainer div:hover {
+ opacity: 1;
+ cursor: pointer;
+}
+
+.netlifyLogo {
+ position: fixed;
+ bottom: 0;
+ margin: 0rem 0.4rem 1rem 0.4rem;
+ height: 8.2rem;
+}
+
+.netlifyLogo img {
+ aspect-ratio: 16 / 9;
}
\ No newline at end of file |