diff --git a/Utility.js b/Utility.js
index e4764d51..7411a9a3 100644
--- a/Utility.js
+++ b/Utility.js
@@ -113,6 +113,9 @@ export function getIconByKey(key) {
}
export function getInitials(fullName) {
+ if (!fullName) {
+ return "?";
+ }
const nameParts = fullName.trim().split(/\s+/);
return nameParts.map((part) => part.charAt(0).toUpperCase()).join("");
}
diff --git a/app/(auth)/signup.js b/app/(auth)/signup.js
index cd38b0e8..3fcef494 100644
--- a/app/(auth)/signup.js
+++ b/app/(auth)/signup.js
@@ -59,16 +59,6 @@ export default function SignUp() {
await setDoc(doc(db, "users", userCredential.user.uid), {
email: email,
});
- await setDoc(doc(db, "teams", "1", "users", userCredential.user.uid), {
- name: name,
- // hardcoded pfp string for now, add pfp upload to profile settings in future PR
- pfp: "",
- // hardcoded "player" role for now, add role selection to profile settings in future PR
- role: "player",
- uid: userCredential.user.uid,
- assigned_data: [],
- uniqueDrills: [],
- });
try {
await sendEmailVerification(auth.currentUser);
@@ -80,7 +70,7 @@ export default function SignUp() {
}
setCurrentUserId(userCredential.user.uid);
- setCurrentUserInfo(userCredential.user);
+ setCurrentUserInfo({ ...userCredential.user, displayName: name });
// console.log(userCredential.user);
} catch (e) {
diff --git a/app/content/team/index.js b/app/content/team/index.js
index 6ae0b7dc..f90d4f88 100644
--- a/app/content/team/index.js
+++ b/app/content/team/index.js
@@ -109,9 +109,12 @@ function Index() {
/>
);
const foundUsers = Object.values(userInfo)
- .filter((user) =>
- user.name.toLowerCase().includes(searchQuery.toLowerCase()),
- )
+ .filter((user) => {
+ if (!user.name) {
+ return true;
+ }
+ return user.name.toLowerCase().includes(searchQuery.toLowerCase());
+ })
.sort((user1, user2) => {
// Assign priorities based on conditions
const getPriority = (user) => {
@@ -136,6 +139,11 @@ function Index() {
return priority1 - priority2;
}
+ //doesn't softlock in case displayName is null for some reason
+ if (!user1.name) {
+ return -1;
+ }
+
// If priorities are the same, then sort alphabetically by name
return user1.name.localeCompare(user2.name);
});
diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js
index a2cd92a5..1d11662a 100644
--- a/app/segments/(team)/chooseTeam.js
+++ b/app/segments/(team)/chooseTeam.js
@@ -5,8 +5,7 @@ import {
sendEmailVerification,
signOut as signoutFireBase,
} from "firebase/auth";
-import { doc, setDoc } from "firebase/firestore";
-import { useCallback, useEffect, useState } from "react";
+import { useCallback, useEffect, useMemo, useState } from "react";
import { RefreshControl, ScrollView, Text, View } from "react-native";
import { Button } from "react-native-paper";
import { SafeAreaView } from "react-native-safe-area-context";
@@ -16,13 +15,21 @@ import ErrorComponent from "~/components/errorComponent";
import Loading from "~/components/loading";
import { useAlertContext } from "~/context/Alert";
import { useAuthContext } from "~/context/Auth";
+import { addToTeam } from "~/dbOperations/addToTeam";
+import { addToWaitlist } from "~/dbOperations/addToWaitlist";
import { useBlackList } from "~/dbOperations/hooks/useBlackList";
+import { useWaitlist } from "~/dbOperations/hooks/useWaitlist";
import { invalidateMultipleKeys } from "~/dbOperations/invalidateMultipleKeys";
-import { auth, db } from "~/firebaseConfig";
+import { auth } from "~/firebaseConfig";
function ChooseTeam() {
- const { signOut, currentUserId, currentUserInfo, setCurrentUserId } =
- useAuthContext();
+ const {
+ signOut,
+ currentUserId,
+ currentUserInfo,
+ setCurrentUserId,
+ currentTeamId,
+ } = useAuthContext();
const queryClient = useQueryClient();
const { showDialog, showSnackBar } = useAlertContext();
@@ -33,12 +40,32 @@ function ChooseTeam() {
isLoading: blacklistIsLoading,
} = useBlackList();
- const invalidateKeys = [["blacklist"]];
+ const {
+ data: waitlist,
+ error: waitlistError,
+ isLoading: waitlistIsLoading,
+ } = useWaitlist();
+
+ const state = useMemo(() => {
+ if (blacklist && blacklist[currentUserId]) {
+ return "blacklist";
+ }
+ if (waitlist && waitlist[currentUserId]) {
+ return "waitlist";
+ }
+ return "neutral";
+ }, [blacklist, currentUserId, waitlist]); //blacklist, waitlist, invited, neutral
const [verified, setVerified] = useState(false);
const [refreshing, setRefreshing] = useState(false); //for Refresh Control
const [loading, setLoading] = useState(false); //for resend email button
+ const invalidateKeys = [
+ ["blacklist"],
+ ["waitlist"],
+ ["userInfo", { userId: currentUserId }],
+ ];
+
async function handleSignOut() {
try {
await signoutFireBase(auth);
@@ -88,12 +115,12 @@ function ChooseTeam() {
setRefreshing(false);
}, []);
- if (blacklistIsLoading) {
+ if (blacklistIsLoading || waitlistIsLoading) {
return ;
}
- if (blacklistError) {
- return ;
+ if (blacklistError || waitlistError) {
+ return ;
}
return (
@@ -109,39 +136,79 @@ function ChooseTeam() {
}
contentContainerStyle={{ flex: 1, justifyContent: "center" }}
>
-
- {blacklist[currentUserId] ? (
-
+ Waiting for email verification...
+
- ) : verified ? (
+
+ Resend Verification Email
+
+
+
+ ) : state === "blacklist" ? (
+
+ You've been banned from this team.
+
+ ) : state === "waitlist" ? (
+
+ Your request to join the team has been received
+
+ ) : state === "invited" ? (
+
- ) : (
-
+ ) : (
+
+
- )}
+ Request to Join Team
+
+
+
+ )}
+
({
invites: <>>,
- waitlist: <>>,
+ waitlist: ,
blacklist: ,
}),
[],
diff --git a/app/segments/(team)/waitlist.js b/app/segments/(team)/waitlist.js
new file mode 100644
index 00000000..012ec848
--- /dev/null
+++ b/app/segments/(team)/waitlist.js
@@ -0,0 +1,87 @@
+import { useQueryClient } from "@tanstack/react-query";
+import { ScrollView, View } from "react-native";
+import { Button, List } from "react-native-paper";
+import { getErrorString } from "~/Utility";
+import ErrorComponent from "~/components/errorComponent";
+import Loading from "~/components/loading";
+import RefreshInvalidate from "~/components/refreshInvalidate";
+import { useAuthContext } from "~/context/Auth";
+import { addToTeam } from "~/dbOperations/addToTeam";
+import { useWaitlist } from "~/dbOperations/hooks/useWaitlist";
+import { invalidateMultipleKeys } from "~/dbOperations/invalidateMultipleKeys";
+import { removeWaitlist } from "~/dbOperations/removeWaitlist";
+
+function Waitlist() {
+ const {
+ data: waitlist,
+ error: waitlistError,
+ isLoading: waitlistIsLoading,
+ } = useWaitlist();
+
+ const { currentTeamId } = useAuthContext();
+ const queryClient = useQueryClient();
+
+ if (waitlistError) {
+ return ;
+ }
+
+ if (waitlistIsLoading) {
+ return ;
+ }
+
+ const invalidateKeys = [["waitlist"], ["userInfo"]];
+
+ return (
+ }
+ >
+
+ {Object.keys(waitlist).map((userId) => {
+ console.log("waitlist", waitlist[userId]);
+ return (
+ (
+
+ {
+ await addToTeam(currentTeamId, userId, waitlist[userId]);
+ await removeWaitlist(currentTeamId, userId);
+ await invalidateMultipleKeys(queryClient, invalidateKeys);
+ }}
+ textColor={"green"}
+ >
+ Accept
+
+ {
+ await removeWaitlist(currentTeamId, userId);
+ await invalidateMultipleKeys(queryClient, invalidateKeys);
+ }}
+ textColor={"red"}
+ >
+ Reject
+
+
+ )}
+ />
+ );
+ })}
+
+
+ );
+}
+
+export default Waitlist;
diff --git a/dbOperations/addToTeam.js b/dbOperations/addToTeam.js
new file mode 100644
index 00000000..d7551129
--- /dev/null
+++ b/dbOperations/addToTeam.js
@@ -0,0 +1,22 @@
+import { doc, setDoc } from "firebase/firestore";
+import { db } from "~/firebaseConfig";
+
+//temporary, should be replaced with multiple team functionality
+export async function addToTeam(currentTeamId, currentUserId, currentUserInfo) {
+ console.log("currentUserInfo", currentUserInfo);
+ try {
+ await setDoc(doc(db, "teams", currentTeamId, "users", currentUserId), {
+ name: currentUserInfo["displayName"],
+ // hardcoded pfp string for now, add pfp upload to profile settings in future PR
+ pfp: "",
+ // hardcoded "player" role for now, add role selection to profile settings in future PR
+ role: "player",
+ uid: currentUserId,
+ assigned_data: [],
+ uniqueDrills: [],
+ });
+ } catch (e) {
+ console.log("Add to Team failed: ", e);
+ throw e; // Rethrow the error to handle it at the caller's level if needed
+ }
+}
diff --git a/dbOperations/addToWaitlist.js b/dbOperations/addToWaitlist.js
new file mode 100644
index 00000000..e7a2593c
--- /dev/null
+++ b/dbOperations/addToWaitlist.js
@@ -0,0 +1,27 @@
+import { doc, setDoc } from "firebase/firestore";
+import { db } from "~/firebaseConfig";
+
+export async function addToWaitlist(
+ currentTeamId,
+ currentUserId,
+ currentUserInfo,
+) {
+ try {
+ const newRequestRef = doc(
+ db,
+ "teams",
+ currentTeamId,
+ "waitlist",
+ currentUserId,
+ );
+ const currentTime = Date.now();
+ await setDoc(newRequestRef, {
+ displayName: currentUserInfo["displayName"],
+ email: currentUserInfo["email"],
+ time: currentTime,
+ });
+ } catch (e) {
+ console.log("Add to Waitlist failed: ", e);
+ throw e; // Rethrow the error to handle it at the caller's level if needed
+ }
+}
diff --git a/dbOperations/hooks/useWaitlist.js b/dbOperations/hooks/useWaitlist.js
new file mode 100644
index 00000000..add4fde6
--- /dev/null
+++ b/dbOperations/hooks/useWaitlist.js
@@ -0,0 +1,30 @@
+import { useQuery } from "@tanstack/react-query";
+import { collection, getDocs } from "firebase/firestore";
+import { useAuthContext } from "~/context/Auth";
+import { db } from "~/firebaseConfig";
+
+export const useWaitlist = ({ enabled = true } = {}) => {
+ const { currentTeamId } = useAuthContext();
+ const { data, error, isLoading } = useQuery({
+ queryKey: ["waitlist"],
+ queryFn: async () => {
+ console.log("fetching waitlist");
+ const newWaitlist = {};
+ // Fetch all Entries on the Waitlist
+ const querySnapshot = await getDocs(
+ collection(db, "teams", currentTeamId, "waitlist"),
+ );
+ querySnapshot.forEach((doc) => {
+ newWaitlist[doc.id] = doc.data();
+ });
+ return newWaitlist;
+ },
+ enabled,
+ });
+
+ return {
+ data,
+ error,
+ isLoading,
+ };
+};
diff --git a/dbOperations/removeWaitlist.js b/dbOperations/removeWaitlist.js
new file mode 100644
index 00000000..5605dde4
--- /dev/null
+++ b/dbOperations/removeWaitlist.js
@@ -0,0 +1,13 @@
+import { deleteDoc, doc } from "firebase/firestore";
+import { db } from "~/firebaseConfig";
+
+async function removeWaitlist(teamId, userId) {
+ try {
+ await deleteDoc(doc(db, "teams", teamId, "waitlist", userId));
+ } catch (e) {
+ console.log("Remove Blacklist Transaction failed: ", e);
+ throw e; // Rethrow the error to handle it at the caller's level if needed
+ }
+}
+
+module.exports = { removeWaitlist };