diff --git a/back/raw/main.ts b/back/raw/main.ts index 9440593..07d609d 100644 --- a/back/raw/main.ts +++ b/back/raw/main.ts @@ -126,28 +126,48 @@ app.setNotFoundHandler((request, reply) => { /* --------------STATIC------------- */ /* --------------------------------- */ -app.get('/partial/:page', async (req: any, reply: any) => { +async function checkAuth(request: any): Promise { + try { + await request.jwtVerify(); + return true; + } catch (error) { + return false; + } +} + +app.get('/partial/pages/:page', async (req: any, reply: any) => { const page = req.params.page; const loadpartial = req.headers['loadpartial'] === 'true'; - const dataSample = { name: 'Jonas' }; const layoutOption = loadpartial ? false : 'basic.ejs'; + const isAuthenticated = await checkAuth(req); if (page === 'game') { try { await req.jwtVerify(); } catch (error) { - return reply.code(401).view('pages/no_access.ejs', dataSample, { layout: layoutOption }); + return reply.code(401).view('partial/pages/no_access.ejs', { name: 'Freddy', isAuthenticated }, { layout: layoutOption }); } } - return reply.view(`pages/${page}.ejs`, dataSample, { layout: layoutOption }); + return reply.view(`partial/pages/${page}.ejs`, { name: 'Freddy', isAuthenticated }, { layout: layoutOption }); +}); +app.get('/menu', async (req: any, reply: any) => { + const isAuthenticated = await checkAuth(req); + const menuTemplate = isAuthenticated ? 'partial/menu/loggedin.ejs' : 'partial/menu/guest.ejs'; + return reply.view(menuTemplate, { name: 'Freddy' }); }); app.get('/', async (req: any, reply: any) => { - logger.info('GET /'); - return reply.view('pages/index.ejs', { name: 'Jonas' }, { - layout: 'basic.ejs' - }); + let isAuthenticated: boolean = false; + try { + await req.jwtVerify(); + isAuthenticated = true; + } + catch (error) { + isAuthenticated = false; + } + return reply.view('partial/pages/index.ejs', { name: 'Jonas', isAuthenticated }, { layout: 'basic.ejs' }); }); + startServer(); export { app }; diff --git a/front/css/styles.css b/front/css/styles.css index 6112be6..ff1452a 100644 --- a/front/css/styles.css +++ b/front/css/styles.css @@ -72,4 +72,9 @@ body.dark .text-gray-700 { body.dark .bg-white { background-color: #2d3748; /* dark background for dark mode */ +} + +button.active { + background-color: #0056b3; + border: 2px solid #fff; } \ No newline at end of file diff --git a/front/layouts/basic.ejs b/front/layouts/basic.ejs index 85d9907..a8768e9 100644 --- a/front/layouts/basic.ejs +++ b/front/layouts/basic.ejs @@ -12,24 +12,14 @@

Welcome to Transcendence

- + +
diff --git a/front/layouts/partial/menu/guest.ejs b/front/layouts/partial/menu/guest.ejs new file mode 100644 index 0000000..22ac772 --- /dev/null +++ b/front/layouts/partial/menu/guest.ejs @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/front/layouts/partial/menu/loggedin.ejs b/front/layouts/partial/menu/loggedin.ejs new file mode 100644 index 0000000..c1ab74c --- /dev/null +++ b/front/layouts/partial/menu/loggedin.ejs @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/front/layouts/pages/about.ejs b/front/layouts/partial/pages/about.ejs similarity index 100% rename from front/layouts/pages/about.ejs rename to front/layouts/partial/pages/about.ejs diff --git a/front/layouts/pages/game.ejs b/front/layouts/partial/pages/game.ejs similarity index 100% rename from front/layouts/pages/game.ejs rename to front/layouts/partial/pages/game.ejs diff --git a/front/layouts/pages/index.ejs b/front/layouts/partial/pages/index.ejs similarity index 100% rename from front/layouts/pages/index.ejs rename to front/layouts/partial/pages/index.ejs diff --git a/front/layouts/pages/login.ejs b/front/layouts/partial/pages/login.ejs similarity index 100% rename from front/layouts/pages/login.ejs rename to front/layouts/partial/pages/login.ejs diff --git a/front/layouts/pages/no_access.ejs b/front/layouts/partial/pages/no_access.ejs similarity index 100% rename from front/layouts/pages/no_access.ejs rename to front/layouts/partial/pages/no_access.ejs diff --git a/front/layouts/pages/profile.ejs b/front/layouts/partial/pages/profile.ejs similarity index 100% rename from front/layouts/pages/profile.ejs rename to front/layouts/partial/pages/profile.ejs diff --git a/front/layouts/pages/register.ejs b/front/layouts/partial/pages/register.ejs similarity index 100% rename from front/layouts/pages/register.ejs rename to front/layouts/partial/pages/register.ejs diff --git a/front/raw/login.ts b/front/raw/login.ts index b9d0a11..510111d 100644 --- a/front/raw/login.ts +++ b/front/raw/login.ts @@ -12,9 +12,9 @@ async function loginAction() { body: JSON.stringify({ username, password }) }); const data = await response.json(); - console.log("cool data received: " + JSON.stringify(data)); if (response.ok) { localStorage.setItem("token", data.token); + updateMenu(); loadPartialView('game'); alert('You have logged in successfully'); } else { diff --git a/front/raw/script.ts b/front/raw/script.ts index e7aa94a..4866aca 100644 --- a/front/raw/script.ts +++ b/front/raw/script.ts @@ -1,93 +1,85 @@ -async function loadPartialView(page: string, pushState: boolean = true): Promise { - const response: Response = await fetch(`/partial/${page}`, { - method: 'GET', - headers: { - 'Authorization': `Bearer ${localStorage.getItem('token')}`, - 'loadpartial': 'true' +function updateActiveMenu(selectedPage: string): void { + const menuButtons = document.querySelectorAll('nav button[data-page]'); + menuButtons.forEach((button) => { + if (button.getAttribute('data-page') === selectedPage) { + button.classList.add('active'); + } else { + button.classList.remove('active'); } }); - const html: string = await response.text(); - console.log(`Switching to page: ${page}`); +} - const contentElement: HTMLElement | null = document.getElementById('content'); - if (contentElement) { - contentElement.innerHTML = html; - const scripts = contentElement.querySelectorAll('script'); - scripts.forEach(oldScript => { - const newScript = document.createElement('script'); - newScript.type = oldScript.type || 'text/javascript'; - if (oldScript.src) { - newScript.src = oldScript.src + '?cb=' + Date.now(); // refresh script, force cache break - } else { - newScript.textContent = oldScript.textContent; - } - document.body.appendChild(newScript); - }); - } else { - console.warn("Content element not found"); +async function loadPartialView(page: string, pushState: boolean = true): Promise { + const token = localStorage.getItem('token'); + const headers: Record = { 'loadpartial': 'true' }; + if (token) { + headers['Authorization'] = `Bearer ${token}`; } + try { + const response: Response = await fetch(`/partial/pages/${page}`, { + method: 'GET', + headers + }); - if (pushState) { - history.pushState({ page }, '', `/partial/${page}`); + const html: string = await response.text(); + console.log(`Switching to page: ${page}`); + + const contentElement: HTMLElement | null = document.getElementById('content'); + if (contentElement) { + contentElement.innerHTML = html; + const scripts = contentElement.querySelectorAll('script'); + scripts.forEach(oldScript => { + const newScript = document.createElement('script'); + newScript.type = oldScript.type || 'text/javascript'; + if (oldScript.src) { + newScript.src = oldScript.src + '?cb=' + Date.now(); // refresh script, force cache break + } else { + newScript.textContent = oldScript.textContent; + } + document.body.appendChild(newScript); + }); + } else { + console.warn("Content element not found"); + } + + if (pushState) { + history.pushState({ page }, '', `/partial/pages/${page}`); + } + + updateActiveMenu(page); + } catch (error) { + console.error('Error fetching partial view:', error); } } - +// history change event window.addEventListener('popstate', (event: PopStateEvent) => { if (event.state && typeof event.state.page === 'string') { loadPartialView(event.state.page, false); } }); -let isDarkModeT: boolean = false; -window.addEventListener('DOMContentLoaded', () => { - const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)"); - toggleDarkMode(prefersDarkScheme.matches); - isDarkModeT = prefersDarkScheme.matches; - - prefersDarkScheme.addEventListener('change', (event) => { - toggleDarkMode(event.matches); - isDarkModeT = event.matches; - }); -}); - -function toggleDarkMode(isDarkMode: boolean = isDarkModeT): void { - if (isDarkMode) { - document.body.classList.add('dark'); - isDarkModeT = true; - } else { - document.body.classList.remove('dark'); - isDarkModeT = false; - } - - const darkModeToggle: HTMLElement | null = document.getElementById('darkModeToggle'); - if (darkModeToggle) { - darkModeToggle.textContent = isDarkModeT ? 'Light Mode' : 'Dark Mode'; - } else { - console.warn("Dark mode toggle element not found"); - } -} - -function toggleDarkModeT(): void { - isDarkModeT = !isDarkModeT; - toggleDarkMode(); -} - -function setCookie(name: string, value: string, days: number): void { - const date: Date = new Date(); - date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); - const expires: string = "expires=" + date.toUTCString(); - document.cookie = `${name}=${value};${expires};path=/`; -} +async function updateMenu(): Promise { + try { + let response: Response; + const token = localStorage.getItem('token'); + if (token) { + response = await fetch('/menu', { + headers: { + 'Authorization': `Bearer ${localStorage.getItem('token') || ''}` + } + }); + } else { + response = await fetch(`/menu`); + } -function getCookie(name: string): string | null { - // A simple implementation might be: - const nameEQ: string = name + "="; - const ca: string[] = document.cookie.split(';'); - for (let c of ca) { - c = c.trim(); - if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length); + const html = await response.text(); + const menuElement = document.getElementById('menu'); + if (menuElement) { + menuElement.innerHTML = html; + } + } catch (error) { + console.error('Menu fetch failed:', error); } - return null; } // THE number