|
|
@@ -1,265 +0,0 @@
|
|
|
-"use client";
|
|
|
-
|
|
|
-import { useDisclosure } from "@heroui/use-disclosure";
|
|
|
-import { AnimatePresence, motion } from "framer-motion";
|
|
|
-import clsx from "clsx";
|
|
|
-import { useSession, signOut } from "next-auth/react";
|
|
|
-import Link from "next/link";
|
|
|
-import { Avatar } from "@heroui/avatar";
|
|
|
-import { useForm } from "react-hook-form";
|
|
|
-import { usePathname, useRouter } from "next/navigation";
|
|
|
-import { useCustomToast } from '@/utils/hooks/useToast';
|
|
|
-import { useBodyScrollLock } from "@utils/hooks/useBodyScrollLock";
|
|
|
-import OpenAuth from "../OpenAuth";
|
|
|
-import { isObject } from '@/utils/type-guards';
|
|
|
-import LoadingDots from "@components/common/icons/LoadingDots";
|
|
|
-import { logoutAction } from "@/actions";
|
|
|
-import { useAppDispatch } from "@/store/hooks";
|
|
|
-import { clearCart } from "@/store/slices/cart-slice";
|
|
|
-
|
|
|
-
|
|
|
-export default function CredentialModal({
|
|
|
- children,
|
|
|
- className,
|
|
|
- onOpen,
|
|
|
- onClose,
|
|
|
- isOpen,
|
|
|
-}: {
|
|
|
- children?: React.ReactNode;
|
|
|
- className?: string;
|
|
|
- onOpen?: () => void;
|
|
|
- onClose?: () => void;
|
|
|
- isOpen?: boolean;
|
|
|
-}) {
|
|
|
- const {
|
|
|
- isOpen: internalIsOpen,
|
|
|
- onOpen: internalOnOpen,
|
|
|
- onClose: internalOnClose,
|
|
|
- onOpenChange: _internalOnOpenChange,
|
|
|
- } = useDisclosure();
|
|
|
-
|
|
|
- const isControlled = isOpen !== undefined;
|
|
|
- const finalIsOpen = isControlled ? isOpen : internalIsOpen;
|
|
|
- const finalOnOpen = isControlled ? onOpen : internalOnOpen;
|
|
|
- const finalOnClose = isControlled ? onClose : internalOnClose;
|
|
|
-
|
|
|
- const pathname = usePathname();
|
|
|
- const router = useRouter();
|
|
|
- const dispatch = useAppDispatch();
|
|
|
- const { showToast } = useCustomToast();
|
|
|
-
|
|
|
-
|
|
|
- useBodyScrollLock(finalIsOpen );
|
|
|
-
|
|
|
-
|
|
|
- const {
|
|
|
- handleSubmit,
|
|
|
- formState: { isSubmitting },
|
|
|
- } = useForm();
|
|
|
-
|
|
|
- const {data: session} = useSession();
|
|
|
-
|
|
|
- const onSubmit = async () => {
|
|
|
- try {
|
|
|
-
|
|
|
- const res = await logoutAction();
|
|
|
-
|
|
|
- if (!res.success) {
|
|
|
- showToast(res.message, "danger");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- await signOut({
|
|
|
- callbackUrl: "/customer/login",
|
|
|
- redirect: false,
|
|
|
- });
|
|
|
-
|
|
|
- dispatch(clearCart());
|
|
|
- showToast("You are logged out successfully!", "success");
|
|
|
- setTimeout(() => {
|
|
|
- router.push("/customer/login");
|
|
|
- router.refresh();
|
|
|
- }, 100);
|
|
|
- } catch (err: unknown) {
|
|
|
- const message = err instanceof Error ? err.message : "Logout failed";
|
|
|
- showToast(message, "danger");
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- const innerContent = (_onClose?: () => void) => (
|
|
|
- <div className={clsx("flex w-full flex-col rounded-md py-4", {
|
|
|
- "gap-y-6": !!session?.user,
|
|
|
- "gap-y-10": !session?.user,
|
|
|
- })}>
|
|
|
- {isObject(session?.user) ? (
|
|
|
- <>
|
|
|
- <header>
|
|
|
- <div className={clsx("flex flex-col gap-3", "items-center justify-center")}>
|
|
|
- <div className={clsx("flex gap-3", "flex-col items-center")}>
|
|
|
- <Avatar
|
|
|
- isBordered
|
|
|
- showFallback
|
|
|
- color="default"
|
|
|
- icon={<OpenAuth className={clsx("h-12 w-12")} />}
|
|
|
- size={"lg"}
|
|
|
- className={clsx( "h-24 w-24 text-large")}
|
|
|
- />
|
|
|
- <div className={clsx("flex flex-col justify-center", "items-center gap-1")}>
|
|
|
- <h4 className={clsx("leading-none dark:text-white", "text-xl font-bold text-black")}>
|
|
|
- {session?.user?.name}
|
|
|
- </h4>
|
|
|
- <h5 className={clsx("tracking-tight dark:text-white", "text-sm text-gray-500")}>
|
|
|
- {session?.user?.email}
|
|
|
- </h5>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <p className={clsx("text-default-500 dark:text-white", "text-center mt-2")}>
|
|
|
- Manage Cart, Orders
|
|
|
- <span aria-label="confetti" className="px-2" role="img">
|
|
|
- 🎉
|
|
|
- </span>
|
|
|
- </p>
|
|
|
- </div>
|
|
|
- </header>
|
|
|
-
|
|
|
- <footer>
|
|
|
- <form onSubmit={handleSubmit(onSubmit)} className={clsx("flex justify-center")}>
|
|
|
- <button
|
|
|
- className={clsx(
|
|
|
- "rounded-full bg-gray-800 px-5 py-2.5 text-sm font-medium text-white hover:bg-gray-900 focus:outline-none focus:ring-4 focus:ring-gray-300 dark:border-gray-700 dark:bg-gray-800 dark:hover:bg-gray-700 dark:focus:ring-gray-700",
|
|
|
- isSubmitting ? " cursor-not-allowed" : " cursor-pointer",
|
|
|
- "w-40 min-w-[150px] mt-2"
|
|
|
- )}
|
|
|
- type="submit"
|
|
|
- >
|
|
|
- <div className="mx-1">
|
|
|
- {isSubmitting ? (
|
|
|
- <div className="flex items-center justify-center">
|
|
|
- <p>Loading</p>
|
|
|
- <LoadingDots className="bg-white" />
|
|
|
- </div>
|
|
|
- ) : (
|
|
|
- <p> Log Out</p>
|
|
|
- )}
|
|
|
- </div>
|
|
|
- </button>
|
|
|
- </form>
|
|
|
- </footer>
|
|
|
- </>
|
|
|
- ) : (
|
|
|
- <>
|
|
|
- <header className="text-center">
|
|
|
- <div className="flex flex-col gap-y-2">
|
|
|
- <h4 className="font-bold leading-none text-black dark:text-white text-3xl">
|
|
|
- Welcome Guest
|
|
|
- </h4>
|
|
|
- <p className="text-default-500 dark:text-neutral-400 text-lg">
|
|
|
- Manage Cart, Orders
|
|
|
- <span aria-label="confetti" className="px-2" role="img">
|
|
|
- 🎉
|
|
|
- </span>
|
|
|
- </p>
|
|
|
- </div>
|
|
|
- </header>
|
|
|
-
|
|
|
- <footer className="flex gap-4">
|
|
|
- <Link className="w-full" href="/customer/login" onClick={finalOnClose} aria-label="Go to sign in page">
|
|
|
- <button
|
|
|
- className={clsx(
|
|
|
- "w-full rounded-full bg-blue-600 px-5 py-3 text-center text-sm font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-4 focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800",
|
|
|
- pathname === "/customer/login"
|
|
|
- ? " cursor-not-allowed"
|
|
|
- : " cursor-pointer"
|
|
|
- )}
|
|
|
- disabled={pathname === "/customer/login"}
|
|
|
- type="button"
|
|
|
- >
|
|
|
- Sign In
|
|
|
- </button>
|
|
|
- </Link>
|
|
|
-
|
|
|
- <Link className="w-full" href="/customer/register" onClick={finalOnClose} aria-label="Go to create account page">
|
|
|
- <button
|
|
|
- className={clsx(
|
|
|
- "w-full rounded-full bg-[#1e293b] px-5 py-3 text-sm font-medium text-white hover:bg-gray-900 focus:outline-none focus:ring-4 focus:ring-gray-300 dark:border-gray-700 dark:bg-gray-800 dark:hover:bg-gray-700 dark:focus:ring-gray-700",
|
|
|
- pathname === "/customer/register"
|
|
|
- ? " cursor-not-allowed"
|
|
|
- : " cursor-pointer"
|
|
|
- )}
|
|
|
- disabled={pathname === "/customer/register"}
|
|
|
- type="button"
|
|
|
- >
|
|
|
- Sign Up
|
|
|
- </button>
|
|
|
- </Link>
|
|
|
- </footer>
|
|
|
- </>
|
|
|
- )}
|
|
|
- </div>
|
|
|
- );
|
|
|
-
|
|
|
-
|
|
|
- return (
|
|
|
- <>
|
|
|
- <button
|
|
|
- type="button"
|
|
|
- aria-label="Open account"
|
|
|
- className={clsx(className, "cursor-pointer bg-transparent")}
|
|
|
- onClick={finalOnOpen}
|
|
|
- >
|
|
|
- {children ? children : <OpenAuth />}
|
|
|
- </button>
|
|
|
-
|
|
|
- <AnimatePresence>
|
|
|
- {finalIsOpen && (
|
|
|
- <>
|
|
|
- <motion.div
|
|
|
- initial={{ opacity: 0 }}
|
|
|
- animate={{ opacity: 1 }}
|
|
|
- exit={{ opacity: 0 }}
|
|
|
- onClick={finalOnClose}
|
|
|
- className="fixed inset-0 z-40 bg-transparent"
|
|
|
- style={{ top: "68px", bottom: "64px" }}
|
|
|
- />
|
|
|
-
|
|
|
- <motion.div
|
|
|
- initial={{ x: "100%" }}
|
|
|
- animate={{ x: 0 }}
|
|
|
- exit={{ x: "100%" }}
|
|
|
- transition={{ type: "spring", damping: 30, stiffness: 300, mass: 0.8 }}
|
|
|
- className="fixed right-0 z-50 flex flex-col border-l border-neutral-200 bg-white dark:border-neutral-800 dark:bg-black lg:hidden"
|
|
|
- style={{
|
|
|
- top: "68px",
|
|
|
- bottom: "64px",
|
|
|
- width: "100%",
|
|
|
- maxWidth: "448px",
|
|
|
- height: "calc(var(--visual-viewport-height) - 132px)",
|
|
|
- }}
|
|
|
- >
|
|
|
- <div className="flex flex-col gap-1 border-b border-neutral-100 p-4 dark:border-neutral-800">
|
|
|
- <div className="flex items-center justify-between">
|
|
|
- <p className="text-xl font-semibold dark:text-white">Account</p>
|
|
|
- <button
|
|
|
- aria-label="Close account"
|
|
|
- className="rounded-full p-1 hover:bg-neutral-100 "
|
|
|
- onClick={finalOnClose}
|
|
|
- type="button"
|
|
|
- >
|
|
|
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" className="h-6 transition-all ease-in-out hover:scale-110"><path strokeLinecap="round" strokeLinejoin="round" d="M6 18 18 6M6 6l12 12"></path></svg>
|
|
|
- </button>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div className="flex flex-1 flex-col justify-center px-4 py-0 drawer-scrollbar-hidden">
|
|
|
- {innerContent(finalOnClose)}
|
|
|
- </div>
|
|
|
-
|
|
|
- <div className="p-4" />
|
|
|
- </motion.div>
|
|
|
- </>
|
|
|
- )}
|
|
|
- </AnimatePresence>
|
|
|
- </>
|
|
|
- );
|
|
|
-}
|