diff --git a/src/app/(protected)/profile/page.tsx b/src/app/(protected)/profile/page.tsx index fdf52b41..5077228c 100644 --- a/src/app/(protected)/profile/page.tsx +++ b/src/app/(protected)/profile/page.tsx @@ -38,11 +38,51 @@ import { Lock, GraduationCap, HelpCircle, + Shield, } from "lucide-react"; import { Roofing, Room } from "@mui/icons-material"; +import { jwtDecode } from "jwt-decode"; + +// Role definitions matching AuthGuard +enum Role { + NONE = 0, + VOLUNTEER = 1, + TEAM = 2, + EXEC = 3, + TECH = 4, + FINANCE = 5, +} + +// Utility to get user role from token +function getUserRole(token: string | undefined): number { + if (!token) return Role.NONE; + + try { + const decoded: any = jwtDecode(token); + const productionRole = decoded.claims?.production; + const stagingRole = decoded.claims?.staging; + return productionRole ?? stagingRole ?? Role.NONE; + } catch (error) { + console.error("Error decoding token:", error); + return Role.NONE; + } +} + +// Get role name for display +function getRoleName(role: number): string { + const roleNames: { [key: number]: string } = { + [Role.NONE]: "Participant", + [Role.VOLUNTEER]: "Volunteer", + [Role.TEAM]: "Team Member", + [Role.EXEC]: "Executive", + [Role.TECH]: "Tech Team", + [Role.FINANCE]: "Finance", + }; + return roleNames[role] || "Unknown"; +} export default function Profile() { - const { isAuthenticated, user, logout, isLoading } = useFirebase(); + const { isAuthenticated, user, logout, isLoading, token } = useFirebase(); const router = useRouter(); const { isLoading: isUserLoading, data: userData } = useUserInfoMe(); const { data: teams } = useAllTeams(); @@ -60,14 +100,21 @@ export default function Profile() { // Feature flag check for HelpDesk const { data: helpDeskFlag } = useFlagState("HelpDesk"); + // Check if user is an organizer (role > 0) + const userRole = getUserRole(token); + const isOrganizer = userRole > Role.NONE; + const toggleQRCode = () => setShowQRCode((prev) => !prev); useEffect(() => { // if user data is still loading, do not redirect if (isUserLoading) return; - if (!userData || !userData.registration) router.push("/register"); - }, [userData, router]); + // Only redirect to registration if user is a participant (not an organizer) and not registered + if (!isOrganizer && (!userData || !userData.registration)) { + router.push("/register"); + } + }, [userData, router, isUserLoading, isOrganizer]); // Handle add-to-Google Wallet click const handleAddToGoogleWallet = async () => { @@ -232,10 +279,11 @@ export default function Profile() { {userData?.firstName && userData?.lastName ? `${userData.firstName} ${userData.lastName}` - : "Profile"} + : user.email || "Profile"} - - HackPSU Participant + + {isOrganizer && } + {isOrganizer ? `HackPSU ${getRoleName(userRole)}` : "HackPSU Participant"} @@ -243,6 +291,13 @@ export default function Profile() { {user.email} + {isOrganizer && ( +
+

+ You are viewing this profile as an organizer. Participant actions are disabled. +

+
+ )}
@@ -315,8 +370,12 @@ export default function Profile() { alt="Add to Google Wallet" width={200} height={60} - className="cursor-pointer hover:opacity-80 transition-opacity duration-200" - onClick={handleAddToGoogleWallet} + className={`transition-opacity duration-200 ${ + isOrganizer + ? "opacity-30 cursor-not-allowed" + : "cursor-pointer hover:opacity-80" + }`} + onClick={isOrganizer ? undefined : handleAddToGoogleWallet} priority /> )} @@ -333,8 +392,12 @@ export default function Profile() { alt="Add to Apple Wallet" width={200} height={60} - className="cursor-pointer hover:opacity-80 transition-opacity duration-200" - onClick={handleAddToAppleWallet} + className={`transition-opacity duration-200 ${ + isOrganizer + ? "opacity-30 cursor-not-allowed" + : "cursor-pointer hover:opacity-80" + }`} + onClick={isOrganizer ? undefined : handleAddToAppleWallet} priority /> )} @@ -385,6 +448,7 @@ export default function Profile() { className="w-full" variant="default" size="lg" + disabled={isOrganizer} > Manage Team @@ -394,6 +458,7 @@ export default function Profile() { className="w-full" variant="default" size="lg" + disabled={isOrganizer} > Reserve Room @@ -402,13 +467,16 @@ export default function Profile() { ) : ( <>

- You're not part of any team yet. + {isOrganizer + ? "Team management is for participants only." + : "You're not part of any team yet."}