Skip to content

Commit

Permalink
Merge branch 'feature/samvrit+sydney/Profile-Home-Page' into feature/…
Browse files Browse the repository at this point in the history
…harsh-steven/search-sort-filter
  • Loading branch information
benjaminJohnson2204 committed May 28, 2024
2 parents 2f3c4a3 + db289d5 commit ba9adbc
Show file tree
Hide file tree
Showing 11 changed files with 396 additions and 2 deletions.
35 changes: 34 additions & 1 deletion backend/src/controllers/user.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { RequestHandler } from "express";
import { PAPRequest } from "src/middleware/auth";
import UserModel from "src/models/user";
import { firebaseAuth } from "src/services/firebase";
import UserModel, { DisplayUser } from "src/models/user";

/**
* Retrieves data about the current user (their MongoDB ID, Firebase UID, and role).
Expand All @@ -20,3 +21,35 @@ export const getWhoAmI: RequestHandler = async (req: PAPRequest, res, next) => {
next(error);
}
};

export const getUsers: RequestHandler = async (req: PAPRequest, res, next) => {
try {
const users = await UserModel.find();
const displayUsers = [];
for (const user of users) {
const { uid, _id } = user;

try {
// const userRecord = await firebaseAuth.getUser(uid);

await firebaseAuth.updateUser(uid, {
displayName: "Samvrit Srinath",
photoURL:
"https://www.google.com/url?sa=i&url=https%3A%2F%2Fstackoverflow.com%2Fquestions%2F42893664%2Ffirebase-photourl-from-a-google-auth-provider-returns-a-jpg-with-colors-inverted&psig=AOvVaw1rsKyabxOup86UrqGbfpsp&ust=1714873347675000&source=images&cd=vfe&opi=89978449&ved=0CBIQjRxqFwoTCIDx4Jjv8oUDFQAAAAAdAAAAABAD",
});

const newUser = await firebaseAuth.getUser(uid);
const { displayName, email, photoURL } = newUser!;

const displayUser = { _id, uid, displayName, email, photoURL };
displayUsers.push(displayUser);
} catch (error) {
next(error);
}
}

res.status(200).json(displayUsers as DisplayUser[]);
} catch (error) {
next(error);
}
};
9 changes: 9 additions & 0 deletions backend/src/models/user.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ObjectId } from "mongodb";
import { InferSchemaType, Schema, model } from "mongoose";

/**
Expand Down Expand Up @@ -28,6 +29,14 @@ export enum UserRole {
ADMIN = "admin",
}

export interface DisplayUser {
_id: ObjectId;
uid: string;
email: string;
displayName: string;
photoURL: string;
}

type User = InferSchemaType<typeof userSchema>;

export default model<User>("User", userSchema);
3 changes: 2 additions & 1 deletion backend/src/routes/user.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import express from "express";

import { requireSignedIn } from "src/middleware/auth";
import { requireAdmin, requireSignedIn } from "src/middleware/auth";
import * as UserController from "src/controllers/user";

const router = express.Router();

router.get("/whoami", requireSignedIn, UserController.getWhoAmI);
router.get("/", requireSignedIn, requireAdmin, UserController.getUsers);

export default router;
5 changes: 5 additions & 0 deletions frontend/public/ic_settings.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions frontend/src/api/Users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ export interface User {
role: string;
}

export interface DisplayUser {
_id: string;
uid: string;
email: string;
displayName: string;
photoURL: string;
}

export const createAuthHeader = (firebaseToken: string) => ({
Authorization: `Bearer ${firebaseToken}`,
});
Expand All @@ -19,3 +27,13 @@ export const getWhoAmI = async (firebaseToken: string): Promise<APIResult<User>>
return handleAPIError(error);
}
};

export const getAllUsers = async (firebaseToken: string): Promise<APIResult<DisplayUser[]>> => {
try {
const response = await get("/api/user", createAuthHeader(firebaseToken));
const json = (await response.json()) as DisplayUser[];
return { success: true, data: json };
} catch (error) {
return handleAPIError(error);
}
};
43 changes: 43 additions & 0 deletions frontend/src/app/staff/profile/page.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* .page {
background-color: var(--color-background);
padding-bottom: 67px;
min-height: 100vh;
} */
.main {
padding: 64px;
padding-top: 105px;
background-color: var(--color-background);
display: flex;
flex-direction: column;
color: var(--Accent-Blue-1, #102d5f);
text-align: left;

padding: 105px 120px 0;
gap: 40px;

/* gap: 32px; */
/* Desktop/H1 */
font-family: var(--font-title);
font-style: normal;
font-weight: 700;
line-height: normal;
}

.row {
display: flex;
flex-direction: row;
justify-content: space-between;
}

.column {
display: flex;
flex-direction: column;
}

.title {
font-size: 40px;
}

.subtitle {
font-size: 24px;
}
72 changes: 72 additions & 0 deletions frontend/src/app/staff/profile/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"use client";

import styles from "@/app/staff/profile/page.module.css";
import HeaderBar from "@/components/shared/HeaderBar";
import React, { useContext, useState } from "react";
import { useScreenSizes } from "@/hooks/useScreenSizes";
import { Button } from "@/components/shared/Button";
import { UserProfile } from "@/components/Profile/UserProfile";
import { AdminProfile } from "@/components/Profile/AdminProfile";
import { DisplayUser, getAllUsers } from "@/api/Users";
import { UserContext } from "@/contexts/userContext";
enum AllUsersError {

Check warning on line 12 in frontend/src/app/staff/profile/page.tsx

View workflow job for this annotation

GitHub Actions / Frontend check

'AllUsersError' is defined but never used. Allowed unused vars must match /^_/u
CANNOT_FETCH_USERS_NO_INTERNET,
CANNOT_FETCH_USERS_INTERNAL,
NONE,
}

export default function Profile() {
const { isMobile, isTablet } = useScreenSizes();

Check warning on line 19 in frontend/src/app/staff/profile/page.tsx

View workflow job for this annotation

GitHub Actions / Frontend check

'isMobile' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 19 in frontend/src/app/staff/profile/page.tsx

View workflow job for this annotation

GitHub Actions / Frontend check

'isTablet' is assigned a value but never used. Allowed unused vars must match /^_/u
const { firebaseUser, papUser } = useContext(UserContext);

Check warning on line 20 in frontend/src/app/staff/profile/page.tsx

View workflow job for this annotation

GitHub Actions / Frontend check

'papUser' is assigned a value but never used. Allowed unused vars must match /^_/u
const [users, setUsers] = useState<DisplayUser[]>([]);
// const [userError, setUserError] = useState<AllUsersError>(AllUsersError.NONE);

firebaseUser?.getIdToken().then((firebaseToken) => {
getAllUsers(firebaseToken).then((result) => {
if (result.success) {
setUsers(result.data);
console.log(result.data);
} else {
// setUserError(AllUsersError.CANNOT_FETCH_USERS_INTERNAL);
// console.log(userError);
}
});
});

// useRedirectToLoginIfNotSignedIn();

return (
<div>
<HeaderBar showLogoutButton />
<div className={styles.main}>
<h1 className={styles.title}>Account</h1>
<h1 className={styles.subtitle}>User Profile</h1>
{/* ACCOUNT INFO */}
<AdminProfile name="Justine Roberts" email="[email protected]"></AdminProfile>
<div className={styles.row}>
<h1 className={styles.subtitle}>Manage Users</h1>
<Button
variant="primary"
outlined
iconPath="/icon_plus.svg"
iconAlt="Add"
text="Add Account"
hideTextOnMobile
// onClick={() => setDeleteVsrModalOpen(true)}
/>
</div>
{/* <UserProfile name="Justin Timberlake" email="[email protected]"></UserProfile> */}
{users.map((user, index) =>
user.uid != firebaseUser?.uid ? (
<UserProfile
key={index}
email={user.email}
name={user.displayName}
photoURL={user.photoURL}
></UserProfile>
) : null,
)}
</div>
</div>
);
}
45 changes: 45 additions & 0 deletions frontend/src/components/Profile/AdminProfile/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from "react";
import styles from "@/components/Profile/AdminProfile/styles.module.css";
import Image from "next/image";
import { User } from "firebase/auth";

Check warning on line 4 in frontend/src/components/Profile/AdminProfile/index.tsx

View workflow job for this annotation

GitHub Actions / Frontend check

'User' is defined but never used. Allowed unused vars must match /^_/u

export interface AdminProps {
name: string;
email: string;
}
export function AdminProfile({ name, email }: AdminProps) {
return (
<div className={styles.admin}>
<div className={styles.column}>
<div className={styles.row_justify}>
<h1 className={styles.subtitle}>Account Information</h1>
<Image
src="/ic_settings.svg"
alt="Internal Error"
// width={isMobile ? 100 : 155}
// height={isMobile ? 69 : 106}
width={18}
height={18}
/>{" "}
</div>
<div className={styles.row}>
<Image
className={styles.pfp}
src="/Images/LoginImage.png"
alt="Internal Error"
width={93}
height={93}
/>
<div className={styles.info_column}>
<p className={styles.info_type}>Name</p>
<p className={styles.info}>{name}</p>
</div>
<div className={styles.info_column_right}>
<p className={styles.info_type}>Email Account</p>
<p className={styles.info}>{email}</p>
</div>
</div>
</div>
</div>
);
}
75 changes: 75 additions & 0 deletions frontend/src/components/Profile/AdminProfile/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
.admin {
display: flex;
flex-direction: row;
border-radius: 6px;
background: var(--Functional-Background, #f9f9f9);

display: flex;
padding: 32px;
align-items: flex-start;
gap: 10px;
align-self: stretch;
margin-bottom: 64px;
}

.row {
display: flex;
flex-direction: row;
}

.row_justify {
display: flex;
flex-direction: row;
justify-content: space-between;
}

.column {
display: flex;
flex-direction: column;
gap: 32px;
width: 100%;
}

.info_column {
display: flex;
flex-direction: column;
gap: 16px;
}

.info_column_right {
display: flex;
flex-direction: column;
gap: 16px;
margin-left: 96px;
}

.pfp {
border-radius: 50%;
margin-right: 64px;
}

.subtitle {
font-size: 24px;
}

.info_type {
color: var(--Dark-Gray, #484848);

/* Desktop/Body 2 */
font-family: var(--font-open-sans);
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: normal;
}

.info {
color: var(--Primary-Background-Dark, #232220);

/* Desktop/Body 1 */
font-family: var(--font-open-sans);
font-size: 20px;
font-style: normal;
font-weight: 400;
line-height: normal;
}
33 changes: 33 additions & 0 deletions frontend/src/components/Profile/UserProfile/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from "react";
import styles from "@/components/Profile/UserProfile/styles.module.css";
import Image from "next/image";
import { User } from "firebase/auth";

Check warning on line 4 in frontend/src/components/Profile/UserProfile/index.tsx

View workflow job for this annotation

GitHub Actions / Frontend check

'User' is defined but never used. Allowed unused vars must match /^_/u

export interface UserProps {
name: string;
email: string;
photoURL: string;
}
export function UserProfile({ name, email, photoURL }: UserProps) {
return (
<div className={styles.user}>
<div className={styles.column}>
<Image className={styles.pfp} src={photoURL} alt="Internal Error" width={93} height={93} />
</div>
<div className={styles.column_right}>
<div className={styles.row_justify}>
<p className={styles.name}>{name}</p>
<Image
src="/ic_settings.svg"
alt="Internal Error"
// width={isMobile ? 100 : 155}
// height={isMobile ? 69 : 106}
width={18}
height={18}
/>
</div>
<p className={styles.email}>{email}</p>
</div>
</div>
);
}
Loading

0 comments on commit ba9adbc

Please sign in to comment.