diff --git a/public/classroom_poc.html b/public/classroom_poc.html index 704967d..edf0300 100644 --- a/public/classroom_poc.html +++ b/public/classroom_poc.html @@ -235,6 +235,19 @@

const desksContainer = document.getElementById('desksContainer'); const toastContainer = document.getElementById('toastContainer'); + // Authentication utils + function getAuth() { + return { + token: localStorage.getItem('edu_token'), + user: JSON.parse(localStorage.getItem('edu_user') || 'null') + }; + } + + function isAuthenticated() { + const { token, user } = getAuth(); + return token && user; + } + // COORDINATE HELPERS // Positions are stored and transmitted as NORMALIZED values (0.0 – 1.0) // representing a fraction of the canvas width/height. @@ -414,6 +427,15 @@

// Join / Leave function joinClassroom() { + if (!isAuthenticated()) { + showToast('Please sign in to join the virtual classroom.', 'warning'); + // Preserve the user's intended destination so login.html can send + // them back here after authentication. + const returnTo = window.location.pathname + window.location.search; + sessionStorage.setItem('post_login_redirect', returnTo); + setTimeout(() => { window.location.href = '/login.html'; }, 800); + return; + } intentionalDisconnect = false; reconnectAttempts = 0; isSeated = false; diff --git a/public/index.html b/public/index.html index 9be30f3..15fc516 100644 --- a/public/index.html +++ b/public/index.html @@ -153,9 +153,14 @@

Global Virtual Classroom

21 learners inside - - Join Lobby Classroom - +
+ + +
diff --git a/public/js/layout.js b/public/js/layout.js index e016c9c..182ffbe 100644 --- a/public/js/layout.js +++ b/public/js/layout.js @@ -178,4 +178,16 @@ document.addEventListener('DOMContentLoaded', async () => { await inject('site-navbar', '/partials/navbar.html', updateAuthSection); await inject('site-footer', '/partials/footer.html'); updateDarkModeIcon(); +}); + +// Conditional rendering for the "Join Lobby Classroom" button. +// These elements only exist on the homepage, so we guard against nulls. +document.addEventListener('DOMContentLoaded', () => { + const loggedInEl = document.getElementById('join-logged-in'); + const notLoggedInEl = document.getElementById('join-not-logged-in'); + if (!loggedInEl || !notLoggedInEl) return; + + const authed = isAuthenticated(); + loggedInEl.style.display = authed ? 'flex' : 'none'; + notLoggedInEl.style.display = authed ? 'none' : 'flex'; }); \ No newline at end of file diff --git a/public/login.html b/public/login.html index 336beeb..cd7ad04 100644 --- a/public/login.html +++ b/public/login.html @@ -256,11 +256,33 @@

Create your : 'border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300'); } -// Store authentication data +// Store authentication data and handle post-login flow function storeAuth(data) { localStorage.setItem('edu_token', data.token); localStorage.setItem('edu_user', JSON.stringify(data.user)); - window.location.href = '/dashboard.html'; + + // Show success toast + showToast('Redirecting...'); + + // Wait a few seconds then redirect + setTimeout(() => { + handlePostLoginRedirect(); + }, 500); +} + +// Show success toast message +function showToast(msg) { + const toast = document.createElement('div'); + toast.className = 'fixed top-4 right-4 bg-green-50 dark:bg-green-900/30 border border-green-200 dark:border-green-800 rounded-lg p-4 text-green-700 dark:text-green-300 text-sm flex items-start gap-2 animate-pulse shadow-lg z-50'; + const icon = document.createElement('i'); + icon.className = 'fas fa-check-circle mt-0.5 flex-shrink-0'; + const span = document.createElement('span'); + span.textContent = msg; + toast.append(icon, span); + document.body.appendChild(toast); + setTimeout(() => { + toast.remove(); + }, 3000); } // Show error message @@ -274,12 +296,28 @@

Create your }, 5000); } +// Handle redirect after successful login +function handlePostLoginRedirect() { + const redirectUrl = sessionStorage.getItem('post_login_redirect'); + sessionStorage.removeItem('post_login_redirect'); + // Only honor same-origin, path-only redirects to prevent open-redirect abuse. + const safe = redirectUrl && /^\/(?!\/)/.test(redirectUrl); + window.location.href = safe ? redirectUrl : '/dashboard.html'; +} + // Handle tab parameter in URL const params = new URLSearchParams(location.search); if (params.get('tab') === 'register') { switchTab('register'); } +// Handle next parameter for post-login redirect. +// URLSearchParams.get() already performs percent-decoding — no need to decode again. +const nextParam = params.get('next'); +if (nextParam) { + sessionStorage.setItem('post_login_redirect', nextParam); +} + // Login form submission document.getElementById('form-login').addEventListener('submit', async e => { e.preventDefault();