Skip to content

Commit

Permalink
Add context for current user state, with redirection
Browse files Browse the repository at this point in the history
  • Loading branch information
benjaminJohnson2204 committed Mar 31, 2024
1 parent 7f2644b commit 234ccee
Show file tree
Hide file tree
Showing 20 changed files with 287 additions and 176 deletions.
6 changes: 3 additions & 3 deletions backend/__tests__/userTest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ describe("User Tests", () => {
.get("/api/user/whoami")
.set("Authorization", `Bearer ${testToken}`);
expect(res.statusCode).toBe(200);
expect(res.body.user.uid).toBe(userInfo.uid);
expect(res.body.user.role).toBe(UserRole.STAFF);
expect(res.body.user._id).toBe(testUser._id.toString());
expect(res.body.uid).toBe(userInfo.uid);
expect(res.body.role).toBe(UserRole.STAFF);
expect(res.body._id).toBe(testUser._id.toString());
});
});
9 changes: 3 additions & 6 deletions backend/src/controllers/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,9 @@ export const getWhoAmI: RequestHandler = async (req: PAPRequest, res, next) => {
const user = await UserModel.findOne({ uid: userUid });
const { _id, uid, role } = user!;
res.status(200).send({
message: "Current user information",
user: {
_id,
uid,
role,
},
_id,
uid,
role,
});
} catch (error) {
next(error);
Expand Down
17 changes: 17 additions & 0 deletions frontend/src/api/Users.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { APIResult, get, handleAPIError } from "@/api/requests";

export interface User {
_id: string;
uid: string;
role: string;
}

export const getWhoAmI = async (firebaseToken: string): Promise<APIResult<User>> => {
try {
const response = await get("/api/user/whoami", { Authorization: `Bearer ${firebaseToken}` });
const json = (await response.json()) as User;
return { success: true, data: json };
} catch (error) {
return handleAPIError(error);
}
};
5 changes: 4 additions & 1 deletion frontend/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from "react";

import type { Metadata } from "next";
import "@/app/globals.css";
import { UserContextProvider } from "@/contexts/userContext";

const inter = Inter({ subsets: ["latin"] });

Expand All @@ -14,7 +15,9 @@ export const metadata: Metadata = {
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<body className={inter.className}>
<UserContextProvider>{children}</UserContextProvider>
</body>
</html>
);
}
163 changes: 75 additions & 88 deletions frontend/src/app/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,25 @@ import Image from "next/image";
import styles from "@/app/login/page.module.css";
import { signInWithEmailAndPassword } from "firebase/auth";
import { initFirebase } from "@/firebase/firebase";
import { useRouter } from "next/navigation";
import { useScreenSizes } from "@/util/useScreenSizes";
import { useScreenSizes } from "@/hooks/useScreenSizes";
import { useRedirectToHomeIfSignedIn } from "@/hooks/useRedirection";
import { getWhoAmI } from "@/api/Users";

const Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");

const { auth } = initFirebase();
useRedirectToHomeIfSignedIn();

const router = useRouter();
const { auth } = initFirebase();

const { isMobile } = useScreenSizes();

const sendTokenToBackend = async (token: string) => {
try {
const response = await fetch(`http://localhost:3001/api/user/whoami`, {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
});

if (response.ok) {
const userInfo = await response.json();
console.log(userInfo);
router.push("/dummyPage");
} else {
console.error("Failed to get user info from JWT Token");
}
} catch (error) {
console.error("error sending JWT token to backend", error);
const res = await getWhoAmI(token);
if (!res.success) {
// TODO: better error handling (e.g. no network, user not found)
console.error(`Error retrieving current user: ${res.error}`);
}
};

Expand All @@ -47,11 +34,13 @@ const Login = () => {
const userCredential = await signInWithEmailAndPassword(auth, email, password);
const token = await userCredential.user?.getIdToken();
if (!token) {
// TODO: better error handling
console.error("JWT token not retrieved.");
} else {
await sendTokenToBackend(token);
}
} catch (error) {
// TODO: better error handling (e.g. no network, invalid credentials)
console.error("login failed: ", error);
}
};
Expand All @@ -62,75 +51,73 @@ const Login = () => {
};

return (
<body>
<div className={styles.loginContainer}>
<Image
src="/Images/login_bg.png"
alt=""
layout="fill"
objectFit="cover"
priority
/* Inline styling due to using Image Component*/
style={{
position: "absolute",
top: "0",
left: "0",
right: "30",
bottom: "0",
}}
className={styles.backgroundImage}
/>
<div
style={{
position: "absolute",
top: "0",
left: "0",
right: "0",
bottom: "0",
background: "#232220D9",
}}
/>
<div className={styles.loginBox}>
<div className={styles.logoContainer}>
<div className={styles.logoImage}>
<Image
src="/Images/LoginImage.png"
alt="Logo"
className={styles.image}
width={isMobile ? 130 : 190}
height={isMobile ? 60 : 90}
/>
</div>
<div className={styles.loginContainer}>
<Image
src="/Images/login_bg.png"
alt=""
layout="fill"
objectFit="cover"
priority
/* Inline styling due to using Image Component*/
style={{
position: "absolute",
top: "0",
left: "0",
right: "30",
bottom: "0",
}}
className={styles.backgroundImage}
/>
<div
style={{
position: "absolute",
top: "0",
left: "0",
right: "0",
bottom: "0",
background: "#232220D9",
}}
/>
<div className={styles.loginBox}>
<div className={styles.logoContainer}>
<div className={styles.logoImage}>
<Image
src="/Images/LoginImage.png"
alt="Logo"
className={styles.image}
width={isMobile ? 130 : 190}
height={isMobile ? 60 : 90}
/>
</div>
<div className={styles.welcomeText}>Welcome!</div>
<form onSubmit={handleLogin} className={styles.loginForm}>
<div className={styles.inputGroup}>
<InputField
label="Email"
id="email"
placeholder="e.g. [email protected]"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div className={styles.inputGroup}>
<InputField
label="Password"
id="password"
placeholder=""
value={password}
onChange={(e) => setPassword(e.target.value)}
type="password"
/>
</div>
<div className={styles.forgotPassword}>Forgot Password?</div>
<button type="submit" className={styles.loginButton}>
Log In
</button>
</form>
</div>
<div className={styles.welcomeText}>Welcome!</div>
<form onSubmit={handleLogin} className={styles.loginForm}>
<div className={styles.inputGroup}>
<InputField
label="Email"
id="email"
placeholder="e.g. [email protected]"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div className={styles.inputGroup}>
<InputField
label="Password"
id="password"
placeholder=""
value={password}
onChange={(e) => setPassword(e.target.value)}
type="password"
/>
</div>
<div className={styles.forgotPassword}>Forgot Password?</div>
<button type="submit" className={styles.loginButton}>
Log In
</button>
</form>
</div>
</body>
</div>
);
};

Expand Down
3 changes: 3 additions & 0 deletions frontend/src/app/staff/vsr/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
"use client";
import { Page } from "@/components/VSRIndividual";
import { useRedirectToLoginIfNotSignedIn } from "@/hooks/useRedirection";

export default function Individual() {
useRedirectToLoginIfNotSignedIn();

return (
<div>
<Page></Page>
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/app/staff/vsr/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,18 @@ import Image from "next/image";
import React from "react";
import { StatusDropdown } from "@/components/VSRIndividual";
import { useMediaQuery } from "@mui/material";
import { useRedirectToLoginIfNotSignedIn } from "@/hooks/useRedirection";

export default function VSRTableView() {
const searchOnOwnRow = useMediaQuery("@media screen and (max-width: 1000px)");
const buttonIconsOnly = useMediaQuery("@media screen and (max-width: 700px)");
const buttonIconSize = buttonIconsOnly ? 16 : 24;

useRedirectToLoginIfNotSignedIn();

return (
<div className={styles.page}>
<HeaderBar />
<HeaderBar showLogoutButton />
<div className={styles.column}>
<PageTitle />
<div className={styles.button_row}>
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/app/vsr/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { createVSR, CreateVSRRequest, FurnitureInput } from "@/api/VSRs";
import { FurnitureItem, getFurnitureItems } from "@/api/FurnitureItems";
import BinaryChoice from "@/components/shared/input/BinaryChoice";
import { FurnitureItemSelection } from "@/components/VeteranForm/FurnitureItemSelection";
import { useScreenSizes } from "@/util/useScreenSizes";
import { useScreenSizes } from "@/hooks/useScreenSizes";

interface IFormInput {
name: string;
Expand Down Expand Up @@ -432,7 +432,7 @@ const VeteranServiceRequest: React.FC = () => {
return (
<div>
<form onSubmit={handleSubmit(incrementPageNumber)}>
<HeaderBar />
<HeaderBar showLogoutButton={false} />
<div className={styles.main}>
<h1 className={styles.title}>Veteran Service Request Form</h1>
<p className={styles.description}>
Expand Down Expand Up @@ -670,7 +670,7 @@ const VeteranServiceRequest: React.FC = () => {
return (
<div>
<form onSubmit={handleSubmit(incrementPageNumber)}>
<HeaderBar />
<HeaderBar showLogoutButton={false} />
<div className={styles.main}>
<div className={styles.formContainer}>
<div className={styles.form}>
Expand Down Expand Up @@ -1008,7 +1008,7 @@ const VeteranServiceRequest: React.FC = () => {
return (
<div>
<form onSubmit={handleSubmit(onSubmit)}>
<HeaderBar />
<HeaderBar showLogoutButton={false} />
<div className={styles.main}>
<div className={styles.formContainer}>
<div className={styles.form}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import moment from "moment";
import { VSRIndividualAccordion } from "@/components/VSRIndividual/VSRIndividualAccordion";
import { STATUS_OPTIONS } from "@/components/shared/StatusDropdown";
import { StatusChip } from "@/components/shared/StatusChip";
import { useScreenSizes } from "@/util/useScreenSizes";
import { useScreenSizes } from "@/hooks/useScreenSizes";

export interface CaseDetailsProp {
vsr: VSR;
Expand Down
15 changes: 0 additions & 15 deletions frontend/src/components/VSRIndividual/HeaderBar/index.tsx

This file was deleted.

32 changes: 0 additions & 32 deletions frontend/src/components/VSRIndividual/HeaderBar/styles.module.css

This file was deleted.

Loading

0 comments on commit 234ccee

Please sign in to comment.