From 3ed505bcf37d93340e1e6c683392b5fca65d84ab Mon Sep 17 00:00:00 2001 From: emmalynf <efoster@unc.edu> Date: Fri, 15 Nov 2024 21:33:13 -0500 Subject: [PATCH] loading for sign out --- compass/app/home/layout.tsx | 4 +++ .../components/Sidebar/LoadingIcon.module.css | 20 ++++++++++++ compass/components/Sidebar/LoadingIcon.tsx | 14 +++++++++ compass/components/Sidebar/Sidebar.tsx | 22 ++++++++++--- compass/components/resource/UserProfile.tsx | 31 ++++++------------- 5 files changed, 64 insertions(+), 27 deletions(-) create mode 100644 compass/components/Sidebar/LoadingIcon.module.css create mode 100644 compass/components/Sidebar/LoadingIcon.tsx diff --git a/compass/app/home/layout.tsx b/compass/app/home/layout.tsx index 236616e..ec67157 100644 --- a/compass/app/home/layout.tsx +++ b/compass/app/home/layout.tsx @@ -15,6 +15,8 @@ export default function RootLayout({ const [isSidebarOpen, setIsSidebarOpen] = useState(true); const [user, setUser] = useState<User>(); const router = useRouter(); + const [loading, setLoading] = useState(true); + useEffect(() => { async function getUser() { @@ -35,6 +37,7 @@ export default function RootLayout({ ); setUser(await userData.json()); + setLoading(false); } getUser(); @@ -50,6 +53,7 @@ export default function RootLayout({ setIsSidebarOpen={setIsSidebarOpen} isSidebarOpen={isSidebarOpen} isAdmin={user.role === Role.ADMIN} + loading={loading} /> <div className={`flex-1 transition duration-300 ease-in-out ${ diff --git a/compass/components/Sidebar/LoadingIcon.module.css b/compass/components/Sidebar/LoadingIcon.module.css new file mode 100644 index 0000000..2b0c9d2 --- /dev/null +++ b/compass/components/Sidebar/LoadingIcon.module.css @@ -0,0 +1,20 @@ +/* components/LoadingIcon.module.css */ +.loader { + width: 24px; /* Larger for better visibility */ + height: 24px; + border: 4px solid #5b21b6; /* Primary color */ + border-top: 4px solid #ffffff; /* Contrasting color */ + border-radius: 50%; + animation: spin 1s linear infinite; /* Smooth continuous spin */ + margin-bottom: 20px; +} + + +@keyframes spin { + 0% { + transform: rotate(0deg); /* Start position */ + } + 100% { + transform: rotate(360deg); /* Full rotation */ + } +} diff --git a/compass/components/Sidebar/LoadingIcon.tsx b/compass/components/Sidebar/LoadingIcon.tsx new file mode 100644 index 0000000..ddf3eb3 --- /dev/null +++ b/compass/components/Sidebar/LoadingIcon.tsx @@ -0,0 +1,14 @@ +// components/Loading.js +import styles from "./LoadingIcon.module.css"; + +const LoadingIcon = () => { + return ( + <div className={styles.loadingOverlay}> + <div className={styles.loadingContent}> + <div className={styles.loader}></div> + </div> + </div> + ); +}; + +export default LoadingIcon; \ No newline at end of file diff --git a/compass/components/Sidebar/Sidebar.tsx b/compass/components/Sidebar/Sidebar.tsx index d82ab69..232eda7 100644 --- a/compass/components/Sidebar/Sidebar.tsx +++ b/compass/components/Sidebar/Sidebar.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useState } from "react"; import { HomeIcon, ChevronDoubleLeftIcon, @@ -9,7 +9,9 @@ import { LockClosedIcon, } from "@heroicons/react/24/solid"; import { SidebarItem } from "./SidebarItem"; +import styles from "./LoadingIcon.module.css" import { UserProfile } from "../resource/UserProfile"; +import LoadingIcon from "./LoadingIcon"; interface SidebarProps { setIsSidebarOpen: React.Dispatch<React.SetStateAction<boolean>>; @@ -17,6 +19,7 @@ interface SidebarProps { name: string; email: string; isAdmin: boolean; + loading: boolean; } const Sidebar: React.FC<SidebarProps> = ({ @@ -25,7 +28,9 @@ const Sidebar: React.FC<SidebarProps> = ({ name, email, isAdmin: admin, + loading, }) => { + const [isLoading, setIsLoading] = useState(false); return ( <> {/* Button to open the sidebar. */} @@ -62,11 +67,18 @@ const Sidebar: React.FC<SidebarProps> = ({ </button> </div> - <div className="flex flex-col space-y-8"> - {/* user + logout button */} - <div className="flex items-center p-4 space-x-2 border border-gray-200 rounded-md "> - <UserProfile name={name} email={email} /> + {/* Loading indicator*/} + {isLoading && ( + <div className="fixed top-2 left-2"> + <LoadingIcon/>{/* Spinner */} </div> + )} + + <div className="flex flex-col space-y-8"> + <div className="flex items-center p-4 space-x-2 border rounded-md"> + <UserProfile name={name} email={email} setLoading={setIsLoading} /> + </div> + {/* navigation menu */} <div className="flex flex-col space-y-2"> <h4 className="text-xs font-semibold text-gray-500"> diff --git a/compass/components/resource/UserProfile.tsx b/compass/components/resource/UserProfile.tsx index ee88eae..3d9f544 100644 --- a/compass/components/resource/UserProfile.tsx +++ b/compass/components/resource/UserProfile.tsx @@ -1,49 +1,36 @@ import { useState } from "react"; import { signOut } from "@/app/auth/actions"; -import LoggingOut from "../auth/LoggingOut"; interface UserProfileProps { name: string; email: string; + setLoading: React.Dispatch<React.SetStateAction<boolean>>; } const handleClick = async ( event: React.MouseEvent<HTMLButtonElement>, setLoading: React.Dispatch<React.SetStateAction<boolean>> ) => { - setLoading(true); // Set loading state to true - - // Call signOut and wait for the process to complete before redirecting + setLoading(true); // Set loading to true await signOut(); - - // Once signOut is complete, the redirect should happen, but let's delay it to allow the loading state to be visible for a short time - setTimeout(() => { - // The signOut already handles the redirect, so we don't need to redirect here again. - setLoading(false); // Reset the loading state after the timeout (just in case) - }, 1000); // You can adjust this delay as needed + setLoading(false); // Reset loading after sign-out completes }; -export const UserProfile = ({ name, email }: UserProfileProps) => { - const [loading, setLoading] = useState(false); - - if (loading) { - // Show the "Logging out" screen while the sign-out process is in progress - return <LoggingOut />; - } - +export const UserProfile = ({ name, email, setLoading }: UserProfileProps) => { return ( <div className="flex flex-col items-start space-y-2"> <div className="flex flex-col"> - <span className="text-sm font-semibold text-gray-800">{name}</span> + <span className="text-sm font-semibold text-gray-800"> + {name} + </span> <span className="text-xs text-gray-500">{email}</span> </div> <button onClick={(event) => handleClick(event, setLoading)} className="text-red-600 font-semibold text-xs hover:underline mt-1" - disabled={loading} // Disable button while loading > - {loading ? "Signing out..." : "Sign out"} {/* Show appropriate text */} + Sign out </button> </div> ); -}; \ No newline at end of file +};