diff options
Diffstat (limited to 'pages/id/novel')
| -rw-r--r-- | pages/id/novel/[...id].tsx | 121 | ||||
| -rw-r--r-- | pages/id/novel/read/index.tsx | 115 |
2 files changed, 236 insertions, 0 deletions
diff --git a/pages/id/novel/[...id].tsx b/pages/id/novel/[...id].tsx new file mode 100644 index 0000000..7e9e155 --- /dev/null +++ b/pages/id/novel/[...id].tsx @@ -0,0 +1,121 @@ +import axios from "axios"; +import Image from "next/image"; +import Link from "next/link"; +import { useEffect, useState } from "react"; +import { Navbar } from "../../../components/shared/NavBar"; +import MobileNav from "../../../components/shared/MobileNav"; +import { GetServerSideProps } from "next"; + +type InfoNovelProps = { + id: string; + API: string; +}; + +type NovelData = { + image?: string; + title?: string; + Release?: string; + Status?: string; + Author?: string; + description?: string; + chapters?: { + chapterId?: string; + chapter?: string; + release?: string; + }[]; + notFound?: boolean; +}; + +export default function InfoNovel({ id, API }: InfoNovelProps) { + const [data, setData] = useState<NovelData>(); + const [loading, setLoading] = useState(true); + + useEffect(() => { + async function fetchData() { + setLoading(true); + try { + const { data } = await axios.get(`${API}/api/novel/info/` + id); + setData(data); + } catch (error) { + setData({ + notFound: true, + }); + } finally { + setLoading(false); + } + } + fetchData(); + + return () => { + setData(undefined); + }; + }, [id]); + + return ( + <div className="flex flex-col items-center"> + <Navbar withNav paddingY="" scrollP={0} /> + <MobileNav hideProfile /> + <div className="relative w-full max-w-screen-lg mx-5 mt-5 px-5 lg:px-0 lg:mt-14"> + {data && ( + <div className="flex lg:flex-row flex-col z-30 pt-24 lg:px-5"> + {data?.image && ( + <Image + src={data?.image} + width={200} + height={200} + alt="coverImage" + className="z-50 w-[170px] h-[240px] object-cover rounded" + /> + )} + <div className="flex flex-col items-start justify-end gap-2 lg:pl-5 z-30 mt-5 lg:mt-0"> + <h1 className="font-bold text-2xl lg:text-3xl font-outfit line-clamp-2"> + {data?.title} + </h1> + <div className="flex gap-5 w-full"> + <p className="flex gap-2 font-bold font-karla"> + Release: <span>{data?.Release}</span> + </p> + <p className="flex gap-2 font-bold font-karla"> + Status: <span>{data?.Status}</span> + </p> + <p className="flex-1 gap-2 font-bold font-karla overflow-x-hidden text-ellipsis whitespace-nowrap"> + Author: <span>{data?.Author}</span> + </p> + </div> + <p className="line-clamp-2 font-light font-karla"> + {data?.description} + </p> + </div> + </div> + )} + + <div className="mt-10 flex flex-col gap-3"> + {data?.chapters?.map((chapter) => ( + <Link + key={chapter?.chapterId} + href={`/id/novel/read/?id=${chapter?.chapterId}`} + className="py-3 bg-secondary w-full px-5 rounded" + > + <div className="flex justify-between w-full"> + <p className="font-bold font-karla">{chapter?.chapter}</p> + <p className="font-light font-karla">{chapter?.release}</p> + </div> + </Link> + ))} + </div> + <div className="w-full bg-secondary rounded-xl h-[200px] absolute inset-0 z-10" /> + </div> + </div> + ); +} + +export const getServerSideProps: GetServerSideProps = async ({ params }) => { + const { id } = params || {}; + const API = process.env.ID_API; + return { + props: { + id, + API, + }, + }; +}; diff --git a/pages/id/novel/read/index.tsx b/pages/id/novel/read/index.tsx new file mode 100644 index 0000000..5f36e54 --- /dev/null +++ b/pages/id/novel/read/index.tsx @@ -0,0 +1,115 @@ +import Link from "next/link"; +import { useSearchParams } from "next/navigation"; +import { useEffect, useState } from "react"; +import { Navbar } from "@/components/shared/NavBar"; +import MobileNav from "@/components/shared/MobileNav"; +import pls from "@/utils/request/index"; + +interface IData { + novelTitle: string; + title: string; + navigation: { + next: string; + prev: string; + }; + content: string; +} + +export async function getServerSideProps() { + const API = process.env.ID_API; + return { + props: { + API, + }, + }; +} + +export default function ReadNovel({ API }: { API: string }) { + const [data, setData] = useState<IData>(); + + const searchParams = useSearchParams(); + const id = searchParams.get("id"); + const mangaId = id?.split("/")[0]; + + useEffect(() => { + async function fetchData() { + if (id) { + const data = await pls.get(`${API}/api/novel/chapter/${id}`); + setData(data); + } + } + fetchData(); + + return () => { + setData(undefined); + }; + }, [id]); + + return ( + <> + <Navbar withNav paddingY="py-2" scrollP={2} /> + <MobileNav hideProfile /> + <div className="w-screen flex flex-col items-center"> + {/* {data && ( */} + <div className="flex items-center gap-5 w-full max-w-screen-lg px-5 mt-16 font-karla font-bold"> + <div className="flex gap-2"> + <Link + href={`/id/novel/read/?id=${data?.navigation?.prev}`} + className={`${ + data?.navigation?.prev ? "" : "pointer-events-none opacity-60" + } py-1 px-2 bg-secondary rounded`} + > + prev + </Link> + <Link + href={`/id/novel/read/?id=${data?.navigation?.next}`} + className={`${ + data?.navigation?.next ? "" : "pointer-events-none opacity-60" + } py-1 px-2 bg-secondary rounded`} + > + next + </Link> + </div> + <span>/</span> + <Link href={`/id/novel/${mangaId}`} className="text-lg line-clamp-1"> + {data?.novelTitle} + </Link> + </div> + {/* )} */} + <div className="block mt-5"> + <div className="px-5 w-full h-full max-w-screen-lg pointer-events-none select-none"> + <p className="text-xl font-bold my-5">{data?.title}</p> + {data?.content && ( + <p + dangerouslySetInnerHTML={{ __html: data?.content }} + className="space-y-5" + /> + )} + </div> + </div> + {data?.content && ( + <div className="px-5 py-10 w-full h-full max-w-screen-lg"> + <div className="flex w-full gap-2"> + <Link + href={`/id/novel/read/?id=${data?.navigation?.prev}`} + className={`${ + data?.navigation?.prev ? "" : "pointer-events-none opacity-60" + } py-1 px-2 bg-secondary rounded`} + > + prev + </Link> + <Link + href={`/id/novel/read/?id=${data?.navigation?.next}`} + className={`${ + data?.navigation?.next ? "" : "pointer-events-none opacity-60" + } py-1 px-2 bg-secondary rounded`} + > + next + </Link> + </div> + </div> + )} + </div> + </> + ); +} |