From a69f1d9c2ee92b21e343f1a3899d61337aa10902 Mon Sep 17 00:00:00 2001 From: alanmcilwaine Date: Tue, 30 Sep 2025 12:48:56 +1300 Subject: [PATCH] fix(leaderboard): Fixed leaderboard timer still going up. Fixed 5 minute timeout to go to home screen. --- .../components/LeaderboardQuestionCard.vue | 9 ++ frontend/src/types/Session.ts | 7 -- frontend/src/views/LeaderboardView.vue | 20 +++- frontend/src/views/QuestionReviewView.vue | 98 +++---------------- frontend/src/views/QuestionView.vue | 3 +- 5 files changed, 44 insertions(+), 93 deletions(-) diff --git a/frontend/src/components/LeaderboardQuestionCard.vue b/frontend/src/components/LeaderboardQuestionCard.vue index 6acaa56..e35b8a7 100644 --- a/frontend/src/components/LeaderboardQuestionCard.vue +++ b/frontend/src/components/LeaderboardQuestionCard.vue @@ -53,6 +53,15 @@ h3 { font-size: 38px; } +.question-name { + text-align: left; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 100%; + font-size: 32px; +} + .question-card { padding: 12px 30px; display: flex; diff --git a/frontend/src/types/Session.ts b/frontend/src/types/Session.ts index ffee8d1..7e4680b 100644 --- a/frontend/src/types/Session.ts +++ b/frontend/src/types/Session.ts @@ -87,13 +87,6 @@ export class Session { } public async fetchLeaderboard(): Promise { - if (this.ws.readyState !== WebSocket.OPEN) { - AlertService.alert("Server has closed the connection because the session has reached 5 minutes."); - this.setGameOver(true); - const router = useRouter(); - router.push("/"); - return; - } return new Promise((resolve) => { const message = JSON.stringify({ action: "GET_LEADERBOARD", diff --git a/frontend/src/views/LeaderboardView.vue b/frontend/src/views/LeaderboardView.vue index 9cd0b0a..88f74a5 100644 --- a/frontend/src/views/LeaderboardView.vue +++ b/frontend/src/views/LeaderboardView.vue @@ -57,9 +57,18 @@ onMounted(async () => { router.push("/"); return; } - await session.value.fetchLeaderboard(); + + if (session.value.ws.readyState !== WebSocket.OPEN) { + router.push("/"); + session.value.setGameOver(true); + AlertService.alert("Server has closed the connection because the session has reached 5 minutes."); + return; + } else { + await session.value.fetchLeaderboard(); + } if (session.value instanceof PlayerSession) { await session.value.fetchScore(); + session.value.getGameTimer()?.stop(); playerAnswers.value = session.value.getAnswers(); questions.value = session.value.getQuestions(); globalPlayers.value = session.value.getGlobalLeaderboard(); @@ -67,7 +76,14 @@ onMounted(async () => { } updater.value = setInterval(async () => { if (session.value instanceof PlayerSession) { - await session.value.fetchLeaderboard(); + if (session.value.ws.readyState !== WebSocket.OPEN) { + router.push("/"); + session.value.setGameOver(true); + AlertService.alert("Server has closed the connection because the session has reached 5 minutes."); + return; + } else { + await session.value.fetchLeaderboard(); + } globalPlayers.value = session.value.getGlobalLeaderboard(); lobbyPlayers.value = [...session.value.getLobbyLeaderboard()]; } diff --git a/frontend/src/views/QuestionReviewView.vue b/frontend/src/views/QuestionReviewView.vue index 541a7de..8151c31 100644 --- a/frontend/src/views/QuestionReviewView.vue +++ b/frontend/src/views/QuestionReviewView.vue @@ -128,12 +128,6 @@ onMounted(async () => { display: flex; flex-direction: column; align-items: center; - justify-content: center; - min-height: 100dvh; - width: 100dvw; - padding: 20px; - box-sizing: border-box; - position: relative; } h2 { @@ -150,98 +144,36 @@ h2 { } .tree-container { - flex: 1; - display: flex; - justify-content: center; - align-items: center; - width: 100%; - max-width: 800px; - margin: 20px 0; + margin-top: 5vh; + transform-origin: center top; + transition: transform 0.3s ease; } .bottom-right-buttons { - position: fixed; - bottom: 30px; - right: 30px; + position: absolute; + bottom: 40px; + right: 60px; display: flex; - gap: 15px; - z-index: 1000; + align-items: center; + gap: 5px; + z-index: 100; } .top-right-buttons { - position: fixed; - top: 30px; - right: 30px; - z-index: 1000; -} - -.info-item { + position: absolute; + top: 25px; + right: 20px; display: flex; - justify-content: space-between; align-items: center; - margin-bottom: 10px; - font-size: 18px; -} - -.info-item:last-child { - margin-bottom: 0; -} - -.label { - font-weight: bold; - color: var(--text-color); -} - -.value { - color: var(--text-color); -} - -.value.correct { - color: var(--positive-color); - font-weight: bold; -} - -.value.incorrect { - color: var(--negative-color); - font-weight: bold; -} - -.btn-img { - width: 20px; - height: 20px; + gap: 15px; + z-index: 100; } -@media screen and (max-width: 890px) { +@media (max-width: 890px) { /* I found this is a good number to make sure it doesn't overlap the title. */ .top-right-buttons { - position: fixed; - top: 20px; - right: 20px; flex-direction: column-reverse; align-items: flex-end; gap: 10px; } - - .bottom-right-buttons { - position: fixed; - bottom: 20px; - right: 20px; - flex-direction: column; - align-items: flex-end; - gap: 10px; - } - - .question-info { - position: relative; - top: auto; - left: auto; - margin-bottom: 20px; - width: 100%; - max-width: 400px; - } - - h2 { - font-size: 36px; - margin-bottom: 20px; - } } diff --git a/frontend/src/views/QuestionView.vue b/frontend/src/views/QuestionView.vue index 3e7213a..a831707 100644 --- a/frontend/src/views/QuestionView.vue +++ b/frontend/src/views/QuestionView.vue @@ -150,7 +150,6 @@ const handleGameEnded = (data: any) => { onMounted(async () => { // Listen for game end event const session = await APIManager.getInstance().getSession(); - initializeQuestion(); // Add window resize listener for responsive scaling window.addEventListener('resize', calculateTreeScale); @@ -169,6 +168,8 @@ onUnmounted(async () => { if (session) { session.removeEventListener("GAME_ENDED", handleGameEnded); } + + gameTimer.value?.stop(); }); // Immediate false just means it won't call on the first mount.