From 4a56c92667a642f89441c94e50dd028715742d00 Mon Sep 17 00:00:00 2001 From: Maieul BOYER Date: Fri, 12 Dec 2025 15:42:28 +0100 Subject: [PATCH 1/2] fixes(frontend): Made the overlay transparent & redirect on login The overlay that is used when the menubar is used is now actually transparent When logging in, actually always redirect to somewhere (if not asked -> redirect to /) --- frontend/index.html | 8 ++++--- frontend/src/carousel/index.ts | 2 ++ frontend/src/pages/login/login.ts | 36 +++++++++++++++++++------------ 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/frontend/index.html b/frontend/index.html index 7ffbbff..97b7829 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -17,8 +17,8 @@ <
-
- +
+ +
+ class="fixed top-14 left-0 right-0 bottom-0 bg-black opacity-0 pointer-events-none transition-opacity duration-300 z-30">
diff --git a/frontend/src/carousel/index.ts b/frontend/src/carousel/index.ts index 999c996..693e21d 100644 --- a/frontend/src/carousel/index.ts +++ b/frontend/src/carousel/index.ts @@ -7,6 +7,7 @@ const overlay = document.querySelector('#overlay')!; menuBtn.addEventListener('click', () => { sidebar.classList.toggle('-translate-x-full') overlay.classList.toggle('opacity-0'); + overlay.classList.toggle('opacity-40'); overlay.classList.toggle('pointer-events-none'); menuBtn.classList.toggle('flipped'); }); @@ -14,4 +15,5 @@ menuBtn.addEventListener('click', () => { overlay.addEventListener('click', () => { sidebar.classList.add('-translate-x-full'); overlay.classList.add('opacity-0', 'pointer-events-none'); + overlay.classList.remove('opacity-40'); }); diff --git a/frontend/src/pages/login/login.ts b/frontend/src/pages/login/login.ts index 5eb5123..f128455 100644 --- a/frontend/src/pages/login/login.ts +++ b/frontend/src/pages/login/login.ts @@ -17,7 +17,11 @@ import { updateUser } from "@app/auth"; const TOTP_LENGTH = 6; -async function handleOtp(app: HTMLElement, token: string, returnTo: string | null) { +async function handleOtp( + app: HTMLElement, + token: string, + returnTo: string | null, +) { app.innerHTML = totpHtml; const container = app.querySelector("#totp-container")!; @@ -76,19 +80,18 @@ async function handleOtp(app: HTMLElement, token: string, returnTo: string | nul if (code.length === TOTP_LENGTH && /^[0-9]+$/.test(code)) { let res = await client.loginOtp({ loginOtpRequest: { - code, token, - } - }) + code, + token, + }, + }); if (res.kind === "success") { Cookie.set("token", res.payload.token, { path: "/", sameSite: "lax", }); - if (returnTo !== null) navigateTo(returnTo); - else navigateTo("/"); - } - else if (res.kind === "failed") { + navigateTo(returnTo ?? "/"); + } else if (res.kind === "failed") { showError(`Failed to authenticate: ${res.msg}`); } } @@ -97,7 +100,6 @@ async function handleOtp(app: HTMLElement, token: string, returnTo: string | nul inputs[0].focus(); } - async function handleLogin( _url: string, _args: RouteHandlerParams, @@ -131,7 +133,7 @@ async function handleLogin( if (returnTo !== null) { bReturnTo.parentElement!.hidden = false; bReturnTo.addEventListener("click", async () => { - if (returnTo !== null) navigateTo(returnTo); + navigateTo(returnTo ?? "/"); }); } }, @@ -189,11 +191,15 @@ async function handleLogin( setTitle( `Welcome ${user.guest ? "[GUEST] " : ""}${user.name}`, ); - if (returnTo !== null) navigateTo(returnTo); + navigateTo(returnTo ?? "/"); break; } case "otpRequired": { - return await handleOtp(app!, res.payload.token, returnTo); + return await handleOtp( + app!, + res.payload.token, + returnTo, + ); } case "failed": { showError(`Failed to login: ${res.msg}`); @@ -209,7 +215,9 @@ async function handleLogin( document.querySelector("#bGuestLogin"); bLoginAsGuest?.addEventListener("click", async () => { try { - const res = await client.guestLogin({ guestLoginRequest: { name: undefined } }); + const res = await client.guestLogin({ + guestLoginRequest: { name: undefined }, + }); switch (res.kind) { case "success": { Cookie.set("token", res.payload.token, { @@ -224,7 +232,7 @@ async function handleLogin( setTitle( `Welcome ${user.guest ? "[GUEST] " : ""}${user.name}`, ); - if (returnTo !== null) navigateTo(returnTo); + navigateTo(returnTo ?? "/"); break; } case "failed": { From 8222ec4ea36e7302372fa95d07ec3c311efbd497 Mon Sep 17 00:00:00 2001 From: Maieul BOYER Date: Fri, 12 Dec 2025 15:49:47 +0100 Subject: [PATCH 2/2] feat(frontend): added logout page --- frontend/src/auth/index.ts | 3 +++ frontend/src/pages/index.ts | 1 + frontend/src/pages/logout/logout.ts | 16 ++++++++++++++++ 3 files changed, 20 insertions(+) create mode 100644 frontend/src/pages/logout/logout.ts diff --git a/frontend/src/auth/index.ts b/frontend/src/auth/index.ts index 449dabc..008e94d 100644 --- a/frontend/src/auth/index.ts +++ b/frontend/src/auth/index.ts @@ -1,5 +1,8 @@ import { showError } from "@app/toast"; import client from '@app/api'; +import cookie from 'js-cookie'; + +cookie.remove('pkce'); export type User = { id: string; diff --git a/frontend/src/pages/index.ts b/frontend/src/pages/index.ts index dfab156..92cebd5 100644 --- a/frontend/src/pages/index.ts +++ b/frontend/src/pages/index.ts @@ -5,6 +5,7 @@ import './login/login.ts' import './signin/signin.ts' import './ttt/ttt.ts' import './profile/profile.ts' +import './logout/logout.ts' // ---- Initial load ---- setTitle(""); diff --git a/frontend/src/pages/logout/logout.ts b/frontend/src/pages/logout/logout.ts new file mode 100644 index 0000000..16fa9a4 --- /dev/null +++ b/frontend/src/pages/logout/logout.ts @@ -0,0 +1,16 @@ +import { addRoute, navigateTo, setTitle, type RouteHandlerReturn } from "@app/routing"; +import cookie from "js-cookie"; + +async function route(_url: string, _args: { [k: string]: string }): Promise { + setTitle('Logout') + return { + html: "you should have been logged out", postInsert: async (app) => { + cookie.remove("token"); + navigateTo("/"); + } + }; +} + + + +addRoute('/logout', route, { bypass_auth: true })