diff --git a/compass/README.md b/compass/README.md index 5ce4a7c..c403366 100644 --- a/compass/README.md +++ b/compass/README.md @@ -24,8 +24,8 @@ This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-opti To learn more about Next.js, take a look at the following resources: -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! diff --git a/compass/app/home/layout.tsx b/compass/app/home/layout.tsx index 236616e..b98493c 100644 --- a/compass/app/home/layout.tsx +++ b/compass/app/home/layout.tsx @@ -15,6 +15,7 @@ export default function RootLayout({ const [isSidebarOpen, setIsSidebarOpen] = useState(true); const [user, setUser] = useState(); const router = useRouter(); + const [loading, setLoading] = useState(true); useEffect(() => { async function getUser() { @@ -35,6 +36,7 @@ export default function RootLayout({ ); setUser(await userData.json()); + setLoading(false); } getUser(); @@ -50,6 +52,7 @@ export default function RootLayout({ setIsSidebarOpen={setIsSidebarOpen} isSidebarOpen={isSidebarOpen} isAdmin={user.role === Role.ADMIN} + loading={loading} />
(null); // Initialize user as null + const router = useRouter(); + + useEffect(() => { + async function getUser() { + const supabase = createClient(); + + const { data, error } = await supabase.auth.getUser(); + + if (error || !data?.user) { + console.log("User not logged in or error fetching user"); + router.push("/auth/login"); + return; + } + + const userData = await fetch( + `${process.env.NEXT_PUBLIC_HOST}/api/user?uuid=${data.user.id}` + ); + + const user: User = await userData.json(); + setUser(user); // Set user data after fetching + } + + getUser(); + }, [router]); + + if (!user) { + return ; // Show loading screen while the user is being fetched + } + + return ( +
+ {/* Sidebar is shared across all pages */} + + + {/* Page content */} +
+ {children} {/* Render page-specific content here */} +
+
+ ); +} diff --git a/compass/components/Sidebar/LoadingIcon.module.css b/compass/components/Sidebar/LoadingIcon.module.css new file mode 100644 index 0000000..7c2947e --- /dev/null +++ b/compass/components/Sidebar/LoadingIcon.module.css @@ -0,0 +1,19 @@ +/* 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..508d4dc --- /dev/null +++ b/compass/components/Sidebar/LoadingIcon.tsx @@ -0,0 +1,14 @@ +// components/Loading.js +import styles from "./LoadingIcon.module.css"; + +const LoadingIcon = () => { + return ( +
+
+
+
+
+ ); +}; + +export default LoadingIcon; diff --git a/compass/components/Sidebar/Sidebar.tsx b/compass/components/Sidebar/Sidebar.tsx index d82ab69..7ab2135 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>; @@ -17,6 +19,7 @@ interface SidebarProps { name: string; email: string; isAdmin: boolean; + loading: boolean; } const Sidebar: React.FC = ({ @@ -25,7 +28,9 @@ const Sidebar: React.FC = ({ name, email, isAdmin: admin, + loading, }) => { + const [isLoading, setIsLoading] = useState(false); return ( <> {/* Button to open the sidebar. */} @@ -62,11 +67,22 @@ const Sidebar: React.FC = ({
-
- {/* user + logout button */} -
- + {/* Loading indicator*/} + {isLoading && ( +
+
+ )} + +
+
+ +
+ {/* navigation menu */}

@@ -79,6 +95,7 @@ const Sidebar: React.FC = ({ text="Admin" active={true} redirect="/admin" + onClick={setIsLoading} /> )} @@ -87,24 +104,28 @@ const Sidebar: React.FC = ({ text="Home" active={true} redirect="/home" + onClick={setIsLoading} /> } text="Resources" active={true} redirect="/resource" + onClick={setIsLoading} /> } text="Services" active={true} redirect="/service" + onClick={setIsLoading} /> } text="Training Manuals" active={true} redirect="/training-manuals" + onClick={setIsLoading} />

diff --git a/compass/components/Sidebar/SidebarItem.tsx b/compass/components/Sidebar/SidebarItem.tsx index 34d3541..475f7b5 100644 --- a/compass/components/Sidebar/SidebarItem.tsx +++ b/compass/components/Sidebar/SidebarItem.tsx @@ -5,6 +5,7 @@ interface SidebarItemProps { text: string; active: boolean; redirect: string; + onClick: React.Dispatch>; } export const SidebarItem: React.FC = ({ @@ -12,9 +13,11 @@ export const SidebarItem: React.FC = ({ text, active, redirect, + onClick, }) => { return ( onClick(true)} href={redirect} className={ active diff --git a/compass/components/auth/LoggingOut.tsx b/compass/components/auth/LoggingOut.tsx new file mode 100644 index 0000000..8915e23 --- /dev/null +++ b/compass/components/auth/LoggingOut.tsx @@ -0,0 +1,22 @@ +// components/LoggingOut.js +import styles from "./Loading.module.css"; +import Image from "next/image"; + +const LoggingOut = () => { + return ( +
+
+ Compass Center logo. +

Signing out...

+
+
+
+ ); +}; + +export default LoggingOut; diff --git a/compass/components/resource/UserProfile.tsx b/compass/components/resource/UserProfile.tsx index d2780a6..6d3c291 100644 --- a/compass/components/resource/UserProfile.tsx +++ b/compass/components/resource/UserProfile.tsx @@ -1,15 +1,21 @@ +import { useState } from "react"; import { signOut } from "@/app/auth/actions"; interface UserProfileProps { name: string; email: string; + setLoading: React.Dispatch>; } -const handleClick = async (event: React.MouseEvent) => { +const handleClick = async ( + event: React.MouseEvent, + setLoading: React.Dispatch> +) => { + setLoading(true); await signOut(); }; -export const UserProfile = ({ name, email }: UserProfileProps) => { +export const UserProfile = ({ name, email, setLoading }: UserProfileProps) => { return (
@@ -19,7 +25,7 @@ export const UserProfile = ({ name, email }: UserProfileProps) => { {email}