Skip to content

Commit

Permalink
Merge pull request #2 from ruishanteo/leaderboard
Browse files Browse the repository at this point in the history
Added leaderboard
  • Loading branch information
mfjkri authored May 30, 2023
2 parents cd85547 + 058c3bc commit 84f08ce
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 120 deletions.
14 changes: 2 additions & 12 deletions src/Pages/auth/RegistrationPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,27 +65,17 @@ export default function RegistrationPage() {
sx={{ mt: 3 }}
>
<Grid container spacing={2}>
<Grid item xs={12} sm={6}>
<Grid item xs={12}>
<TextField
autoComplete="given-name"
name="firstName"
required
fullWidth
id="firstName"
label="First Name"
label="Name"
autoFocus
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
required
fullWidth
id="lastName"
label="Last Name"
name="lastName"
autoComplete="family-name"
/>
</Grid>
<Grid item xs={12}>
<TextField
required
Expand Down
7 changes: 0 additions & 7 deletions src/Pages/misc/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,6 @@ export const Home = () => {
>
WELCOME
</Typography>

<Typography
variant="h5"
sx={{ fontFamily: "Roboto", mt: 2, mb: 5, color: "white" }}
>
U R SIGNED IN
</Typography>
<Button variant="contained" href="/quiz">
Go to Quiz
</Button>
Expand Down
2 changes: 1 addition & 1 deletion src/Pages/misc/Landing.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const Landing = () => {
fontSize: 70,
}}
>
WEBNAME
EDUNOW
</Typography>

<Typography
Expand Down
26 changes: 16 additions & 10 deletions src/Pages/quiz/QuizPage.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { useEffect, useState } from "react";
import { useCallback, useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";

import store from "stores/store";
import { useAuth } from "hooks/FirebaseHooks";

import { fetchQuestions, selectOption } from "stores/questionStore";
import { updateCurrentUser } from "stores/userStore";

import { Box, Card, CardActionArea, Typography } from "@mui/material";
import { Box, Card, Typography } from "@mui/material";

import { OptionButton } from "components/OptionButton";

const QuizPage = () => {
const user = useAuth();
const dispatch = useDispatch();
const currQuestion = useSelector((state) => state.questions.currentQuestion);
const currQuestionNumber = useSelector(
Expand All @@ -19,21 +22,24 @@ const QuizPage = () => {
);
const score = useSelector((state) => state.questions.score);

const handleSelectOption = (optionIndex) =>
dispatch(selectOption(optionIndex));
const onUpdate = () => {
store.dispatch(fetchQuestions);
};
const handleSelectOption = useCallback(
(optionIndex) => dispatch(selectOption(optionIndex)),
[dispatch]
);
const onUpdate = useCallback(() => {
dispatch(fetchQuestions);
}, [dispatch]);

useEffect(() => {
onUpdate();
}, []);
}, [onUpdate]);

if (!currQuestion) {
return <Typography>Loading...</Typography>;
}

if (currQuestionNumber === totalQuestionNumber) {
dispatch(updateCurrentUser(user, score));
return (
<Box align="center" justifyContent="center">
<Box height="20vh" />
Expand All @@ -42,7 +48,7 @@ const QuizPage = () => {
</Typography>
<Box height="10vh" />
<Typography sx={{ color: "white", fontSize: 30 }}>
You have scored {score}/{totalQuestionNumber}.
You scored {score}/{totalQuestionNumber}.
</Typography>
</Box>
);
Expand Down
93 changes: 43 additions & 50 deletions src/Pages/user/Leaderboard.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
import { useCallback, useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";

import { fetchUsers } from "stores/userStore";

import { Box, Typography } from "@mui/material";

import EmojiEventsIcon from "@mui/icons-material/EmojiEvents";

const Leaderboard = () => {
const dispatch = useDispatch();
const users = useSelector((state) => state.users.users);
const currentScore = useSelector((state) => state.users.currentScore);

const onUpdate = useCallback(() => {
dispatch(fetchUsers);
}, [dispatch]);
useEffect(() => onUpdate(), [onUpdate]);

if (!users) {
return <Typography>No users...</Typography>;
}

const usersMutatable = [...users];

return (
<Box align="center">
<Box sx={{ height: "10vh" }} />
Expand All @@ -20,56 +40,29 @@ const Leaderboard = () => {
>
Leaderboard
</Typography>

<Box
sx={{
backgroundColor: "rgba(255,255,255,0.7)",
width: "50vw",
height: "8vh",
alignItems: "center",
display: "flex",
justifyContent: "center",
flexDirection: "column",
mt: 2,
}}
>
<Typography sx={{ fontSize: 30 }}>
1. This is the name of the user
</Typography>
</Box>

<Box
sx={{
backgroundColor: "rgba(255,255,255,0.7)",
width: "50vw",
height: "8vh",
alignItems: "center",
display: "flex",
justifyContent: "center",
flexDirection: "column",
mt: 2,
}}
>
<Typography sx={{ fontSize: 30 }}>
2. This is the name of the user
</Typography>
</Box>
<Box
sx={{
backgroundColor: "rgba(255,255,255,0.7)",
width: "50vw",
height: "8vh",
alignItems: "center",
display: "flex",
justifyContent: "center",
flexDirection: "column",
mt: 2,
}}
>
<Typography sx={{ fontSize: 30 }}>
3. This is the name of the user
</Typography>
</Box>
{usersMutatable
.sort((a, b) => b.score - a.score)
.map((user, index) => {
return (
<Box
key={index}
sx={{
backgroundColor: "rgba(255,255,255,0.7)",
width: "50vw",
height: "8vh",
alignItems: "center",
display: "flex",
justifyContent: "center",
flexDirection: "column",
mt: 2,
}}
>
<Typography sx={{ fontSize: 30 }}>
{`${index + 1}. ${user.displayName}, Score: ${user.score}`}
</Typography>
</Box>
);
})}
</Box>
);
};
Expand Down
4 changes: 2 additions & 2 deletions src/components/Navigation/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const Header = () => {
textDecoration: "none",
}}
>
WEBNAME
EDUNOW
</Typography>

<Box sx={{ flexGrow: 1, display: { xs: "flex", md: "none" } }}>
Expand Down Expand Up @@ -95,7 +95,7 @@ const Header = () => {
textDecoration: "none",
}}
>
WEBNAME
EDUNOW
</Typography>

<Box
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/FirebaseHooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from "firebase/auth";

import store from "stores/store";
import { saveCurrentUser } from "stores/userStore";
import { updateCurrentUser } from "stores/userStore";

import { auth } from "./Firebase";

Expand All @@ -28,8 +28,8 @@ const logInWithEmailAndPassword = async (email, password) => {
const registerWithEmailAndPassword = async (name, email, password) => {
return await createUserWithEmailAndPassword(auth, email, password)
.then(async (response) => {
saveCurrentUser();
await updateProfile(response.user, { displayName: name });
store.dispatch(updateCurrentUser(response.user, 0));
})
.catch(handleErrorMessage);
};
Expand Down
2 changes: 2 additions & 0 deletions src/stores/store.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { configureStore } from "@reduxjs/toolkit";

import { questionsReducer } from "./questionStore";
import { usersReducers } from "./userStore";

export const store = configureStore({
reducer: {
questions: questionsReducer,
users: usersReducers,
},
});

Expand Down
57 changes: 21 additions & 36 deletions src/stores/userStore.js
Original file line number Diff line number Diff line change
@@ -1,72 +1,57 @@
import { createSlice } from "@reduxjs/toolkit";

import { db } from "hooks/Firebase";
import {
addDoc,
collection,
doc,
getDoc,
getDocs,
query,
where,
} from "firebase/firestore";
import { useAuth } from "hooks/FirebaseHooks";
import { collection, doc, getDoc, getDocs, setDoc } from "firebase/firestore";

const usersSlice = createSlice({
name: "users",
initialState: {
users: [],
currentUser: {},
currentScore: 0,
},
reducers: {
saveUsers: (state, action) => {
state.users = action.payload;
},
saveCurrentUser: (state, action) => {
state.currentUser = action.payload;
state.currentScore = action.payload;
},
},
});

export function fetchCurrentUser() {
return async (dispatch, getState) => {
const user = useAuth();
const response = await getDoc(collection(db, "users"));
const userData = { ...response.data(), id: doc.id };
return userData;
};
}

export async function fetchUsers(dispatch, getState) {
const response = await getDocs(collection(db, "users"));
const users = response.docs.map((doc) => ({ ...doc.data(), id: doc.id }));
dispatch(usersSlice.actions.saveUsers(users));
}

export function fetchCurrentUser(user) {
return async (dispatch, getState) => {
const response = await getDoc(doc(db, "users", user.uid));
const userData = { ...response.data(), id: doc.id };
dispatch(usersSlice.actions.saveCurrentUser(userData.score));
};
}

export function fetchUser(userId) {
return async (dispatch, getState) => {
const response = await getDoc(collection(db, "users", userId));
const response = await getDoc(doc(db, "users", userId));
const user = { ...response.data(), id: doc.id };
return user;
};
}

export async function saveUser(dispatch, getState) {
addDoc(collection(db, "users"), getState().currentUser);
}

export function saveCurrentUser(user) {
export function updateCurrentUser(user, score) {
return async (dispatch, getState) => {
const docs = await getDocs(
query(collection(db, "users"), where("uid", "==", user.uid))
);
await addDoc(collection(db, "users"), {
uid: user.uid,
email: user.email,
await fetchCurrentUser(user);
const oldScore = getState().users.currentScore;
await setDoc(doc(db, "users", user.uid), {
displayName: user.displayName,
score: score + (oldScore ? oldScore : 0),
});
dispatch(fetchCurrentUser(user));
};
}

export const { goNext, goToQuestion, saveQuestionsToStore } =
usersSlice.actions;
export const questionsReducer = usersSlice.reducer;
export const { saveUsers, saveCurrentUser } = usersSlice.actions;
export const usersReducers = usersSlice.reducer;

0 comments on commit 84f08ce

Please sign in to comment.