A significant part of our project involved creating a real-time scoreboard that displays the highest scores of the top 10 users. Here's how we achieved this:
First, we established a scoreboard function in the Firebase database and set an initial state for the scores:
import { onValue, ref } from "firebase/database";
import { useEffect, useState } from "react";
import { database } from "../../utils/Firebase/Firebase";
import { Navbar } from "../../components/Navbar/Navbar"
export function Scoreboard() {
const [scores, setScores] = useState([]);
...
}
We then created a function that would determine the highest score of a user, comparing their song score and quiz score:
function getHighestScore(user) {
const songScore = user.highScore.song || 0;
const quizScore = user.highScore.quiz || 0;
if (songScore > quizScore) {
return {
name: `${user.firstName} ${user.lastName}`,
type: "Song",
score: songScore
}
} else {
return {
name: `${user.firstName} ${user.lastName}`,
type: "Quiz",
score: quizScore
}
}
}
Next, we utilized the useEffect function to listen for value changes in the /users node of our database. For each change, we would sort and slice the top 10 highest scores, and update the state accordingly:
useEffect(() => {
onValue(ref(database, "/users"), (snapshot) => {
const users = Object.values(snapshot.val())
if (users) {
const highestScores = users
.map(user => getHighestScore(user))
.sort((a, b) => b.score - a.score)
.slice(0, 10)
setScores(highestScores);
}
})
}, [])
Lastly, we rendered the scores in a table format:
return (
<div>
<Navbar />
<main className="loggedIn">
<h1> Scoreboard </h1>
<table className="table">
...
<tbody className="tableBody">
{scores.map((score, index) => {
return (
<tr key={index} className="tableBodyRow">
<td className="tableBodyIndex"></td>
<td className="tableBodyName"><b>{index + 1}</b><span className="tabBody" />{score.name}</td>
<td className="tableBodyItem">{score.type}</td>
<td className="tableBodyItem">{score.score}</td>
</tr>
)
})}
</tbody>
</table>
</main>
</div>
);
};
We also set up functionalities to update the song and quiz scores for each user in the database as they achieved new highs:
export async function setSongScore(newScore) {
const user = await getUser();
let currentScore = user.highScore.song;
if (newScore > currentScore) {
await updateUser({
highScore: {
song: newScore,
quiz: user.highScore.quiz
}
})
}
}
export async function setQuizScore(newScore) {
const user = await getUser();
let currentScore = user.highScore.quiz;
if (newScore > currentScore) {
await updateUser({
highScore: {
song: user.highScore.song,
quiz: newScore
}
})
}
}
With these functionalities in place, we're able to provide a live, competitive environment for our users, encouraging them to improve their skills and reach higher scores.