Quellcode durchsuchen

个人中心添加退出登录逻辑

fogwind vor 20 Stunden
Ursprung
Commit
5a1975c9d8

+ 0 - 14
src/components/customer/OpenAuth.tsx

@@ -1,14 +0,0 @@
-import { UserIcon } from "@heroicons/react/24/outline";
-import clsx from "clsx";
-
-export default function OpenAuth({ className }: { className?: string }) {
-  return (
-    <>
-      <div className="relative flex items-center justify-center rounded-md border-0 lg:border border-solid border-neutral-200 dark:border-neutral-700 lg:h-11 lg:w-11">
-        <UserIcon className={clsx("h-5 w-5  ", className)} />
-      </div>
-    </>
-
-  );
-}
-

+ 39 - 1
src/components/customer/SettingModal.tsx

@@ -1,6 +1,13 @@
 "use client";
 import Link from "next/link";
 import { useState } from "react";
+import { useRouter } from "next/navigation";
+import { signOut } from "next-auth/react";
+import { logoutAction } from "@/actions";
+import { useCustomToast } from '@/utils/hooks/useToast';
+import { useAppDispatch } from "@/store/hooks";
+import { clearCart } from "@/store/slices/cart-slice";
+import { overlayLoading } from "@/components/theme/ui/kernel/loading/api";
 import HelpModal from "../../app/(public)/customer/account/_components/HelpModal";
 export default function SettingModal({
   visible,
@@ -9,7 +16,38 @@ export default function SettingModal({
   visible: boolean;
   onClose: () => void;
 }) {
+  const router = useRouter();
+  const dispatch = useAppDispatch();
+  const { showToast } = useCustomToast();
   const [showSetting, setShowSetting] = useState(false);
+  const logOutHandler = async () => {
+    try {
+      overlayLoading.start();
+      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");
+      overlayLoading.stop();
+      setTimeout(() => {
+        router.push("/customer/login");
+        router.refresh();
+      }, 100);
+    } catch (err: unknown) {
+      overlayLoading.stop();
+      const message = err instanceof Error ? err.message : "Logout failed";
+      showToast(message, "danger");
+    }
+  };
   // 如果不显示,直接 return null
   if (!visible) return null;
   
@@ -132,7 +170,7 @@ export default function SettingModal({
 
               {/* Log Out */}
               <div className="py-4  absolute left-1/2 -translate-x-1/2 bottom-7 ">
-                <button className="text-black font-medium  w-full underline text-center">
+                <button onClick={logOutHandler} className="text-black font-medium  w-full underline text-center" type="button">
                   Log Out
                 </button>
               </div>

+ 0 - 265
src/components/customer/credentials/CredentialModal.tsx

@@ -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>
-    </>
-  );
-}

+ 0 - 21
src/components/customer/credentials/index.tsx

@@ -1,21 +0,0 @@
-import CredentialModal from "./CredentialModal";
-
-export default function UserAccount({
-  children,
-  className,
-  onOpen,
-  onClose,
-  isOpen,
-}: {
-  children?: React.ReactNode;
-  className?: string;
-  onOpen?: () => void;
-  onClose?: () => void;
-  isOpen?: boolean;
-}) {
-  return (
-    <CredentialModal className={className} onOpen={onOpen} onClose={onClose} isOpen={isOpen}>
-      {children}
-    </CredentialModal>
-  );
-}