Made it so the pages update the user when loading
This commit is contained in:
@@ -3,6 +3,7 @@ import {User} from "@/interfaces/user";
|
|||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import LevelLabel from "./LevelLabel";
|
import LevelLabel from "./LevelLabel";
|
||||||
import LevelProgressBar from "./LevelProgressBar";
|
import LevelProgressBar from "./LevelProgressBar";
|
||||||
|
import {Avatar} from "primereact/avatar";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
user: User;
|
user: User;
|
||||||
@@ -13,8 +14,11 @@ export default function ProfileCard({user, className}: Props) {
|
|||||||
return (
|
return (
|
||||||
<div className={clsx("bg-white drop-shadow-xl p-4 md:p-8 rounded-xl w-full flex flex-col gap-6", className)}>
|
<div className={clsx("bg-white drop-shadow-xl p-4 md:p-8 rounded-xl w-full flex flex-col gap-6", className)}>
|
||||||
<div className="flex w-full items-center gap-8">
|
<div className="flex w-full items-center gap-8">
|
||||||
<div className="w-16 md:w-24 rounded-full border-2 md:border-4 border-white drop-shadow-md md:drop-shadow-xl">
|
<div className="w-16 md:w-24 h-16 md:h-24 rounded-full border-2 md:border-4 border-white drop-shadow-md md:drop-shadow-xl">
|
||||||
<img src={user.profilePicture} alt="Profile picture" className="rounded-full" />
|
{user.profilePicture.length > 0 && <img src={user.profilePicture} alt="Profile picture" className="rounded-full" />}
|
||||||
|
{user.profilePicture.length === 0 && (
|
||||||
|
<Avatar size="xlarge" style={{width: "100%", height: "100%"}} label={user.name.slice(0, 1)} shape="circle" />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col justify-center">
|
<div className="flex flex-col justify-center">
|
||||||
<span className="text-neutral-600 font-bold text-xl lg:text-2xl">{user.name}</span>
|
<span className="text-neutral-600 font-bold text-xl lg:text-2xl">{user.name}</span>
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import {app} from "@/firebase";
|
import {app} from "@/firebase";
|
||||||
|
import {User} from "@/interfaces/user";
|
||||||
import {sessionOptions} from "@/lib/session";
|
import {sessionOptions} from "@/lib/session";
|
||||||
import {getAuth} from "firebase/auth";
|
import {getAuth} from "firebase/auth";
|
||||||
|
import {doc, getDoc, getFirestore} from "firebase/firestore";
|
||||||
import {withIronSessionApiRoute} from "iron-session/next";
|
import {withIronSessionApiRoute} from "iron-session/next";
|
||||||
import {NextApiRequest, NextApiResponse} from "next";
|
import {NextApiRequest, NextApiResponse} from "next";
|
||||||
|
|
||||||
const auth = getAuth(app);
|
const auth = getAuth(app);
|
||||||
|
const db = getFirestore(app);
|
||||||
|
|
||||||
export default withIronSessionApiRoute(user, sessionOptions);
|
export default withIronSessionApiRoute(user, sessionOptions);
|
||||||
|
|
||||||
async function user(req: NextApiRequest, res: NextApiResponse) {
|
async function user(req: NextApiRequest, res: NextApiResponse) {
|
||||||
@@ -14,12 +18,23 @@ async function user(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.session.user.id === auth.currentUser.uid) {
|
if (req.session.user.id !== auth.currentUser.uid) {
|
||||||
res.status(401).json(undefined);
|
res.status(401).json(undefined);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(req.session.user);
|
const docUser = await getDoc(doc(db, "users", req.session.user.id));
|
||||||
|
if (!docUser.exists()) {
|
||||||
|
res.status(401).json(undefined);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = docUser.data() as User;
|
||||||
|
|
||||||
|
req.session.user = {...user, id: req.session.user.id};
|
||||||
|
await req.session.save();
|
||||||
|
|
||||||
|
res.json({...user, id: req.session.user.id});
|
||||||
} else {
|
} else {
|
||||||
res.status(401).json(undefined);
|
res.status(401).json(undefined);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {sessionOptions} from "@/lib/session";
|
|||||||
import {Stat, User} from "@/interfaces/user";
|
import {Stat, User} from "@/interfaces/user";
|
||||||
import Speaking from "@/exams/Speaking";
|
import Speaking from "@/exams/Speaking";
|
||||||
import {v4 as uuidv4} from "uuid";
|
import {v4 as uuidv4} from "uuid";
|
||||||
|
import useUser from "@/hooks/useUser";
|
||||||
|
|
||||||
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
|
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
|
||||||
const user = req.session.user;
|
const user = req.session.user;
|
||||||
@@ -37,7 +38,7 @@ export const getServerSideProps = withIronSessionSsr(({req, res}) => {
|
|||||||
};
|
};
|
||||||
}, sessionOptions);
|
}, sessionOptions);
|
||||||
|
|
||||||
export default function Page({user}: {user: User}) {
|
export default function Page() {
|
||||||
const [userSolutions, setUserSolutions] = useState<UserSolution[]>([]);
|
const [userSolutions, setUserSolutions] = useState<UserSolution[]>([]);
|
||||||
const [selectedModules, setSelectedModules] = useState<Module[]>([]);
|
const [selectedModules, setSelectedModules] = useState<Module[]>([]);
|
||||||
const [hasBeenUploaded, setHasBeenUploaded] = useState(false);
|
const [hasBeenUploaded, setHasBeenUploaded] = useState(false);
|
||||||
@@ -47,6 +48,8 @@ export default function Page({user}: {user: User}) {
|
|||||||
const [exam, setExam] = useState<Exam>();
|
const [exam, setExam] = useState<Exam>();
|
||||||
const [timer, setTimer] = useState(-1);
|
const [timer, setTimer] = useState(-1);
|
||||||
|
|
||||||
|
const {user} = useUser({redirectTo: "/login"});
|
||||||
|
|
||||||
useEffect(() => setSessionId(uuidv4()), []);
|
useEffect(() => setSessionId(uuidv4()), []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -67,7 +70,7 @@ export default function Page({user}: {user: User}) {
|
|||||||
session: sessionId,
|
session: sessionId,
|
||||||
exam: solution.exam!,
|
exam: solution.exam!,
|
||||||
module: solution.module!,
|
module: solution.module!,
|
||||||
user: user.id,
|
user: user?.id || "",
|
||||||
}));
|
}));
|
||||||
|
|
||||||
axios
|
axios
|
||||||
@@ -126,13 +129,13 @@ export default function Page({user}: {user: User}) {
|
|||||||
|
|
||||||
const renderScreen = () => {
|
const renderScreen = () => {
|
||||||
if (selectedModules.length === 0) {
|
if (selectedModules.length === 0) {
|
||||||
return <Selection user={user} onStart={setSelectedModules} />;
|
return <Selection user={user!} onStart={setSelectedModules} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moduleIndex >= selectedModules.length) {
|
if (moduleIndex >= selectedModules.length) {
|
||||||
return (
|
return (
|
||||||
<Finish
|
<Finish
|
||||||
user={user}
|
user={user!}
|
||||||
modules={selectedModules}
|
modules={selectedModules}
|
||||||
onViewResults={() => {
|
onViewResults={() => {
|
||||||
setShowSolutions(true);
|
setShowSolutions(true);
|
||||||
@@ -184,10 +187,12 @@ export default function Page({user}: {user: User}) {
|
|||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<ToastContainer />
|
<ToastContainer />
|
||||||
|
{user && (
|
||||||
<main className="w-full h-full min-h-[100vh] flex flex-col items-center bg-neutral-100 text-black pb-4 gap-4">
|
<main className="w-full h-full min-h-[100vh] flex flex-col items-center bg-neutral-100 text-black pb-4 gap-4">
|
||||||
<Navbar profilePicture={user.profilePicture} timer={exam ? timer : undefined} />
|
<Navbar profilePicture={user.profilePicture} timer={exam ? timer : undefined} />
|
||||||
{renderScreen()}
|
{renderScreen()}
|
||||||
</main>
|
</main>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {useEffect, useState} from "react";
|
|||||||
import useStats from "@/hooks/useStats";
|
import useStats from "@/hooks/useStats";
|
||||||
import {averageScore, formatModuleTotalStats, totalExams} from "@/utils/stats";
|
import {averageScore, formatModuleTotalStats, totalExams} from "@/utils/stats";
|
||||||
import {Divider} from "primereact/divider";
|
import {Divider} from "primereact/divider";
|
||||||
|
import useUser from "@/hooks/useUser";
|
||||||
|
|
||||||
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
|
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
|
||||||
const user = req.session.user;
|
const user = req.session.user;
|
||||||
@@ -30,10 +31,12 @@ export const getServerSideProps = withIronSessionSsr(({req, res}) => {
|
|||||||
};
|
};
|
||||||
}, sessionOptions);
|
}, sessionOptions);
|
||||||
|
|
||||||
export default function Home({user}: {user: User}) {
|
export default function Home() {
|
||||||
const [showEndExam, setShowEndExam] = useState(false);
|
const [showEndExam, setShowEndExam] = useState(false);
|
||||||
const [windowWidth, setWindowWidth] = useState(0);
|
const [windowWidth, setWindowWidth] = useState(0);
|
||||||
|
|
||||||
const {stats, isLoading} = useStats();
|
const {stats, isLoading} = useStats();
|
||||||
|
const {user} = useUser({redirectTo: "/login"});
|
||||||
|
|
||||||
useEffect(() => setShowEndExam(window.innerWidth <= 960), []);
|
useEffect(() => setShowEndExam(window.innerWidth <= 960), []);
|
||||||
useEffect(() => setWindowWidth(window.innerWidth), []);
|
useEffect(() => setWindowWidth(window.innerWidth), []);
|
||||||
@@ -49,6 +52,7 @@ export default function Home({user}: {user: User}) {
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
|
{user && (
|
||||||
<main className="w-full h-full min-h-[100vh] flex flex-col items-center bg-neutral-100 text-black">
|
<main className="w-full h-full min-h-[100vh] flex flex-col items-center bg-neutral-100 text-black">
|
||||||
<Navbar profilePicture={user.profilePicture} showExamEnd={showEndExam} />
|
<Navbar profilePicture={user.profilePicture} showExamEnd={showEndExam} />
|
||||||
<div className="w-full h-full p-4 relative flex flex-col gap-8">
|
<div className="w-full h-full p-4 relative flex flex-col gap-8">
|
||||||
@@ -77,6 +81,7 @@ export default function Home({user}: {user: User}) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ export default function Stats({user}: {user: User}) {
|
|||||||
<main className="w-full h-full min-h-[100vh] flex flex-col items-center bg-neutral-100 text-neutral-600">
|
<main className="w-full h-full min-h-[100vh] flex flex-col items-center bg-neutral-100 text-neutral-600">
|
||||||
<Navbar profilePicture={user.profilePicture} />
|
<Navbar profilePicture={user.profilePicture} />
|
||||||
<div className="w-full h-full flex flex-col items-center justify-center p-4 relative gap-8">
|
<div className="w-full h-full flex flex-col items-center justify-center p-4 relative gap-8">
|
||||||
|
{!isLoading && (
|
||||||
<AutoComplete
|
<AutoComplete
|
||||||
value={autocompleteValue}
|
value={autocompleteValue}
|
||||||
suggestions={items}
|
suggestions={items}
|
||||||
@@ -69,6 +70,7 @@ export default function Stats({user}: {user: User}) {
|
|||||||
onSelect={(e) => setSelectedUser(e.value)}
|
onSelect={(e) => setSelectedUser(e.value)}
|
||||||
dropdown
|
dropdown
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<section className="flex flex-col gap-2 md:gap-4 w-full">
|
<section className="flex flex-col gap-2 md:gap-4 w-full">
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
|
|||||||
Reference in New Issue
Block a user