loading for sign out

This commit is contained in:
emmalynf 2024-11-15 21:33:13 -05:00
parent e1fd04f963
commit 3ed505bcf3
5 changed files with 64 additions and 27 deletions

View File

@ -15,6 +15,8 @@ export default function RootLayout({
const [isSidebarOpen, setIsSidebarOpen] = useState(true); const [isSidebarOpen, setIsSidebarOpen] = useState(true);
const [user, setUser] = useState<User>(); const [user, setUser] = useState<User>();
const router = useRouter(); const router = useRouter();
const [loading, setLoading] = useState(true);
useEffect(() => { useEffect(() => {
async function getUser() { async function getUser() {
@ -35,6 +37,7 @@ export default function RootLayout({
); );
setUser(await userData.json()); setUser(await userData.json());
setLoading(false);
} }
getUser(); getUser();
@ -50,6 +53,7 @@ export default function RootLayout({
setIsSidebarOpen={setIsSidebarOpen} setIsSidebarOpen={setIsSidebarOpen}
isSidebarOpen={isSidebarOpen} isSidebarOpen={isSidebarOpen}
isAdmin={user.role === Role.ADMIN} isAdmin={user.role === Role.ADMIN}
loading={loading}
/> />
<div <div
className={`flex-1 transition duration-300 ease-in-out ${ className={`flex-1 transition duration-300 ease-in-out ${

View File

@ -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 */
}
}

View File

@ -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;

View File

@ -1,4 +1,4 @@
import React from "react"; import React, { useState } from "react";
import { import {
HomeIcon, HomeIcon,
ChevronDoubleLeftIcon, ChevronDoubleLeftIcon,
@ -9,7 +9,9 @@ import {
LockClosedIcon, LockClosedIcon,
} from "@heroicons/react/24/solid"; } from "@heroicons/react/24/solid";
import { SidebarItem } from "./SidebarItem"; import { SidebarItem } from "./SidebarItem";
import styles from "./LoadingIcon.module.css"
import { UserProfile } from "../resource/UserProfile"; import { UserProfile } from "../resource/UserProfile";
import LoadingIcon from "./LoadingIcon";
interface SidebarProps { interface SidebarProps {
setIsSidebarOpen: React.Dispatch<React.SetStateAction<boolean>>; setIsSidebarOpen: React.Dispatch<React.SetStateAction<boolean>>;
@ -17,6 +19,7 @@ interface SidebarProps {
name: string; name: string;
email: string; email: string;
isAdmin: boolean; isAdmin: boolean;
loading: boolean;
} }
const Sidebar: React.FC<SidebarProps> = ({ const Sidebar: React.FC<SidebarProps> = ({
@ -25,7 +28,9 @@ const Sidebar: React.FC<SidebarProps> = ({
name, name,
email, email,
isAdmin: admin, isAdmin: admin,
loading,
}) => { }) => {
const [isLoading, setIsLoading] = useState(false);
return ( return (
<> <>
{/* Button to open the sidebar. */} {/* Button to open the sidebar. */}
@ -62,11 +67,18 @@ const Sidebar: React.FC<SidebarProps> = ({
</button> </button>
</div> </div>
<div className="flex flex-col space-y-8"> {/* Loading indicator*/}
{/* user + logout button */} {isLoading && (
<div className="flex items-center p-4 space-x-2 border border-gray-200 rounded-md "> <div className="fixed top-2 left-2">
<UserProfile name={name} email={email} /> <LoadingIcon/>{/* Spinner */}
</div> </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 */} {/* navigation menu */}
<div className="flex flex-col space-y-2"> <div className="flex flex-col space-y-2">
<h4 className="text-xs font-semibold text-gray-500"> <h4 className="text-xs font-semibold text-gray-500">

View File

@ -1,48 +1,35 @@
import { useState } from "react"; import { useState } from "react";
import { signOut } from "@/app/auth/actions"; import { signOut } from "@/app/auth/actions";
import LoggingOut from "../auth/LoggingOut";
interface UserProfileProps { interface UserProfileProps {
name: string; name: string;
email: string; email: string;
setLoading: React.Dispatch<React.SetStateAction<boolean>>;
} }
const handleClick = async ( const handleClick = async (
event: React.MouseEvent<HTMLButtonElement>, event: React.MouseEvent<HTMLButtonElement>,
setLoading: React.Dispatch<React.SetStateAction<boolean>> setLoading: React.Dispatch<React.SetStateAction<boolean>>
) => { ) => {
setLoading(true); // Set loading state to true setLoading(true); // Set loading to true
// Call signOut and wait for the process to complete before redirecting
await signOut(); await signOut();
setLoading(false); // Reset loading after sign-out completes
// 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
}; };
export const UserProfile = ({ name, email }: UserProfileProps) => { export const UserProfile = ({ name, email, setLoading }: UserProfileProps) => {
const [loading, setLoading] = useState(false);
if (loading) {
// Show the "Logging out" screen while the sign-out process is in progress
return <LoggingOut />;
}
return ( return (
<div className="flex flex-col items-start space-y-2"> <div className="flex flex-col items-start space-y-2">
<div className="flex flex-col"> <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> <span className="text-xs text-gray-500">{email}</span>
</div> </div>
<button <button
onClick={(event) => handleClick(event, setLoading)} onClick={(event) => handleClick(event, setLoading)}
className="text-red-600 font-semibold text-xs hover:underline mt-1" 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> </button>
</div> </div>
); );