aboutsummaryrefslogtreecommitdiff
path: root/components/shared/NavBar.tsx
diff options
context:
space:
mode:
authorFactiven <[email protected]>2023-12-24 13:03:54 +0700
committerFactiven <[email protected]>2023-12-24 13:03:54 +0700
commit50a0f0240d7fef133eb5acc1bea2b1168b08e9db (patch)
tree307e09e505580415a58d64b5fc3580e9235869f1 /components/shared/NavBar.tsx
parentUpdate README.md (#104) (diff)
downloadmoopa-50a0f0240d7fef133eb5acc1bea2b1168b08e9db.tar.xz
moopa-50a0f0240d7fef133eb5acc1bea2b1168b08e9db.zip
migrate to typescript
Diffstat (limited to 'components/shared/NavBar.tsx')
-rw-r--r--components/shared/NavBar.tsx289
1 files changed, 289 insertions, 0 deletions
diff --git a/components/shared/NavBar.tsx b/components/shared/NavBar.tsx
new file mode 100644
index 0000000..6e8812e
--- /dev/null
+++ b/components/shared/NavBar.tsx
@@ -0,0 +1,289 @@
+import { useSearch } from "@/lib/context/isOpenState";
+import { getCurrentSeason } from "@/utils/getTimes";
+import { ArrowLeftIcon, ArrowUpCircleIcon } from "@heroicons/react/20/solid";
+import { UserIcon } from "@heroicons/react/24/solid";
+import { signIn, signOut, useSession } from "next-auth/react";
+import Image from "next/image";
+import Link from "next/link";
+import { useRouter } from "next/router";
+import { useEffect, useState } from "react";
+import { AniListInfoTypes } from "types/info/AnilistInfoTypes";
+
+const getScrollPosition = (el: Window | Element = window) => {
+ if (el instanceof Window) {
+ return { x: el.pageXOffset, y: el.pageYOffset };
+ } else {
+ return { x: el.scrollLeft, y: el.scrollTop };
+ }
+};
+
+type NavbarProps = {
+ info?: AniListInfoTypes | null;
+ scrollP?: number;
+ toTop?: boolean;
+ withNav?: boolean;
+ paddingY?: string;
+ home?: boolean;
+ back?: boolean;
+ manga?: boolean;
+ shrink?: boolean;
+ bgHover?: boolean;
+};
+
+export function Navbar({
+ info = null,
+ scrollP = 200,
+ toTop = false,
+ withNav = false,
+ paddingY = "py-3",
+ home = false,
+ back = false,
+ manga = false,
+ shrink = false,
+ bgHover = false,
+}: NavbarProps) {
+ const { data: session }: { data: any } = useSession();
+ const router = useRouter();
+ const [scrollPosition, setScrollPosition] = useState<
+ { x: number; y: number } | undefined
+ >();
+ const { setIsOpen } = useSearch();
+
+ const year = new Date().getFullYear();
+ const season = getCurrentSeason();
+
+ useEffect(() => {
+ const handleScroll = () => {
+ setScrollPosition(getScrollPosition());
+ };
+
+ // Add a scroll event listener when the component mounts
+ window.addEventListener("scroll", handleScroll);
+
+ // Clean up the event listener when the component unmounts
+ return () => {
+ window.removeEventListener("scroll", handleScroll);
+ };
+ }, []);
+ return (
+ <>
+ <nav
+ className={`${home ? "" : "fixed"} ${
+ bgHover ? "hover:bg-tersier" : ""
+ } z-[200] top-0 px-5 w-full ${
+ scrollPosition?.y ?? 0 >= scrollP
+ ? home
+ ? ""
+ : `bg-tersier shadow-tersier shadow-sm ${
+ shrink ? "py-1" : `${paddingY}`
+ }`
+ : `${paddingY}`
+ } transition-all duration-200 ease-linear`}
+ >
+ <div
+ className={`flex items-center justify-between mx-auto ${
+ home ? "lg:max-w-[90%] gap-10" : "max-w-screen-2xl"
+ }`}
+ >
+ <div
+ className={`flex items-center ${
+ withNav ? `${home ? "" : "w-[20%]"} gap-8` : " w-full gap-4"
+ }`}
+ >
+ {info ? (
+ <>
+ <button
+ type="button"
+ className="flex-center w-7 h-7 text-white"
+ onClick={() => {
+ back
+ ? router.back()
+ : manga
+ ? router.push("/en/search/manga")
+ : router.push("/en");
+ }}
+ >
+ <ArrowLeftIcon className="w-full h-full" />
+ </button>
+
+ <span
+ className={`font-inter font-semibold w-[50%] line-clamp-1 select-none ${
+ scrollPosition?.y ?? 0 >= scrollP + 80
+ ? "opacity-100"
+ : "opacity-0"
+ } transition-all duration-200 ease-linear`}
+ >
+ {info.title.romaji}
+ </span>
+ </>
+ ) : (
+ // <></>
+ <Link
+ href={"/en"}
+ className={`flex-center font-outfit font-semibold pb-2 ${
+ home ? "text-4xl text-action" : "text-white text-3xl"
+ }`}
+ >
+ moopa
+ </Link>
+ )}
+ </div>
+
+ {withNav && (
+ <ul
+ className={`hidden w-full items-center gap-10 pt-2 font-outfit text-[14px] lg:pt-0 lg:flex ${
+ home ? "justify-start" : "justify-center"
+ }`}
+ >
+ <li>
+ <Link
+ href={`/en/search/anime?season=${season}&year=${year}`}
+ className="hover:text-action/80 transition-all duration-150 ease-linear"
+ >
+ This Season
+ </Link>
+ </li>
+ <li>
+ <Link
+ href="/en/search/manga"
+ className="hover:text-action/80 transition-all duration-150 ease-linear"
+ >
+ Manga
+ </Link>
+ </li>
+ <li>
+ <Link
+ href="/en/search/anime"
+ className="hover:text-action/80 transition-all duration-150 ease-linear"
+ >
+ Anime
+ </Link>
+ </li>
+ <li>
+ <Link
+ href="/en/schedule"
+ className="hover:text-action/80 transition-all duration-150 ease-linear"
+ >
+ Schedule
+ </Link>
+ </li>
+
+ {!session && (
+ <li>
+ <button
+ onClick={() => signIn("AniListProvider")}
+ className="hover:text-action/80 transition-all duration-150 ease-linear"
+ // className="px-2 py-1 ring-1 ring-action font-bold font-karla rounded-md"
+ >
+ Sign In
+ </button>
+ </li>
+ )}
+ {session && (
+ <li className="text-center">
+ <Link
+ href={`/en/profile/${session?.user?.name}`}
+ className="hover:text-action/80 transition-all duration-150 ease-linear"
+ >
+ My List
+ </Link>
+ </li>
+ )}
+ </ul>
+ )}
+
+ <div className="flex w-[20%] justify-end items-center gap-4">
+ <button
+ type="button"
+ title="Search"
+ onClick={() => setIsOpen(true)}
+ className="flex-center w-[26px] h-[26px]"
+ >
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ width="32"
+ height="32"
+ viewBox="0 0 24 24"
+ >
+ <path
+ fill="none"
+ stroke="currentColor"
+ strokeLinecap="round"
+ strokeLinejoin="round"
+ strokeWidth="2"
+ d="M15 15l6 6m-11-4a7 7 0 110-14 7 7 0 010 14z"
+ ></path>
+ </svg>
+ </button>
+ {/* <div
+ className="bg-white"
+ // title={sessions ? "Go to Profile" : "Login With AniList"}
+ > */}
+ {session ? (
+ <div className="w-7 h-7 relative flex flex-col items-center group shrink-0">
+ <button
+ type="button"
+ onClick={() =>
+ router.push(`/en/profile/${session?.user?.name}`)
+ }
+ className="rounded-full w-7 h-7 bg-white/30 overflow-hidden"
+ >
+ <Image
+ src={session?.user?.image?.large}
+ alt="avatar"
+ width={50}
+ height={50}
+ className="w-7 h-7 object-cover"
+ />
+ </button>
+ <div className="hidden absolute z-50 w-28 text-center -bottom-20 text-white shadow-2xl opacity-0 bg-secondary p-1 py-2 rounded-md font-karla font-light invisible group-hover:visible group-hover:opacity-100 duration-300 transition-all md:grid place-items-center gap-1">
+ <Link
+ href={`/en/profile/${session?.user?.name}`}
+ className="hover:text-action"
+ >
+ Profile
+ </Link>
+ <button
+ type="button"
+ onClick={() => signOut({ redirect: true })}
+ className="hover:text-action"
+ >
+ Log out
+ </button>
+ </div>
+ </div>
+ ) : (
+ <button
+ type="button"
+ onClick={() => signIn("AniListProvider")}
+ title="Login With AniList"
+ className="w-7 h-7 bg-white/30 rounded-full overflow-hidden shrink-0"
+ >
+ <UserIcon className="w-full h-full translate-y-1" />
+ </button>
+ )}
+ {/* </div> */}
+ </div>
+ </div>
+ </nav>
+ {toTop && (
+ <button
+ type="button"
+ onClick={() => {
+ window.scrollTo({
+ top: 0,
+ behavior: "smooth",
+ });
+ }}
+ className={`${
+ scrollPosition?.y ?? 0 >= 180
+ ? "-translate-x-6 opacity-100"
+ : "translate-x-[100%] opacity-0"
+ } transform transition-all duration-300 ease-in-out fixed bottom-24 lg:bottom-14 right-0 z-[500]`}
+ >
+ <ArrowUpCircleIcon className="w-10 h-10 text-white" />
+ </button>
+ )}
+ </>
+ );
+}