diff --git a/components/Loading/index.tsx b/components/Loading/index.tsx
new file mode 100644
index 0000000..3677ad6
--- /dev/null
+++ b/components/Loading/index.tsx
@@ -0,0 +1,21 @@
+import { Divider } from "antd";
+
+export default function Loading() {
+ return (
+
+ {/* header */}
+
+
+
+
+
+
Loading
+
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/contexts/teamDashboardContext.tsx b/contexts/teamDashboardContext.tsx
new file mode 100644
index 0000000..8305ec5
--- /dev/null
+++ b/contexts/teamDashboardContext.tsx
@@ -0,0 +1,148 @@
+import { useRouter } from "next/router";
+import React, { useContext, useEffect, useState } from "react";
+import Loading from "../components/Loading";
+import { Team } from "../models/team";
+import { TeamMember, TeamMemberStatus } from "../models/teamMember";
+import { User } from "../models/user";
+import TeamService from "../services/teamService";
+import UserService from "../services/userService";
+import { useAuth } from "./authContext";
+
+interface TeamDashboardContextInterface {
+ team: Team;
+ teamMembers: TeamMember[];
+ userTeamMember: TeamMember;
+ user: User;
+}
+
+const TeamDashboardContext =
+ React.createContext(null);
+
+const teamService = new TeamService();
+const userService = new UserService();
+
+export function TeamDashboardContextProvider({ children }) {
+ const { currUser } = useAuth();
+ const [loading, setLoading] = useState(true);
+ const router = useRouter();
+ const { teamid } = router.query;
+
+ // this context can only be used if it's a specific route: '/teams'
+ if (!teamid) {
+ router.push("/teams");
+ }
+
+ // update this "global" object to send to children
+ const [value, setValue] = useState(
+ {} as TeamDashboardContextInterface
+ );
+
+ useEffect(() => {
+ (async function () {
+ try {
+ // SECTION: authentication
+ if (!currUser) {
+ console.log(
+ "not authenticated...routing from dashboard to teams home"
+ );
+ router.push("/teams/login");
+ return;
+ }
+
+ // SECTION: get user details
+ const returnedUser = await userService.getUser(currUser.uid);
+ setValue((prevValue) => ({ ...prevValue, user: returnedUser }));
+
+ // SECTION: getting team data and team member information
+ if (typeof teamid !== "string") {
+ console.log("not a proper query with teamid");
+ router.push("/teams");
+ return;
+ }
+
+ // check if the team is a valid team and that user is in it
+ const returnedTeam = await teamService.getTeam(teamid);
+ if (!returnedTeam) {
+ console.log("team doesnt exist");
+ router.push("/teams");
+ return;
+ }
+ setValue((prevValue) => ({ ...prevValue, team: returnedTeam }));
+
+ const returnedTeamMember = await teamService.getTeamMemberByUserId(
+ teamid,
+ currUser.uid
+ );
+
+ // if you are not a member of this team, then get out of here
+ // but have to check through email invite and userid
+ if (
+ returnedTeamMember &&
+ returnedTeamMember.status == TeamMemberStatus.deleted
+ ) {
+ console.log("user was deleted from team");
+ router.push("/teams");
+ return;
+ }
+
+ // if there is no team member through user id,
+ // give him last chance and see if he was invited
+ if (!returnedTeamMember) {
+ const invitedTeamMember =
+ await teamService.getTeamMemberByEmailInvite(
+ teamid,
+ currUser.email
+ );
+
+ if (!invitedTeamMember) {
+ console.log("not invited to team either");
+ router.push("/teams");
+ return;
+ }
+
+ // if I am new to the team but I was invited, and this is my first time, then activate me into the team
+ // and proceed with showing the dashboard stuff
+
+ invitedTeamMember.status = TeamMemberStatus.activated;
+ invitedTeamMember.userId = currUser.uid;
+ await teamService.updateTeamMember(invitedTeamMember);
+
+ setValue((prevValue) => ({
+ ...prevValue,
+ userTeamMember: invitedTeamMember,
+ }));
+ } else {
+ setValue((prevValue) => ({
+ ...prevValue,
+ userTeamMember: returnedTeamMember,
+ }));
+ }
+
+ // SECTION: get all teammembers for team, will have listeners in other subcomponents
+ const teamMembers = await teamService.getTeamMembersByTeamId(
+ returnedTeam.id
+ );
+ setValue((prevValue) => ({ ...prevValue, teamMembers: teamMembers }));
+ } catch (error) {
+ console.log(error);
+ router.push("/teams/login");
+ }
+
+ setLoading(false);
+ })();
+ }, []);
+
+ if (loading) {
+ return ;
+ }
+
+ return (
+
+ {children}
+
+ );
+}
+
+export function useTeamDashboardContext() {
+ return useContext(TeamDashboardContext);
+}
diff --git a/pages/teams/[teamid].tsx b/pages/teams/[teamid].tsx
index 60a8870..c4429d9 100644
--- a/pages/teams/[teamid].tsx
+++ b/pages/teams/[teamid].tsx
@@ -1,99 +1,35 @@
-import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next'
-import { useRouter } from 'next/router'
-import { useEffect, useState } from 'react'
-import BackgroundLayout from '../../components/Layouts/BackgroundLayout'
-import { useAuth } from '../../contexts/authContext'
-import { Team } from '../../models/team'
-import { TeamMemberStatus } from '../../models/teamMember'
-import TeamService from '../../services/teamService'
+import { GetServerSidePropsContext, GetServerSidePropsResult } from "next";
+import { useRouter } from "next/router";
+import { useEffect, useState } from "react";
+import BackgroundLayout from "../../components/Layouts/BackgroundLayout";
+import Loading from "../../components/Loading";
+import { useAuth } from "../../contexts/authContext";
+import {
+ TeamDashboardContextProvider,
+ useTeamDashboardContext,
+} from "../../contexts/teamDashboardContext";
+import { Team } from "../../models/team";
+import { TeamMemberStatus } from "../../models/teamMember";
+import TeamService from "../../services/teamService";
-const teamService = new TeamService()
+function TeamDashboard() {
+ const { currUser } = useAuth();
+ const router = useRouter();
+ const teamDashboardContext = useTeamDashboardContext();
-export default function TeamDashboard() {
- const { currUser } = useAuth()
- const router = useRouter()
- const { teamid } = router.query
+ console.log(teamDashboardContext);
- const [loading, setLoading] = useState(true)
- const [team, setTeam] = useState(null)
-
- 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')
- return
- }
-
- if (typeof teamid !== "string") {
- console.log('not a proper query with teamid')
- router.push('/teams')
- return
- }
-
- // check if the team is a valid team and that user is in it
- const returnedTeam = await teamService.getTeam(teamid)
- if (!returnedTeam) {
- console.log('team doesnt exist')
- router.push('/teams')
- return
- }
-
- const returnedTeamMember = await teamService.getTeamMemberByUserId(teamid, currUser.uid)
-
- console.log(returnedTeam)
- console.log(returnedTeamMember)
-
- // if you are not a member of this team, then get out of here
- // but have to check through email invite and userid
- if (returnedTeamMember && returnedTeamMember.status == TeamMemberStatus.deleted) {
- console.log('user was deleted from team')
- router.push('/teams')
- return
- }
-
- // if there is no team member through user id,
- // give him last chance and see if he was invited
- if (!returnedTeamMember) {
- const invitedTeamMember = await teamService.getTeamMemberByEmailInvite(teamid, currUser.email)
-
- if (!invitedTeamMember) {
- console.log('not invited to team either')
- router.push('/teams')
- return
- }
-
- // if I am new to the team but I was invited, and this is my first time, then activate me into the team
- // and proceed with showing the dashboard stuff
-
- invitedTeamMember.status = TeamMemberStatus.activated
- invitedTeamMember.userId = currUser.uid
- await teamService.updateTeamMember(invitedTeamMember)
- }
- } catch(error) {
- console.log(error)
- router.push('/teams/login')
- }
-
- setLoading(false)
- })();
- }, [])
-
- if (loading) {
- return (
-
loading
- )
- }
+ return
{JSON.stringify(teamDashboardContext)}
;
+}
+export default function TeamDashboardWrapper() {
return (
-
- the team is {teamid}
-
-
-
- )
+
+
+
+
+
+ );
}
export async function getServerSideProps(context: GetServerSidePropsContext) {
@@ -105,5 +41,5 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
return {
props: {},
- }
-}
\ No newline at end of file
+ };
+}
diff --git a/pages/teams/index.tsx b/pages/teams/index.tsx
index a803708..952745a 100644
--- a/pages/teams/index.tsx
+++ b/pages/teams/index.tsx
@@ -1,72 +1,80 @@
-import { useAuth } from "../../contexts/authContext"
-import { useRouter } from "next/router"
-import { useEffect, useState } from "react"
-import UserService from '../../services/userService'
-import { User } from "../../models/user"
-import { GetServerSidePropsContext } from "next"
-import nookies from 'nookies'
-import firebaseAdmin from 'firebase-admin'
-import unfetch from 'isomorphic-unfetch'
-import {
- FaPeopleCarry,
- FaArrowRight,
- FaBullhorn
-} from "react-icons/fa";
-import BackgroundLayout from "../../components/Layouts/BackgroundLayout"
-import TeamService from "../../services/teamService"
+import { useAuth } from "../../contexts/authContext";
+import { useRouter } from "next/router";
+import { useEffect, useState } from "react";
+import UserService from "../../services/userService";
+import { User } from "../../models/user";
+import { GetServerSidePropsContext } from "next";
+import nookies from "nookies";
+import firebaseAdmin from "firebase-admin";
+import unfetch from "isomorphic-unfetch";
+import { FaPeopleCarry, FaArrowRight, FaBullhorn } from "react-icons/fa";
+import BackgroundLayout from "../../components/Layouts/BackgroundLayout";
+import TeamService from "../../services/teamService";
/**
* figure out where to take the user based on everything
*/
-const userService: UserService = new UserService()
-const teamService: TeamService = new TeamService()
+const userService: UserService = new UserService();
+const teamService: TeamService = new TeamService();
function RouteHandler() {
- const { currUser } = useAuth()
- const router = useRouter()
-
- const [loading, setLoading] = useState(true)
- const [user, setUser] = useState(null)
+ const { currUser } = useAuth();
+ const router = useRouter();
+
+ const [loading, setLoading] = useState(true);
+ const [user, setUser] = useState(null);
useEffect(() => {
- (async function() {
+ (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')
+ 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)
- console.log(returnedUser)
+ // get user
+ const returnedUser: User | null = await userService.getUser(
+ currUser.uid
+ );
+ console.log(returnedUser);
// if user has no profile, then go to create profile
- if (!returnedUser || !returnedUser.firstName || !returnedUser.lastName || !returnedUser.nickName) {
- console.log('no profile for the user, routing him/her there')
- router.push('/teams/profile')
- }
- setUser(returnedUser)
-
- // check if user is in a team go to the team dashboard
- const returnedTeamMembers = await teamService.getTeamMembersByUserId(currUser.uid)
- if (returnedTeamMembers.length > 0) {
- console.log('in a team! going to the team dashboard of the first one!')
- router.push('/teams/' + returnedTeamMembers[0].teamId)
- return
+ if (
+ !returnedUser ||
+ !returnedUser.firstName ||
+ !returnedUser.lastName ||
+ !returnedUser.nickName
+ ) {
+ console.log("no profile for the user, routing him/her there");
+ router.push("/teams/profile");
}
+ setUser(returnedUser);
- } catch(error) {
- console.log(error)
- router.push('/teams/login')
+ // check if user is in a team go to the team dashboard
+ const returnedTeamMembers = await teamService.getTeamMembersByUserId(
+ currUser.uid
+ );
+ if (returnedTeamMembers.length > 0) {
+ console.log(
+ "in a team! going to the team dashboard of the first one!"
+ );
+ router.push("/teams/" + returnedTeamMembers[0].teamId);
+ return;
+ }
+ } catch (error) {
+ console.log(error);
+ router.push("/teams/login");
}
})();
- setLoading(false)
- }, [currUser])
+ setLoading(false);
+ }, [currUser]);
if (loading || !user) {
- return
+ return ;
}
// not in a team yet, and have not created a team yet
@@ -76,25 +84,36 @@ function RouteHandler() {
👋Hey, {user.firstName}
- Let's get you started.
+
+ Let's get you started.
+
-
-
{/* create team hover thing */}
- router.push('/teams/create')} className="group flex flex-row py-5 px-3 items-center border border-dashed rounded hover:shadow-lg transition duration-400">
+ router.push("/teams/create")}
+ className="group flex flex-row py-5 px-3 items-center border border-dashed rounded hover:shadow-lg transition duration-400"
+ >
Create a Team
- Add members, and get started immediately.
+
+ Add members, and get started immediately.
+
-
-
+
+
@@ -104,14 +123,23 @@ function RouteHandler() {
Remind Your Manager
- Your account email is {user.emailAddress}
+
+ Your account email is {user.emailAddress}
+
-
- or learn more about router.push('/teams/landing')} className="underline font-satisfy text-xl text-teal-500 decoration-teal-500">nirvana
+
+ or learn more about{" "}
+ router.push("/teams/landing")}
+ className="underline font-satisfy text-xl text-teal-500 decoration-teal-500"
+ >
+ nirvana
+
+
- )
+ );
}
export async function getServerSideProps(context: GetServerSidePropsContext) {
@@ -143,14 +171,14 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
// console.log(e)
// }
// }
-
+
// // Pass data to the page via props
- // return { props: {
+ // return { props: {
// user
// }
// }
- return { props: { }}
+ return { props: {} };
}
-export default RouteHandler
+export default RouteHandler;
diff --git a/services/teamService.tsx b/services/teamService.tsx
index a34e56c..16660b0 100644
--- a/services/teamService.tsx
+++ b/services/teamService.tsx
@@ -1,34 +1,55 @@
-import { addDoc, collection, doc, DocumentReference, Firestore, getDoc, getDocs, getFirestore, orderBy, query, serverTimestamp, setDoc, where } from 'firebase/firestore'
-import { Team } from '../models/team'
-import { TeamMember, TeamMemberRole, TeamMemberStatus } from '../models/teamMember'
-import { Collections } from './collections'
-import IService from './IService'
+import {
+ addDoc,
+ collection,
+ doc,
+ DocumentReference,
+ Firestore,
+ getDoc,
+ getDocs,
+ getFirestore,
+ orderBy,
+ query,
+ serverTimestamp,
+ setDoc,
+ where,
+} from "firebase/firestore";
+import { Team } from "../models/team";
+import {
+ TeamMember,
+ TeamMemberRole,
+ TeamMemberStatus,
+} from "../models/teamMember";
+import { Collections } from "./collections";
+import IService from "./IService";
export default class TeamService implements IService {
- db : Firestore = getFirestore()
+ db: Firestore = getFirestore();
async createTeam(team: Team): Promise {
// create team
const teamDocRef = await addDoc(collection(this.db, Collections.teams), {
...team,
- createdDate: serverTimestamp()
- })
+ createdDate: serverTimestamp(),
+ });
- const teamMember = new TeamMember()
- teamMember.role = TeamMemberRole.admin
- teamMember.teamId = teamDocRef.id
- teamMember.userId = team.createdByUserId
- teamMember.status = TeamMemberStatus.activated
+ const teamMember = new TeamMember();
+ teamMember.role = TeamMemberRole.admin;
+ teamMember.teamId = teamDocRef.id;
+ teamMember.userId = team.createdByUserId;
+ teamMember.status = TeamMemberStatus.activated;
// create team member as admin who created the team
- const teamMemberRef = await addDoc(collection(this.db, Collections.teamMembers), {
- ...teamMember,
- createdDate: serverTimestamp()
- })
+ const teamMemberRef = await addDoc(
+ collection(this.db, Collections.teamMembers),
+ {
+ ...teamMember,
+ createdDate: serverTimestamp(),
+ }
+ );
- console.log('created team')
+ console.log("created team");
- return teamDocRef.id
+ return teamDocRef.id;
}
async getTeam(teamId: string): Promise {
@@ -36,105 +57,135 @@ export default class TeamService implements IService {
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
- console.log('got team data')
- let team: Team = docSnap.data() as Team
- team.id = docSnap.id
- return team
+ console.log("got team data");
+ let team: Team = docSnap.data() as Team;
+ team.id = docSnap.id;
+ return team;
} else {
// doc.data() will be undefined in this case
console.log("team not found!");
-
- return null
+
+ return null;
}
}
-
- async getTeamMemberByUserId(teamId: string, userId: string): Promise {
+
+ async getTeamMemberByUserId(
+ teamId: string,
+ userId: string
+ ): Promise {
const q = query(
- collection(this.db, Collections.teamMembers),
+ collection(this.db, Collections.teamMembers),
where("teamId", "==", teamId),
where("userId", "==", userId)
- )
-
+ );
+
const querySnapshot = await getDocs(q);
-
+
if (querySnapshot.size > 1) {
- console.log('there are multiple teammembers for this user...error in teamservice')
+ console.log(
+ "there are multiple teammembers for this user...error in teamservice"
+ );
}
- console.log(querySnapshot)
-
- var teamMember: TeamMember | null = null
+ var teamMember: TeamMember | null = null;
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
// get the first one and just return...shouldn't be more
- console.log('got teammember data')
- teamMember = doc.data() as TeamMember
+ console.log("got teammember data");
+ teamMember = doc.data() as TeamMember;
- teamMember.id = doc.id
+ teamMember.id = doc.id;
});
- return teamMember
+ return teamMember;
}
- async getTeamMemberByEmailInvite(teamId: string, emailAddress: string): Promise {
+ async getTeamMemberByEmailInvite(
+ teamId: string,
+ emailAddress: string
+ ): Promise {
const q = query(
- collection(this.db, Collections.teamMembers),
+ collection(this.db, Collections.teamMembers),
where("teamId", "==", teamId),
where("inviteEmailAddress", "==", emailAddress)
- )
-
+ );
+
const querySnapshot = await getDocs(q);
-
+
if (querySnapshot.size > 1) {
- console.log('there are multiple teammembers for this user...error in teamservice')
+ console.log(
+ "there are multiple teammembers for this user...error in teamservice"
+ );
}
- console.log(querySnapshot)
-
- var teamMember: TeamMember | null = null
+ var teamMember: TeamMember | null = null;
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
// get the first one and just return...shouldn't be more
- console.log('got teammember data')
- teamMember = doc.data() as TeamMember
+ console.log("got teammember data");
+ teamMember = doc.data() as TeamMember;
- teamMember.id = doc.id
+ teamMember.id = doc.id;
});
- return teamMember
+ return teamMember;
}
async getTeamMembersByUserId(userId: string): Promise {
const q = query(
- collection(this.db, Collections.teamMembers),
- where("userId", "==", userId),
- )
-
+ collection(this.db, Collections.teamMembers),
+ where("userId", "==", userId)
+ );
+
const querySnapshot = await getDocs(q);
-
+
if (querySnapshot.size > 1) {
- console.log('this user is part of multiple teams')
+ console.log("this user is part of multiple teams");
}
- console.log(querySnapshot)
-
- var teamMembers: TeamMember[] = []
+ var teamMembers: TeamMember[] = [];
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
// get the first one and just return...shouldn't be more
- console.log('got teammember data')
- let teamMember:TeamMember = doc.data() as TeamMember
- teamMember.id = doc.id
+ console.log("got teammember data");
+ let teamMember: TeamMember = doc.data() as TeamMember;
+ teamMember.id = doc.id;
- teamMembers.push(teamMember)
+ teamMembers.push(teamMember);
});
- return teamMembers
+ return teamMembers;
+ }
+
+ async getTeamMembersByTeamId(teamId: string): Promise {
+ const q = query(
+ collection(this.db, Collections.teamMembers),
+ where("teamId", "==", teamId)
+ );
+
+ const querySnapshot = await getDocs(q);
+
+ var teamMembers: TeamMember[] = [];
+
+ querySnapshot.forEach((doc) => {
+ // doc.data() is never undefined for query doc snapshots
+ // get the first one and just return...shouldn't be more
+ let teamMember: TeamMember = doc.data() as TeamMember;
+ teamMember.id = doc.id;
+
+ teamMembers.push(teamMember);
+ });
+
+ return teamMembers;
}
async updateTeamMember(teamMember: TeamMember) {
const docRef = doc(this.db, Collections.teamMembers, teamMember.id);
- await setDoc(docRef, { ...teamMember, lastUpdatedDate: serverTimestamp() }, { merge: true })
- }
-}
\ No newline at end of file
+ await setDoc(
+ docRef,
+ { ...teamMember, lastUpdatedDate: serverTimestamp() },
+ { merge: true }
+ );
+ }
+}