redefined logout fix

This commit is contained in:
chark1es 2025-04-05 03:24:10 -07:00
parent 961ef1437a
commit 3533dc8048
3 changed files with 1002 additions and 869 deletions

View file

@ -33,6 +33,9 @@ export const GET: APIRoute = async ({ request, redirect }) => {
// Make a POST request to the Logto session end endpoint with the redirect in the body // Make a POST request to the Logto session end endpoint with the redirect in the body
const logoutUrl = `${logtoEndpoint}/oidc/session/end`; const logoutUrl = `${logtoEndpoint}/oidc/session/end`;
console.log(`Using Logto endpoint: ${logtoEndpoint}`);
console.log(`Full logout URL: ${logoutUrl}`);
try { try {
// Try to make a POST request with the redirect in the body and client ID // Try to make a POST request with the redirect in the body and client ID
const response = await fetch(logoutUrl, { const response = await fetch(logoutUrl, {

View file

@ -32,8 +32,8 @@ const components = Object.fromEntries(
); );
// console.log(`Loaded component: ${section.component}`); // Debug log // console.log(`Loaded component: ${section.component}`); // Debug log
return [section.component, component.default]; return [section.component, component.default];
}), })
), )
); );
// console.log("Available components:", Object.keys(components)); // Debug log // console.log("Available components:", Object.keys(components)); // Debug log
@ -52,7 +52,10 @@ const components = Object.fromEntries(
</head> </head>
<body class="bg-base-200"> <body class="bg-base-200">
<!-- First Time Login Manager - This handles the onboarding popup for new users --> <!-- First Time Login Manager - This handles the onboarding popup for new users -->
<FirstTimeLoginManager client:load logtoApiEndpoint={logtoApiEndpoint} /> <FirstTimeLoginManager
client:load
logtoApiEndpoint={logtoApiEndpoint}
/>
<div class="flex h-screen"> <div class="flex h-screen">
<!-- Sidebar --> <!-- Sidebar -->
@ -72,19 +75,33 @@ const components = Object.fromEntries(
<!-- User Profile --> <!-- User Profile -->
<div class="p-6 border-b border-base-200"> <div class="p-6 border-b border-base-200">
<!-- Loading State --> <!-- Loading State -->
<div id="userProfileSkeleton" class="flex items-center gap-4"> <div
id="userProfileSkeleton"
class="flex items-center gap-4"
>
<div class="avatar flex items-center justify-center"> <div class="avatar flex items-center justify-center">
<div class="w-12 h-12 rounded-xl bg-base-300 animate-pulse"></div> <div
class="w-12 h-12 rounded-xl bg-base-300 animate-pulse"
>
</div>
</div> </div>
<div class="flex-1"> <div class="flex-1">
<div class="h-6 w-32 bg-base-300 animate-pulse rounded mb-2"> <div
class="h-6 w-32 bg-base-300 animate-pulse rounded mb-2"
>
</div>
<div
class="h-5 w-20 bg-base-300 animate-pulse rounded"
>
</div> </div>
<div class="h-5 w-20 bg-base-300 animate-pulse rounded"></div>
</div> </div>
</div> </div>
<!-- Signed Out State --> <!-- Signed Out State -->
<div id="userProfileSignedOut" class="flex items-center gap-4 hidden"> <div
id="userProfileSignedOut"
class="flex items-center gap-4 hidden"
>
<div class="avatar flex items-center justify-center"> <div class="avatar flex items-center justify-center">
<div <div
class="w-12 h-12 rounded-xl bg-base-300 text-base-content/30 flex items-center justify-center" class="w-12 h-12 rounded-xl bg-base-300 text-base-content/30 flex items-center justify-center"
@ -93,15 +110,22 @@ const components = Object.fromEntries(
</div> </div>
</div> </div>
<div> <div>
<h3 class="font-medium text-lg text-base-content/70"> <h3
class="font-medium text-lg text-base-content/70"
>
Signed Out Signed Out
</h3> </h3>
<div class="badge badge-outline mt-1 opacity-50">Guest</div> <div class="badge badge-outline mt-1 opacity-50">
Guest
</div>
</div> </div>
</div> </div>
<!-- Actual Profile --> <!-- Actual Profile -->
<div id="userProfileSummary" class="flex items-center gap-4 hidden"> <div
id="userProfileSummary"
class="flex items-center gap-4 hidden"
>
<div class="avatar flex items-center justify-center"> <div class="avatar flex items-center justify-center">
<div <div
class="w-12 h-12 rounded-xl bg-[#06659d] text-white ring ring-base-200 ring-offset-base-100 ring-offset-2 inline-flex items-center justify-center" class="w-12 h-12 rounded-xl bg-[#06659d] text-white ring ring-base-200 ring-offset-base-100 ring-offset-2 inline-flex items-center justify-center"
@ -113,7 +137,9 @@ const components = Object.fromEntries(
</div> </div>
</div> </div>
<div> <div>
<h3 class="font-medium text-lg" id="userName">Loading...</h3> <h3 class="font-medium text-lg" id="userName">
Loading...
</h3>
<div <div
class="badge badge-outline mt-1 border-[#06659d] text-[#06659d]" class="badge badge-outline mt-1 border-[#06659d] text-[#06659d]"
id="userRole" id="userRole"
@ -125,8 +151,12 @@ const components = Object.fromEntries(
</div> </div>
<!-- Navigation --> <!-- Navigation -->
<nav class="flex-1 overflow-y-auto scrollbar-hide py-6"> <nav
<ul class="menu gap-2 px-4 text-base-content/80"> class="flex-1 overflow-y-auto scrollbar-hide py-6 flex flex-col"
>
<ul
class="menu gap-2 px-4 text-base-content/80 flex-1 flex flex-col"
>
<!-- Loading Skeleton --> <!-- Loading Skeleton -->
<div id="menuLoadingSkeleton"> <div id="menuLoadingSkeleton">
{ {
@ -152,43 +182,80 @@ const components = Object.fromEntries(
<div id="actualMenu" class="hidden"> <div id="actualMenu" class="hidden">
{ {
Object.entries(dashboardConfig.categories).map( Object.entries(dashboardConfig.categories).map(
([categoryKey, category]: [string, any]) => ( ([categoryKey, category]: [
string,
any,
]) => (
<> <>
<li <li
class={`menu-title font-medium opacity-70 ${ class={`menu-title font-medium opacity-70 ${
category.role && category.role !== "none" category.role &&
category.role !== "none"
? "hidden" ? "hidden"
: "" : ""
}`} }`}
data-role-required={category.role || "none"} data-role-required={
category.role || "none"
}
> >
<span>{category.title}</span> <span>{category.title}</span>
</li> </li>
{category.sections.map((sectionKey: string) => { {category.sections.map(
const section = dashboardConfig.sections[sectionKey]; (sectionKey: string) => {
const section =
dashboardConfig
.sections[
sectionKey
];
return ( return (
<li <li
class={ class={
section.role && section.role !== "none" section.role &&
section.role !==
"none"
? "hidden" ? "hidden"
: "" : ""
} }
data-role-required={section.role} data-role-required={
section.role
}
> >
<button <button
class={`dashboard-nav-btn gap-4 transition-all duration-200 outline-none focus:outline-none hover:bg-opacity-5 ${section.class || ""}`} class={`dashboard-nav-btn gap-4 transition-all duration-200 outline-none focus:outline-none hover:bg-opacity-5 ${section.class || ""}`}
data-section={sectionKey} data-section={
sectionKey
}
> >
<Icon name={section.icon} class="h-5 w-5" /> <Icon
name={
section.icon
}
class="h-5 w-5"
/>
{section.title} {section.title}
</button> </button>
</li> </li>
); );
})} }
)}
</> </>
), )
) )
} }
{/* Add Logout Button to the bottom of the menu */}
<li class="mt-auto">
<button
class="dashboard-nav-btn gap-4 transition-all duration-200 outline-none focus:outline-none hover:bg-opacity-5 text-error"
data-section="logout"
>
<Icon
name="heroicons:arrow-left-on-rectangle"
class="h-5 w-5"
/>
Logout
</button>
</li>
</div> </div>
</ul> </ul>
</nav> </nav>
@ -199,10 +266,15 @@ const components = Object.fromEntries(
class="flex-1 overflow-x-hidden overflow-y-auto bg-base-200 w-full xl:w-[calc(100%-20rem)]" class="flex-1 overflow-x-hidden overflow-y-auto bg-base-200 w-full xl:w-[calc(100%-20rem)]"
> >
<!-- Mobile Header --> <!-- Mobile Header -->
<header class="bg-base-100 p-4 shadow-md xl:hidden sticky top-0 z-40"> <header
class="bg-base-100 p-4 shadow-md xl:hidden sticky top-0 z-40"
>
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<button id="mobileSidebarToggle" class="btn btn-square btn-ghost"> <button
id="mobileSidebarToggle"
class="btn btn-square btn-ghost"
>
<Icon name="heroicons:bars-3" class="h-6 w-6" /> <Icon name="heroicons:bars-3" class="h-6 w-6" />
</button> </button>
<h1 class="text-xl font-bold">IEEE UCSD</h1> <h1 class="text-xl font-bold">IEEE UCSD</h1>
@ -214,8 +286,11 @@ const components = Object.fromEntries(
<div class="p-4 md:p-6 max-w-[1600px] mx-auto"> <div class="p-4 md:p-6 max-w-[1600px] mx-auto">
<!-- Loading State --> <!-- Loading State -->
<div id="pageLoadingState" class="w-full"> <div id="pageLoadingState" class="w-full">
<div class="flex flex-col items-center justify-center p-4 sm:p-8"> <div
<div class="loading loading-spinner loading-lg"></div> class="flex flex-col items-center justify-center p-4 sm:p-8"
>
<div class="loading loading-spinner loading-lg">
</div>
<p class="mt-4 opacity-70">Loading dashboard...</p> <p class="mt-4 opacity-70">Loading dashboard...</p>
</div> </div>
</div> </div>
@ -241,7 +316,9 @@ const components = Object.fromEntries(
<!-- Not Authenticated State --> <!-- Not Authenticated State -->
<div id="notAuthenticatedState" class="hidden w-full"> <div id="notAuthenticatedState" class="hidden w-full">
<div class="card bg-base-100 shadow-xl mx-2 sm:mx-0"> <div class="card bg-base-100 shadow-xl mx-2 sm:mx-0">
<div class="card-body items-center text-center p-4 sm:p-8"> <div
class="card-body items-center text-center p-4 sm:p-8"
>
<div class="mb-4 sm:mb-6"> <div class="mb-4 sm:mb-6">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -258,9 +335,11 @@ const components = Object.fromEntries(
<h2 class="card-title text-xl sm:text-2xl mb-2"> <h2 class="card-title text-xl sm:text-2xl mb-2">
Sign in to Access Dashboard Sign in to Access Dashboard
</h2> </h2>
<p class="opacity-70 mb-4 sm:mb-6 text-sm sm:text-base"> <p
Please sign in with your IEEE UCSD account to access the class="opacity-70 mb-4 sm:mb-6 text-sm sm:text-base"
dashboard. >
Please sign in with your IEEE UCSD account
to access the dashboard.
</p> </p>
<button <button
class="login-button btn btn-primary btn-lg gap-2 w-full sm:w-auto" class="login-button btn btn-primary btn-lg gap-2 w-full sm:w-auto"
@ -292,12 +371,14 @@ const components = Object.fromEntries(
// Skip if no component is defined // Skip if no component is defined
if (!section.component) return null; if (!section.component) return null;
const Component = components[section.component]; const Component =
components[section.component];
return ( return (
<div <div
id={`${sectionKey}Section`} id={`${sectionKey}Section`}
class={`dashboard-section hidden ${ class={`dashboard-section hidden ${
section.role && section.role !== "none" section.role &&
section.role !== "none"
? "role-restricted" ? "role-restricted"
: "" : ""
}`} }`}
@ -306,7 +387,7 @@ const components = Object.fromEntries(
<Component /> <Component />
</div> </div>
); );
}, }
) )
} }
</div> </div>
@ -335,10 +416,11 @@ const components = Object.fromEntries(
} }
// Initialize page state // Initialize page state
const pageLoadingState = document.getElementById("pageLoadingState"); const pageLoadingState =
document.getElementById("pageLoadingState");
const pageErrorState = document.getElementById("pageErrorState"); const pageErrorState = document.getElementById("pageErrorState");
const notAuthenticatedState = document.getElementById( const notAuthenticatedState = document.getElementById(
"notAuthenticatedState", "notAuthenticatedState"
); );
const mainContent = document.getElementById("mainContent"); const mainContent = document.getElementById("mainContent");
const sidebar = document.querySelector("aside"); const sidebar = document.querySelector("aside");
@ -369,9 +451,11 @@ const components = Object.fromEntries(
} }
// For non-sponsor roles, handle normally // For non-sponsor roles, handle normally
document.querySelectorAll("[data-role-required]").forEach((element) => { document
.querySelectorAll("[data-role-required]")
.forEach((element) => {
const requiredRole = element.getAttribute( const requiredRole = element.getAttribute(
"data-role-required", "data-role-required"
) as OfficerStatus; ) as OfficerStatus;
// Skip elements that don't have a role requirement // Skip elements that don't have a role requirement
@ -381,7 +465,10 @@ const components = Object.fromEntries(
} }
// Check if user has permission for this role // Check if user has permission for this role
const hasPermission = hasAccess(officerStatus, requiredRole); const hasPermission = hasAccess(
officerStatus,
requiredRole
);
// Only show elements if user has permission // Only show elements if user has permission
element.classList.toggle("hidden", !hasPermission); element.classList.toggle("hidden", !hasPermission);
@ -412,7 +499,9 @@ const components = Object.fromEntries(
const cookie = cookies[i]; const cookie = cookies[i];
const eqPos = cookie.indexOf("="); const eqPos = cookie.indexOf("=");
const name = const name =
eqPos > -1 ? cookie.substring(0, eqPos).trim() : cookie.trim(); eqPos > -1
? cookie.substring(0, eqPos).trim()
: cookie.trim();
if (!name) continue; // Skip empty cookie names if (!name) continue; // Skip empty cookie names
@ -490,22 +579,27 @@ const components = Object.fromEntries(
.getElementById("confirmLogout") .getElementById("confirmLogout")
?.addEventListener("click", async () => { ?.addEventListener("click", async () => {
// Show loading state // Show loading state
const spinner = document.getElementById("logoutSpinner"); const spinner =
document.getElementById("logoutSpinner");
const text = document.getElementById("logoutText"); const text = document.getElementById("logoutText");
const confirmBtn = document.getElementById("confirmLogout"); const confirmBtn =
const cancelBtn = document.getElementById("cancelLogout"); document.getElementById("confirmLogout");
const cancelBtn =
document.getElementById("cancelLogout");
if (spinner) spinner.classList.remove("hidden"); if (spinner) spinner.classList.remove("hidden");
if (text) text.textContent = "Logging out..."; if (text) text.textContent = "Logging out...";
if (confirmBtn) confirmBtn.setAttribute("disabled", "true"); if (confirmBtn)
if (cancelBtn) cancelBtn.setAttribute("disabled", "true"); confirmBtn.setAttribute("disabled", "true");
if (cancelBtn)
cancelBtn.setAttribute("disabled", "true");
try { try {
// Log the logout action // Log the logout action
await logger.send( await logger.send(
"logout", "logout",
"auth", "auth",
"User logged out from dashboard menu", "User logged out from dashboard menu"
); );
// Log out from PocketBase using the Authentication class // Log out from PocketBase using the Authentication class
@ -518,33 +612,32 @@ const components = Object.fromEntries(
// Delete all cookies to ensure Logto is logged out // Delete all cookies to ensure Logto is logged out
deleteAllCookies(); deleteAllCookies();
// Specifically target auth.ieeeucsd.org cookies with different approaches // Redirect to our API logout endpoint which will properly sign out from Logto
document.cookie =
"logto=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;domain=auth.ieeeucsd.org";
document.cookie =
"logto=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;domain=.ieeeucsd.org";
document.cookie =
"logto=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/";
// Direct logout from Logto by redirecting to our API endpoint
// This will handle the Logto session end with proper redirect back to dashboard
window.location.href = "/api/logout"; window.location.href = "/api/logout";
return; // Stop execution here as we're redirecting return; // Stop execution here as we're redirecting
} catch (error) { } catch (error) {
console.error("Error during logout:", error); console.error("Error during logout:", error);
// Show error message if toast is available // Show error message if toast is available
if (window.toast && typeof window.toast === "function") { if (
window.toast("Failed to log out. Please try again.", { window.toast &&
typeof window.toast === "function"
) {
window.toast(
"Failed to log out. Please try again.",
{
type: "error", type: "error",
}); }
);
} }
// Reset button state // Reset button state
if (spinner) spinner.classList.add("hidden"); if (spinner) spinner.classList.add("hidden");
if (text) text.textContent = "Log Out"; if (text) text.textContent = "Log Out";
if (confirmBtn) confirmBtn.removeAttribute("disabled"); if (confirmBtn)
if (cancelBtn) cancelBtn.removeAttribute("disabled"); confirmBtn.removeAttribute("disabled");
if (cancelBtn)
cancelBtn.removeAttribute("disabled");
// Close the modal // Close the modal
if (modal) (modal as HTMLDialogElement).close(); if (modal) (modal as HTMLDialogElement).close();
@ -558,8 +651,10 @@ const components = Object.fromEntries(
// Handle navigation // Handle navigation
const handleNavigation = () => { const handleNavigation = () => {
const navButtons = document.querySelectorAll(".dashboard-nav-btn"); const navButtons =
const sections = document.querySelectorAll(".dashboard-section"); document.querySelectorAll(".dashboard-nav-btn");
const sections =
document.querySelectorAll(".dashboard-section");
const mainContentDiv = document.getElementById("mainContent"); const mainContentDiv = document.getElementById("mainContent");
// Ensure mainContent is visible // Ensure mainContent is visible
@ -592,7 +687,8 @@ const components = Object.fromEntries(
// Show selected section // Show selected section
const sectionId = `${sectionKey}Section`; const sectionId = `${sectionKey}Section`;
const targetSection = document.getElementById(sectionId); const targetSection =
document.getElementById(sectionId);
if (targetSection) { if (targetSection) {
targetSection.classList.remove("hidden"); targetSection.classList.remove("hidden");
// console.log(`Showing section: ${sectionId}`); // Debug log // console.log(`Showing section: ${sectionId}`); // Debug log
@ -602,7 +698,8 @@ const components = Object.fromEntries(
if (window.innerWidth < 1024 && sidebar) { if (window.innerWidth < 1024 && sidebar) {
sidebar.classList.add("-translate-x-full"); sidebar.classList.add("-translate-x-full");
document.body.classList.remove("overflow-hidden"); document.body.classList.remove("overflow-hidden");
const overlay = document.getElementById("sidebarOverlay"); const overlay =
document.getElementById("sidebarOverlay");
overlay?.remove(); overlay?.remove();
} }
}); });
@ -647,7 +744,7 @@ const components = Object.fromEntries(
"", "",
{ {
fields: ["id", "type", "role"], fields: ["id", "type", "role"],
}, }
); );
if (officerRecords && officerRecords.items.length > 0) { if (officerRecords && officerRecords.items.length > 0) {
@ -689,7 +786,7 @@ const components = Object.fromEntries(
"", "",
{ {
fields: ["id", "company"], fields: ["id", "company"],
}, }
); );
if (sponsorRecords && sponsorRecords.items.length > 0) { if (sponsorRecords && sponsorRecords.items.length > 0) {
@ -723,7 +820,8 @@ const components = Object.fromEntries(
if (userName) userName.textContent = fallbackValues.name; if (userName) userName.textContent = fallbackValues.name;
if (userRole) userRole.textContent = fallbackValues.role; if (userRole) userRole.textContent = fallbackValues.role;
if (userInitials) userInitials.textContent = fallbackValues.initials; if (userInitials)
userInitials.textContent = fallbackValues.initials;
updateSectionVisibility("" as OfficerStatus); updateSectionVisibility("" as OfficerStatus);
} }
@ -731,16 +829,18 @@ const components = Object.fromEntries(
// Mobile sidebar toggle // Mobile sidebar toggle
const mobileSidebarToggle = document.getElementById( const mobileSidebarToggle = document.getElementById(
"mobileSidebarToggle", "mobileSidebarToggle"
); );
if (mobileSidebarToggle && sidebar) { if (mobileSidebarToggle && sidebar) {
const toggleSidebar = () => { const toggleSidebar = () => {
const isOpen = !sidebar.classList.contains("-translate-x-full"); const isOpen =
!sidebar.classList.contains("-translate-x-full");
if (isOpen) { if (isOpen) {
sidebar.classList.add("-translate-x-full"); sidebar.classList.add("-translate-x-full");
document.body.classList.remove("overflow-hidden"); document.body.classList.remove("overflow-hidden");
const overlay = document.getElementById("sidebarOverlay"); const overlay =
document.getElementById("sidebarOverlay");
overlay?.remove(); overlay?.remove();
} else { } else {
sidebar.classList.remove("-translate-x-full"); sidebar.classList.remove("-translate-x-full");
@ -775,7 +875,8 @@ const components = Object.fromEntries(
window.toast = originalToast; window.toast = originalToast;
// console.log("User not authenticated"); // console.log("User not authenticated");
if (pageLoadingState) pageLoadingState.classList.add("hidden"); if (pageLoadingState)
pageLoadingState.classList.add("hidden");
if (notAuthenticatedState) if (notAuthenticatedState)
notAuthenticatedState.classList.remove("hidden"); notAuthenticatedState.classList.remove("hidden");
return; return;
@ -784,28 +885,30 @@ const components = Object.fromEntries(
// Initialize auth sync for IndexedDB (for authenticated users) // Initialize auth sync for IndexedDB (for authenticated users)
await initAuthSync(); await initAuthSync();
if (pageLoadingState) pageLoadingState.classList.remove("hidden"); if (pageLoadingState)
pageLoadingState.classList.remove("hidden");
if (pageErrorState) pageErrorState.classList.add("hidden"); if (pageErrorState) pageErrorState.classList.add("hidden");
if (notAuthenticatedState) if (notAuthenticatedState)
notAuthenticatedState.classList.add("hidden"); notAuthenticatedState.classList.add("hidden");
// Show loading states // Show loading states
const userProfileSkeleton = document.getElementById( const userProfileSkeleton = document.getElementById(
"userProfileSkeleton", "userProfileSkeleton"
); );
const userProfileSignedOut = document.getElementById( const userProfileSignedOut = document.getElementById(
"userProfileSignedOut", "userProfileSignedOut"
); );
const userProfileSummary = const userProfileSummary =
document.getElementById("userProfileSummary"); document.getElementById("userProfileSummary");
const menuLoadingSkeleton = document.getElementById( const menuLoadingSkeleton = document.getElementById(
"menuLoadingSkeleton", "menuLoadingSkeleton"
); );
const actualMenu = document.getElementById("actualMenu"); const actualMenu = document.getElementById("actualMenu");
if (userProfileSkeleton) if (userProfileSkeleton)
userProfileSkeleton.classList.remove("hidden"); userProfileSkeleton.classList.remove("hidden");
if (userProfileSummary) userProfileSummary.classList.add("hidden"); if (userProfileSummary)
userProfileSummary.classList.add("hidden");
if (userProfileSignedOut) if (userProfileSignedOut)
userProfileSignedOut.classList.add("hidden"); userProfileSignedOut.classList.add("hidden");
if (menuLoadingSkeleton) if (menuLoadingSkeleton)
@ -816,11 +919,15 @@ const components = Object.fromEntries(
await updateUserProfile(user); await updateUserProfile(user);
// Show actual profile and hide skeleton // Show actual profile and hide skeleton
if (userProfileSkeleton) userProfileSkeleton.classList.add("hidden"); if (userProfileSkeleton)
if (userProfileSummary) userProfileSummary.classList.remove("hidden"); userProfileSkeleton.classList.add("hidden");
if (userProfileSummary)
userProfileSummary.classList.remove("hidden");
// Hide all sections first // Hide all sections first
document.querySelectorAll(".dashboard-section").forEach((section) => { document
.querySelectorAll(".dashboard-section")
.forEach((section) => {
section.classList.add("hidden"); section.classList.add("hidden");
}); });
@ -837,7 +944,7 @@ const components = Object.fromEntries(
"", "",
{ {
fields: ["id", "type", "role"], fields: ["id", "type", "role"],
}, }
); );
if (officerRecords && officerRecords.items.length > 0) { if (officerRecords && officerRecords.items.length > 0) {
@ -875,17 +982,23 @@ const components = Object.fromEntries(
"", "",
{ {
fields: ["id", "company"], fields: ["id", "company"],
}, }
); );
if (sponsorRecords && sponsorRecords.items.length > 0) { if (
sponsorRecords &&
sponsorRecords.items.length > 0
) {
officerStatus = "sponsor"; officerStatus = "sponsor";
} else { } else {
officerStatus = "none"; officerStatus = "none";
} }
} }
} catch (error) { } catch (error) {
console.error("Error determining officer status:", error); console.error(
"Error determining officer status:",
error
);
officerStatus = "none"; officerStatus = "none";
} }
@ -896,14 +1009,19 @@ const components = Object.fromEntries(
// Only sponsors get a different default view // Only sponsors get a different default view
if (officerStatus === "sponsor") { if (officerStatus === "sponsor") {
// For sponsors, show the sponsor dashboard // For sponsors, show the sponsor dashboard
defaultSection = document.getElementById("sponsorDashboardSection"); defaultSection = document.getElementById(
"sponsorDashboardSection"
);
defaultButton = document.querySelector( defaultButton = document.querySelector(
'[data-section="sponsorDashboard"]', '[data-section="sponsorDashboard"]'
); );
} else { } else {
// For all other users (including administrators), show the profile section // For all other users (including administrators), show the profile section
defaultSection = document.getElementById("profileSection"); defaultSection =
defaultButton = document.querySelector('[data-section="profile"]'); document.getElementById("profileSection");
defaultButton = document.querySelector(
'[data-section="profile"]'
);
// Log the default section for debugging // Log the default section for debugging
// console.log(`Setting default section to profile for user with role: ${officerStatus}`); // console.log(`Setting default section to profile for user with role: ${officerStatus}`);
@ -920,16 +1038,20 @@ const components = Object.fromEntries(
handleNavigation(); handleNavigation();
// Show actual menu and hide skeleton // Show actual menu and hide skeleton
if (menuLoadingSkeleton) menuLoadingSkeleton.classList.add("hidden"); if (menuLoadingSkeleton)
menuLoadingSkeleton.classList.add("hidden");
if (actualMenu) actualMenu.classList.remove("hidden"); if (actualMenu) actualMenu.classList.remove("hidden");
// Show main content and hide loading // Show main content and hide loading
if (mainContent) mainContent.classList.remove("hidden"); if (mainContent) mainContent.classList.remove("hidden");
if (pageLoadingState) pageLoadingState.classList.add("hidden"); if (pageLoadingState)
pageLoadingState.classList.add("hidden");
} catch (error) { } catch (error) {
console.error("Error initializing dashboard:", error); console.error("Error initializing dashboard:", error);
if (pageLoadingState) pageLoadingState.classList.add("hidden"); if (pageLoadingState)
if (pageErrorState) pageErrorState.classList.remove("hidden"); pageLoadingState.classList.add("hidden");
if (pageErrorState)
pageErrorState.classList.remove("hidden");
} }
}; };
@ -941,23 +1063,20 @@ const components = Object.fromEntries(
.querySelector(".login-button") .querySelector(".login-button")
?.addEventListener("click", async () => { ?.addEventListener("click", async () => {
try { try {
if (pageLoadingState) pageLoadingState.classList.remove("hidden"); if (pageLoadingState)
pageLoadingState.classList.remove("hidden");
if (notAuthenticatedState) if (notAuthenticatedState)
notAuthenticatedState.classList.add("hidden"); notAuthenticatedState.classList.add("hidden");
await auth.login(); await auth.login();
} catch (error) { } catch (error) {
console.error("Login error:", error); console.error("Login error:", error);
if (pageLoadingState) pageLoadingState.classList.add("hidden"); if (pageLoadingState)
if (pageErrorState) pageErrorState.classList.remove("hidden"); pageLoadingState.classList.add("hidden");
if (pageErrorState)
pageErrorState.classList.remove("hidden");
} }
}); });
// Handle logout button click
document.getElementById("logoutButton")?.addEventListener("click", () => {
auth.logout();
window.location.reload();
});
// Handle responsive sidebar // Handle responsive sidebar
if (sidebar) { if (sidebar) {
if (window.innerWidth < 1024) { if (window.innerWidth < 1024) {
@ -966,7 +1085,8 @@ const components = Object.fromEntries(
window.addEventListener("resize", () => { window.addEventListener("resize", () => {
if (window.innerWidth >= 1024) { if (window.innerWidth >= 1024) {
const overlay = document.getElementById("sidebarOverlay"); const overlay =
document.getElementById("sidebarOverlay");
if (overlay) { if (overlay) {
overlay.remove(); overlay.remove();
document.body.classList.remove("overflow-hidden"); document.body.classList.remove("overflow-hidden");

View file

@ -3,15 +3,25 @@ import Layout from "../layouts/Layout.astro";
const title = "Authenticating..."; const title = "Authenticating...";
--- ---
<main class="min-h-screen flex items-center justify-center"> <html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{title} | IEEE UCSD</title>
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
</head>
<body class="bg-base-200">
<main class="min-h-screen flex items-center justify-center">
<div id="content" class="text-center"> <div id="content" class="text-center">
<p class="text-2xl font-medium">Redirecting to dashboard...</p> <p class="text-2xl font-medium">Redirecting to dashboard...</p>
<div class="mt-4"> <div class="mt-4">
<div class="loading loading-spinner loading-lg"></div> <div class="loading loading-spinner loading-lg"></div>
</div> </div>
</div> </div>
</main> </main>
<script> <script>
import { RedirectHandler } from "../scripts/auth/RedirectHandler"; import { RedirectHandler } from "../scripts/auth/RedirectHandler";
new RedirectHandler(); new RedirectHandler();
</script> </script>
</body>
</html>