aboutsummaryrefslogtreecommitdiff
path: root/pages/manga
diff options
context:
space:
mode:
authorFactiven <[email protected]>2023-04-11 23:23:29 +0700
committerFactiven <[email protected]>2023-04-11 23:23:29 +0700
commit1fcdd9f7d859b925bf92265f441655d5522e351c (patch)
tree86391522f6fcc70d105f7e796a9f91d132ee4a29 /pages/manga
parentInitial commit (diff)
downloadmoopa-1fcdd9f7d859b925bf92265f441655d5522e351c.tar.xz
moopa-1fcdd9f7d859b925bf92265f441655d5522e351c.zip
initial commit
Diffstat (limited to 'pages/manga')
-rw-r--r--pages/manga/chapter/[chapter].js423
-rw-r--r--pages/manga/detail/id.js318
2 files changed, 741 insertions, 0 deletions
diff --git a/pages/manga/chapter/[chapter].js b/pages/manga/chapter/[chapter].js
new file mode 100644
index 0000000..8d2a5a1
--- /dev/null
+++ b/pages/manga/chapter/[chapter].js
@@ -0,0 +1,423 @@
+import axios from "axios";
+import Head from "next/head";
+import { useEffect, useState } from "react";
+import Navbar from "../../../components/navbar";
+import Footer from "../../../components/footer";
+import ScrollTracker from "../../../components/scrollTracker";
+
+export default function Test({ title, id, aniId, data, provider }) {
+ const [isLoading, setIsLoading] = useState(true);
+ const [datas, setData] = useState(data);
+ const [currentChapter, setCurrentChapter] = useState(null);
+ const [nextChapter, setNextChapter] = useState(null);
+ const [prevChapter, setPrevChapter] = useState(null);
+
+ useEffect(() => {
+ function storedData() {
+ const nowChap = localStorage.getItem("currentChapterId");
+ const chapt = localStorage.getItem("chapters");
+ const chapters = JSON.parse(chapt);
+ const currentChapter = chapters.find((chapter) => chapter.id === nowChap);
+ const currentIndex = chapters.findIndex(
+ (chapter) => chapter.id === nowChap
+ );
+
+ const nextIndex = currentIndex + 1;
+
+ const nextChapter = chapters[nextIndex];
+ const prevIndex = currentIndex - 1;
+
+ setNextChapter(nextChapter);
+ setCurrentChapter(currentChapter);
+ setPrevChapter(chapters[prevIndex]);
+ setIsLoading(false);
+ }
+ storedData();
+ }, []);
+
+ function getNextChapter() {
+ window.scrollTo(0, 0);
+ setIsLoading(true);
+ const currentId = localStorage.getItem("currentChapterId");
+ const scrollData = JSON.parse(localStorage.getItem("watchedManga")) || [];
+ const scroll = localStorage.getItem("scrollPercentage");
+ if (scroll >= 5) {
+ const existingDataIndex = scrollData.findIndex(
+ (data) => data.id === currentId
+ );
+ if (existingDataIndex !== -1) {
+ // Update existing data
+ scrollData[existingDataIndex].timestamp = Date.now();
+ scrollData[existingDataIndex].percentage = parseFloat(
+ localStorage.getItem("scrollPercentage")
+ );
+ } else {
+ // Add new data
+ scrollData.push({
+ timestamp: Date.now(),
+ percentage: parseFloat(localStorage.getItem("scrollPercentage")),
+ id: currentId,
+ });
+ }
+
+ localStorage.setItem("watchedManga", JSON.stringify(scrollData));
+
+ const chapt = localStorage.getItem("chapters");
+ const chapters = JSON.parse(chapt);
+
+ const currentIndex = chapters.findIndex(
+ (chapter) => chapter.id === currentId
+ );
+
+ const nextIndex = currentIndex + 1;
+
+ const nextChapter = chapters[nextIndex];
+ const nexttChapter = chapters[nextIndex + 1];
+ const prevChapter = chapters[nextIndex - 1];
+
+ setNextChapter(nexttChapter);
+ setCurrentChapter(nextChapter);
+ setPrevChapter(prevChapter);
+
+ if (!nextChapter) {
+ return;
+ }
+
+ fetch(
+ `https://api.moopa.my.id/meta/anilist-manga/read?chapterId=${nextChapter.id}&provider=${provider}`
+ )
+ .then((response) => response.json())
+ .then((data) => {
+ if (provider === "mangakakalot") {
+ const datas = data.map((item) => ({
+ img: `https://api.consumet.org/utils/image-proxy?url=${item.img}&referer={Referer:'https://mangakakalot.com/'}`,
+ page: item.page,
+ title: item.title,
+ }));
+ // console.log(datas);
+ setData(datas);
+ } else {
+ setData(data);
+ }
+ })
+ .finally(() => {
+ setIsLoading(false);
+ });
+
+ // Update the current chapter id in local storage
+ localStorage.setItem("currentChapterId", nextChapter.id);
+ }
+
+ const chapt = localStorage.getItem("chapters");
+ const chapters = JSON.parse(chapt);
+
+ const currentIndex = chapters.findIndex(
+ (chapter) => chapter.id === currentId
+ );
+
+ const nextIndex = currentIndex + 1;
+
+ const nextChapter = chapters[nextIndex];
+ const nexttChapter = chapters[nextIndex + 1];
+ const prevChapter = chapters[nextIndex - 1];
+
+ setNextChapter(nexttChapter);
+ setCurrentChapter(nextChapter);
+ setPrevChapter(prevChapter);
+
+ if (!nextChapter) {
+ return;
+ }
+
+ fetch(
+ `https://api.moopa.my.id/meta/anilist-manga/read?chapterId=${nextChapter.id}&provider=${provider}`
+ )
+ .then((response) => response.json())
+ .then((data) => {
+ if (provider === "mangakakalot") {
+ const datas = data.map((item) => ({
+ img: `https://api.consumet.org/utils/image-proxy?url=${item.img}&referer={Referer:'https://mangakakalot.com/'}`,
+ page: item.page,
+ title: item.title,
+ }));
+ // console.log(datas);
+ setData(datas);
+ } else {
+ setData(data);
+ }
+ })
+ .finally(() => {
+ setIsLoading(false);
+ });
+
+ // Update the current chapter id in local storage
+ localStorage.setItem("currentChapterId", nextChapter.id);
+ }
+ // console.log(data);
+
+ function getPrevChapter() {
+ // Get the current id
+ window.scrollTo(0, 0);
+ setIsLoading(true);
+
+ const currentId = localStorage.getItem("currentChapterId");
+ const scrollData = JSON.parse(localStorage.getItem("watchedManga")) || [];
+ const scroll = localStorage.getItem("scrollPercentage");
+ if (scroll >= 5) {
+ const existingDataIndex = scrollData.findIndex(
+ (data) => data.id === currentId
+ );
+ if (existingDataIndex !== -1) {
+ // Update existing data
+ scrollData[existingDataIndex].timestamp = Date.now();
+ scrollData[existingDataIndex].percentage = parseFloat(
+ localStorage.getItem("scrollPercentage")
+ );
+ } else {
+ // Add new data
+ scrollData.push({
+ timestamp: Date.now(),
+ percentage: parseFloat(localStorage.getItem("scrollPercentage")),
+ id: currentId,
+ });
+ }
+
+ localStorage.setItem("watchedManga", JSON.stringify(scrollData));
+
+ const chapt = localStorage.getItem("chapters");
+ const chapters = JSON.parse(chapt);
+
+ const currentIndex = chapters.findIndex(
+ (chapter) => chapter.id === currentId
+ );
+
+ const nextIndex = currentIndex + 1;
+
+ const nextChapter = chapters[nextIndex];
+ const nexttChapter = chapters[nextIndex + 1];
+ const prevChapter = chapters[nextIndex - 1];
+
+ setNextChapter(nexttChapter);
+ setCurrentChapter(nextChapter);
+ setPrevChapter(prevChapter);
+
+ if (!nextChapter) {
+ return;
+ }
+
+ fetch(
+ `https://api.moopa.my.id/meta/anilist-manga/read?chapterId=${nextChapter.id}&provider=${provider}`
+ )
+ .then((response) => response.json())
+ .then((data) => {
+ if (provider === "mangakakalot") {
+ const datas = data.map((item) => ({
+ img: `https://api.consumet.org/utils/image-proxy?url=${item.img}&referer={Referer:'https://mangakakalot.com/'}`,
+ page: item.page,
+ title: item.title,
+ }));
+ // console.log(datas);
+ setData(datas);
+ } else {
+ setData(data);
+ }
+ })
+ .finally(() => {
+ setIsLoading(false);
+ });
+
+ // Update the current chapter id in local storage
+ localStorage.setItem("currentChapterId", nextChapter.id);
+ }
+
+ const chapt = localStorage.getItem("chapters");
+ const chapters = JSON.parse(chapt);
+
+ const currentIndex = chapters.findIndex(
+ (chapter) => chapter.id === currentId
+ );
+
+ const prevIndex = currentIndex - 1;
+
+ const prevChapter = chapters[prevIndex];
+ const nextChapter = chapters[prevIndex + 1];
+ const prevvChapter = chapters[prevIndex - 1];
+ setCurrentChapter(prevChapter);
+ setNextChapter(nextChapter);
+ setPrevChapter(prevvChapter);
+
+ fetch(
+ `https://api.moopa.my.id/meta/anilist-manga/read?chapterId=${prevChapter.id}&provider=${provider}`
+ )
+ .then((response) => response.json())
+ .then((data) => {
+ // console.log(data);
+ if (provider === "mangakakalot") {
+ const datas = data.map((item) => ({
+ img: `https://api.consumet.org/utils/image-proxy?url=${item.img}&referer={Referer:'https://mangakakalot.com/'}`,
+ page: item.page,
+ title: item.title,
+ }));
+ // console.log(datas);
+ setData(datas);
+ } else {
+ setData(data);
+ }
+ })
+ .finally(() => {
+ setIsLoading(false);
+ });
+
+ // Update the current chapter id in local storage
+ localStorage.setItem("currentChapterId", prevChapter.id);
+ }
+ // console.log({ PREV_CHAPTER: prevChapter });
+ // console.log({ CURRENT_CHAPTER: currentChapter });
+ // console.log({ NEXT_CHAPTER: nextChapter });
+
+ return (
+ <>
+ <Head>
+ <title>{title}</title>
+ <meta name="info" content="More detailed info about the Manga" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <link rel="icon" href="/c.svg" />
+ </Head>
+ <Navbar />
+ <ScrollTracker data={currentChapter} id={aniId} />
+
+ <div className="flex h-full min-h-screen w-screen flex-col items-center text-white">
+ <div className="lg:pt-nav pt-5 text-3xl font-semibold">
+ {isLoading ? (
+ <div />
+ ) : currentChapter && currentChapter.chapter ? (
+ <p>Chapter {currentChapter.chapter}</p>
+ ) : (
+ <p>{currentChapter.title}</p>
+ )}
+ </div>
+
+ {isLoading ? (
+ <p className="pt-nav">Loading...</p>
+ ) : (
+ <div className="pointer-events-none z-10 flex min-h-screen w-screen flex-col items-center pt-nav">
+ {datas.length > 0 &&
+ datas.map((item, index) => (
+ <img
+ draggable={false}
+ key={index}
+ src={item.img}
+ alt={`Page ${item.page}`}
+ />
+ ))}
+ </div>
+ )}
+ {isLoading ? (
+ <div />
+ ) : (
+ <>
+ <div className="sticky bottom-9 z-40 my-5 mr-[20rem] flex gap-6 lg:mr-0 lg:gap-10">
+ <div
+ className={`cursor-pointer rounded-md bg-[#121212] p-2 text-center text-xl hover:bg-[#2d303a] ${
+ prevChapter ? `` : `pointer-events-none`
+ }`}
+ onClick={getPrevChapter}
+ >
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ fill="none"
+ viewBox="0 0 24 24"
+ strokeWidth="1.5"
+ stroke={`${prevChapter ? `currentColor` : `#919191`}`}
+ className="h-6 w-6"
+ >
+ <path
+ strokeLinecap="round"
+ strokeLinejoin="round"
+ d="M15.75 19.5L8.25 12l7.5-7.5"
+ />
+ </svg>
+ </div>
+ <div
+ className={`cursor-pointer ${
+ nextChapter ? `` : `pointer-events-none`
+ } rounded-md bg-[#121212] p-2 text-center text-xl hover:bg-[#2d303a]`}
+ onClick={getNextChapter}
+ >
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+ strokeWidth="1.5"
+ stroke={`${nextChapter ? `currentColor` : `#919191`}`}
+ className={`h-6 w-6`}
+ >
+ <path
+ strokeLinecap="round"
+ strokeLinejoin="round"
+ d="M8.25 4.5l7.5 7.5-7.5 7.5"
+ />
+ </svg>
+ </div>
+ </div>
+
+ <div className="z-30 w-screen bg-[#1e2023] px-5 py-[3px] text-xl lg:w-[30%] lg:bg-transparent lg:text-center">
+ {nextChapter ? (
+ nextChapter.chapter ? (
+ <p>Next Chapter {nextChapter.chapter}</p>
+ ) : (
+ <p>Next Chapter {nextChapter.title}</p>
+ )
+ ) : (
+ <p>End of Chapter</p>
+ )}
+ </div>
+ </>
+ )}
+ </div>
+ <Footer />
+ </>
+ );
+}
+
+export async function getServerSideProps(context) {
+ const { id, title, provider, aniId } = context.query;
+ const urls = [
+ `https://api.moopa.my.id/meta/anilist-manga/read?chapterId=${id}&provider=${provider}`,
+ ];
+ const results = await axios.get(urls);
+
+ if (provider === "mangakakalot") {
+ const data = results.data;
+ const datas = data.map((item) => ({
+ img: `https://api.consumet.org/utils/image-proxy?url=${item.img}&referer={Referer:'https://mangakakalot.com/'}`,
+ page: item.page,
+ title: item.title,
+ }));
+ return {
+ props: {
+ aniId,
+ id,
+ title,
+ data: datas,
+ provider,
+ },
+ };
+ }
+
+ if (!results.data) {
+ return {
+ notFound: true,
+ };
+ }
+
+ return {
+ props: {
+ aniId,
+ id,
+ title,
+ data: results.data,
+ provider,
+ },
+ };
+}
diff --git a/pages/manga/detail/id.js b/pages/manga/detail/id.js
new file mode 100644
index 0000000..cfc7076
--- /dev/null
+++ b/pages/manga/detail/id.js
@@ -0,0 +1,318 @@
+import axios from "axios";
+import Head from "next/head";
+import Image from "next/image";
+import Link from "next/link";
+import { useEffect, useState } from "react";
+import Layout from "../../../components/layout";
+
+// { `Don't touch this` }
+
+// import { useUser } from "@auth0/nextjs-auth0/client";
+// import {
+// arrayRemove,
+// arrayUnion,
+// collection,
+// doc,
+// getDoc,
+// getDocs,
+// setDoc,
+// updateDoc,
+// } from "firebase/firestore";
+// import db from "../../../lib/firebase";
+
+const options = [
+ "mangadex",
+ "mangahere",
+ "mangakakalot",
+ "mangapark",
+ "mangapill",
+ "mangareader",
+ "mangasee123",
+];
+
+export default function MangaDetail({ data, manga, aniId, provider }) {
+ const [selectOption, setSelectedOption] = useState(options[0]);
+ const [recentWatch, setRecentWatch] = useState();
+
+ // const { user, error, loading } = useUser();
+
+ // if (loading) return <div>Loading...</div>;
+ // if (error) return <div>{error.message}</div>;
+
+ const [load, setLoad] = useState(true);
+
+ useEffect(() => {
+ // async function firebase() {
+ // const colRef = collection(db, "user");
+
+ // const snapshots = await getDocs(colRef);
+
+ // const docs = snapshots.docs.map((doc) => {
+ // const data = doc.data();
+ // data.id = doc.id;
+ // return data;
+ // });
+
+ // // console.log(docs);
+ // }
+ function getRecent() {
+ const recentWatch = JSON.parse(localStorage.getItem("watchedManga"))?.map(
+ (data) => data.id
+ );
+ setRecentWatch(recentWatch);
+ }
+ getRecent();
+ // firebase();
+ }, []);
+
+ function handleLoad() {
+ setLoad(false);
+ }
+
+ const relation = data?.relations.filter(
+ (relation) => relation.malId !== null
+ );
+
+ const mangan = JSON.stringify(manga);
+
+ async function clickDeez(props) {
+ localStorage.setItem("chapters", mangan);
+ localStorage.setItem("currentChapterId", props);
+
+ // const colRef = collection(db, "user");
+ // const docRef = doc(colRef, user.sub);
+
+ // const docMangaRef = collection(docRef, "watchedManga");
+ // const watchedMangaRef = doc(docMangaRef, data.id);
+
+ // const watchedMangaSnap = await getDoc(watchedMangaRef);
+
+ // if (watchedMangaSnap.exists()) {
+ // // Update existing chapter
+ // await updateDoc(watchedMangaRef, {
+ // chapter: arrayUnion({
+ // id: props,
+ // scrollPercentage: 0,
+ // timeStamp: null,
+ // }),
+ // });
+ // // console.log("Chapter updated successfully!");
+ // } else {
+ // // Add new manga with chapter data
+ // await setDoc(watchedMangaRef, {
+ // id: data.id,
+ // image: data.image,
+ // rating: data.rating,
+ // title: data.title?.romaji || data.title?.english,
+ // chapter: [props],
+ // });
+ // // console.log("Manga added successfully with chapter data!");
+ // }
+ }
+
+ // console.log(data.id);
+ // console.log(mangan);
+ return (
+ <>
+ <Head>
+ <title>{data.title?.english || data.title.romaji}</title>
+ <meta name="info" content="More detailed info about the Manga" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <link rel="icon" href="/c.svg" />
+ </Head>
+ <div className="w-screen">
+ <Layout>
+ <div className="flex w-screen justify-center pt-[10rem] ">
+ {data ? (
+ <div className="flex w-[85%] flex-col gap-10 ">
+ <div className="flex gap-10">
+ <div className="relative h-[358px] w-[230px]">
+ <Image
+ src={data.image}
+ alt="CoverImage"
+ fill
+ className="object-cover"
+ />
+ </div>
+ <div className="flex w-[77%] flex-col gap-10">
+ <h1 className="font-karla text-3xl font-bold">
+ {data.title?.english}
+ </h1>
+ <p dangerouslySetInnerHTML={{ __html: data.description }} />
+ </div>
+ </div>
+ {relation?.length > 0 ? (
+ <div className="p-3 lg:p-0">
+ <h1 className="items-start py-5 text-2xl font-bold">
+ Relations
+ </h1>
+ <div
+ className={`grid grid-cols-1 justify-items-center py-5 px-5 lg:grid-cols-3 ${
+ load ? "h-[290px] overflow-y-clip" : ""
+ }`}
+ >
+ {relation &&
+ relation.map((relation, index) => {
+ return (
+ <div key={index} className="w-full gap-6 p-5 ">
+ <Link
+ href={
+ relation.type === "MANGA" ||
+ relation.type === "NOVEL"
+ ? `/manga/detail/id?aniId=${relation.id}`
+ : `/anime/${relation.id}`
+ }
+ className={`flex w-full justify-between rounded-md bg-[#282828] p-2 shadow-lg duration-300 ease-out hover:scale-105 ${
+ relation.type === "TV" ||
+ relation.type === "OVA" ||
+ relation.type === "MOVIE" ||
+ relation.type === "SPECIAL" ||
+ relation.type === "ONA" ||
+ relation.type === "MANGA" ||
+ relation.type === "TV_SHORT"
+ ? ``
+ : "pointer-events-none"
+ }`}
+ >
+ <div className="flex flex-col justify-between">
+ <div className="font-bold text-[#FF7F57]">
+ {relation.relationType}
+ </div>
+ <div className="text-lg font-bold text-white">
+ {relation.title.romaji ||
+ relation.title.english ||
+ relation.title.userPreferred}
+ </div>
+ <div className="flex">
+ <p className="dynamic-text rounded-lg p-1 font-outfit text-sm font-semibold">
+ {relation.type}
+ </p>
+ </div>
+ </div>
+ <div className="relative h-[200px] w-[140px] shrink-0">
+ <Image
+ fill
+ src={relation.image}
+ alt={`Cover Image for ${relation.title}`}
+ className=" bg-slate-400 object-cover"
+ />
+ </div>
+ </Link>
+ </div>
+ );
+ })}
+ </div>
+ {relation.length > 3 && (
+ <button
+ type="button"
+ className="w-full"
+ onClick={handleLoad}
+ >
+ {load ? "Load More" : ""}
+ </button>
+ )}
+ </div>
+ ) : (
+ <p>No Relations</p>
+ )}
+ <div className="flex flex-col gap-10">
+ <h1 className="text-3xl font-bold">Chapters</h1>
+ <div className="flex h-[640px] flex-col gap-10 overflow-y-scroll scrollbar-thin scrollbar-thumb-slate-800 scrollbar-thumb-rounded-full hover:scrollbar-thumb-slate-600">
+ {manga?.map((chapter, index) => {
+ return (
+ <div
+ key={index}
+ onClick={() => clickDeez(chapter.id)}
+ className={`${
+ recentWatch?.includes(chapter.id)
+ ? "text-gray-400"
+ : ""
+ }`}
+ >
+ <Link
+ // href="#"
+ href={`/manga/chapter/[chapter]`}
+ as={`/manga/chapter/read?id=${chapter.id}&title=${
+ data.title?.english || data.title?.romaji
+ }&provider=${provider}&aniId=${aniId}`}
+ >
+ {typeof chapter.title === "string" &&
+ !isNaN(Number(chapter.title)) ? (
+ <div>Chapter {Number(chapter.title)}</div>
+ ) : (
+ <div>
+ {chapter.chapter ? (
+ <p>Chapter {chapter.chapter}</p>
+ ) : (
+ <p>{chapter.title}</p>
+ )}
+ </div>
+ )}
+ </Link>
+ </div>
+ );
+ })}
+ </div>
+ </div>
+ </div>
+ ) : (
+ <p>Oops no data found :(</p>
+ )}
+ </div>
+ </Layout>
+ </div>
+ </>
+ );
+}
+
+export const getServerSideProps = async (context) => {
+ context.res.setHeader("Cache-Control", "public, max-age=3600");
+ const { aniId, aniTitle } = context.query;
+ const prv = "mangapill";
+
+ try {
+ const info = await axios.get(
+ `https://api.moopa.my.id/meta/anilist-manga/info/${aniId}?provider=${prv}`
+ );
+ const result = info.data;
+ const manga = result.chapters;
+
+ return {
+ props: {
+ data: result,
+ aniId: aniId,
+ provider: prv,
+ manga,
+ },
+ };
+ } catch (error) {
+ if (error.response && error.response.status === 404) {
+ try {
+ const prv = "mangakakalot";
+ const manga = await axios.get(
+ `https://api.moopa.my.id/meta/anilist-manga/info/${aniId}?provider=${prv}`
+ );
+ const results = manga.data;
+
+ return {
+ props: {
+ data: results,
+ aniId: aniId,
+ manga: results.chapters,
+ provider: prv,
+ },
+ };
+ } catch (error) {
+ console.error(error);
+ return {
+ notFound: true,
+ };
+ }
+ } else {
+ console.error(error);
+ return {
+ notFound: true,
+ };
+ }
+ }
+};