diff options
| author | Factiven <[email protected]> | 2023-04-11 23:23:29 +0700 |
|---|---|---|
| committer | Factiven <[email protected]> | 2023-04-11 23:23:29 +0700 |
| commit | 1fcdd9f7d859b925bf92265f441655d5522e351c (patch) | |
| tree | 86391522f6fcc70d105f7e796a9f91d132ee4a29 /pages/manga | |
| parent | Initial commit (diff) | |
| download | moopa-1fcdd9f7d859b925bf92265f441655d5522e351c.tar.xz moopa-1fcdd9f7d859b925bf92265f441655d5522e351c.zip | |
initial commit
Diffstat (limited to 'pages/manga')
| -rw-r--r-- | pages/manga/chapter/[chapter].js | 423 | ||||
| -rw-r--r-- | pages/manga/detail/id.js | 318 |
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, + }; + } + } +}; |