From c05c5af384d303845f89c19d8c5fe282c13b9387 Mon Sep 17 00:00:00 2001 From: Arjun Patel Date: Fri, 14 Jan 2022 01:42:17 -0800 Subject: [PATCH] profile page complete functionality --- models/user.ts | 7 +- pages/teams/index.tsx | 4 +- pages/teams/profile.js | 0 pages/teams/profile.tsx | 147 +++++++++++++++++++++++++++++++++++++++ services/userService.tsx | 24 ++++--- 5 files changed, 169 insertions(+), 13 deletions(-) delete mode 100644 pages/teams/profile.js create mode 100644 pages/teams/profile.tsx diff --git a/models/user.ts b/models/user.ts index b1560b9..4100354 100644 --- a/models/user.ts +++ b/models/user.ts @@ -3,12 +3,15 @@ import IFirestoreSerializable from "./firestoreSerializable"; export class User { id: string; + emailAddress: string; nickName: string; firstName: string; lastName: string; + avatarUrl: string; + userStatus: UserStatus - createdDate: Date - lastUpdatedDate: Date + createdDate: Timestamp; + lastUpdatedDate: Timestamp; // serialize() { // return { diff --git a/pages/teams/index.tsx b/pages/teams/index.tsx index f8df2cc..a931ece 100644 --- a/pages/teams/index.tsx +++ b/pages/teams/index.tsx @@ -12,7 +12,7 @@ import unfetch from 'isomorphic-unfetch' * figure out where to take the user based on everything */ function RouteHandler({ user }) { - const { currUser, logOut } = useAuth() + const { currUser } = useAuth() const router = useRouter() const userService: UserService = new UserService() @@ -31,7 +31,7 @@ function RouteHandler({ user }) { console.log(user) // if user has no profile, then go to create profile if (!user || !user.firstName || !user.lastName || !user.nickName) { - + router.push('/teams/profile') } } catch(error) { console.log(error) diff --git a/pages/teams/profile.js b/pages/teams/profile.js deleted file mode 100644 index e69de29..0000000 diff --git a/pages/teams/profile.tsx b/pages/teams/profile.tsx new file mode 100644 index 0000000..5124f73 --- /dev/null +++ b/pages/teams/profile.tsx @@ -0,0 +1,147 @@ +import { Divider } from "antd"; +import { useRouter } from "next/router"; +import { useEffect, useState } from "react"; +import { useAuth } from "../../contexts/authContext"; +import { User } from "../../models/user"; +import UserService from "../../services/userService"; +import Image from "next/image"; + + +export default function Profile() { + const { currUser, logOut } = useAuth() + const [user, setUser] = useState(null) + + const router = useRouter() + const userService: UserService = new UserService() + + useEffect(() => { + (async function() { + try { + // if not authenticated, take user to the login + if (!currUser) { + console.log('not authenticated...routing from dashboard to teams home') + // router.push('/teams/login') + } + + // get user + const returnedUser: User|null = await userService.getUser(currUser.uid) + + // if the user is null, then go ahead and create the user even though it's not there yet + if (!returnedUser) { + userService.createUser(currUser.uid, currUser.email, currUser.photoURL) + } + + console.log('got user from the backend') + + setUser(returnedUser) + setNickname(returnedUser.nickName ?? '') + setFirstName(returnedUser.firstName ?? currUser.displayName.split(" ")[0]) + setLastName(returnedUser.lastName ?? '') + } catch(error) { + console.log(error) + router.push('/teams/login') + } + })(); + }, []) + + function handleSubmit() { + if (!firstName) { + setError('Must input first name') + return + } else if (!lastName) { + setError('Must input last name') + return + } else if (!nickname) { + setError('Must input nickname') + return + } else if (nickname.length > 22) { + setError('nickname must be less than 22 characters') + return + } + + // create the user in the backend or just merge results + let newUser = new User() + newUser.id = currUser.uid + newUser.firstName = firstName + newUser.lastName = lastName + newUser.nickName = nickname + newUser.avatarUrl = currUser.photoURL + + userService.updateUser(newUser) + } + + const [firstName, setFirstName] = useState(currUser.displayName.split(" ")[0]); + const [lastName, setLastName] = useState(''); + const [nickname, setNickname] = useState('') + const [error, setError] = useState('') + + return ( +
+ {/* header */} +
Profile
+ + { + error && {error} + } + + + + + Avatar + Please change your google image to change this. + asdf + + + + Email + This is set from your Google account and cannot be changed. + + + + + First Name + + setFirstName(e.target.value)} /> + + + + Last Name + + setLastName(e.target.value)} /> + + + + Nickname + What does your team call you? + setNickname(e.target.value)} /> + + + + + + {/* if they already had a nickname, they are probably revisiting this page */} + {/* can't cancel if they are a new user */} + { + user && user.nickName ? + <> + + + + : + <> + {/* if they already had a nickname, they are probably revisiting this page */} + + + } + + + + ) +} \ No newline at end of file diff --git a/services/userService.tsx b/services/userService.tsx index 05832a4..40e417b 100644 --- a/services/userService.tsx +++ b/services/userService.tsx @@ -1,5 +1,5 @@ import { User as FirUser } from "firebase/auth"; -import { Firestore, getFirestore, doc, getDoc } from "firebase/firestore"; +import { Firestore, getFirestore, doc, getDoc, setDoc, Timestamp, serverTimestamp } from "firebase/firestore"; import { User } from '../models/user' export default class UserService { @@ -10,13 +10,9 @@ export default class UserService { } - // give back the avatar based on the person's google account avatar or if they set one then - getUserAvatar(firstName: string, lastName: string, avatar: string = null) { - if (avatar) { - return avatar - } - - return `https://ui-avatars.com/api/?name=${firstName}+${lastName}` + // give back the avatar based on the person's google account avatar + getUserAvatar(displayName: string) { + return `https://ui-avatars.com/api/?name=${displayName}` } async getUser(userId: string) : Promise { @@ -24,7 +20,7 @@ export default class UserService { const docSnap = await getDoc(docRef); if (docSnap.exists()) { - console.log("Document data:", docSnap.data()); + console.log('got user data') let user: User = docSnap.data() as User return user } else { @@ -34,4 +30,14 @@ export default class UserService { return null } } + + async createUser(userId: string, emailAddress: string, avatarUrl: string) { + const docRef = doc(this.db, UserService.collectionName, userId); + await setDoc(docRef, { emailAddress, avatarUrl, createdDate: serverTimestamp() }, { merge: true }) + } + + async updateUser(user: User) { + const docRef = doc(this.db, UserService.collectionName, user.id); + await setDoc(docRef, { ...user, lastUpdatedDate: serverTimestamp() }, { merge: true }) + } } \ No newline at end of file