From 8ca99336a855c020e7d80486293b1af8877b6215 Mon Sep 17 00:00:00 2001 From: Frankreed Date: Sun, 14 Jul 2024 22:15:54 +0700 Subject: [PATCH 01/56] added blacklist hook --- app/segments/(team)/chooseTeam.js | 48 +++++++++--------------------- dbOperations/hooks/useBlackList.js | 31 +++++++++++++++++++ 2 files changed, 45 insertions(+), 34 deletions(-) create mode 100644 dbOperations/hooks/useBlackList.js diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js index 246ef913..4aeaa84c 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -1,8 +1,7 @@ import { useQueryClient } from "@tanstack/react-query"; import { router } from "expo-router"; import { signOut as signoutFireBase } from "firebase/auth"; -import { doc, getDoc, setDoc } from "firebase/firestore"; -import { useEffect, useState } from "react"; +import { doc, setDoc } from "firebase/firestore"; import { Text, View } from "react-native"; import { Button } from "react-native-paper"; import { SafeAreaView } from "react-native-safe-area-context"; @@ -12,6 +11,7 @@ import ErrorComponent from "~/components/errorComponent"; import Loading from "~/components/loading"; import { useAlertContext } from "~/context/Alert"; import { useAuthContext } from "~/context/Auth"; +import { useBlackList } from "~/dbOperations/hooks/useBlackList"; import { invalidateMultipleKeys } from "~/dbOperations/invalidateMultipleKeys"; import { auth, db } from "~/firebaseConfig"; @@ -22,10 +22,19 @@ function ChooseTeam() { const { showDialog } = useAlertContext(); - const [blacklist, setBlacklist] = useState(false); + const { + data: blacklist, + error: blacklistError, + isLoading: blacklistIsLoading, + } = useBlackList(); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); + if (blacklistIsLoading) { + return ; + } + + if (blacklistError) { + return ; + } async function handleSignOut() { try { @@ -37,35 +46,6 @@ function ChooseTeam() { } } - // TODO: make an actual hook for this? Shouldn't be related tho, as is coach pov? - useEffect(() => { - const fetchBlacklistDoc = async () => { - try { - const docRef = doc(db, "teams", "1", "blacklist", currentUserId); - const docSnap = await getDoc(docRef); - - //See if the user is on blacklist - setBlacklist(docSnap.exists()); - } catch (e) { - setError(e); - } finally { - setLoading(false); - } - }; - - if (currentUserId) { - fetchBlacklistDoc(); - } - }, [currentUserId]); - - if (loading) { - return ; - } - - if (error) { - return ; - } - return ( { + const { currentTeamId } = useAuthContext(); + + const { data, error, isLoading } = useQuery({ + queryKey: ["blackList"], + queryFn: async () => { + console.log("fetching blacklist"); + // Fetch all time records + const querySnapshot = await getDoc( + doc(db, "teams", currentTeamId, "blacklist"), + ); + const data = querySnapshot.data(); + if (data === undefined) { + return false; + } + return querySnapshot.data(); + }, + enabled, + }); + + return { + data, + error, + isLoading, + }; +}; From ac7e8153261549c18930363958a2b2731c97892d Mon Sep 17 00:00:00 2001 From: Frankreed Date: Tue, 16 Jul 2024 18:12:00 +0700 Subject: [PATCH 02/56] black list feature works --- app/content/team/index.js | 88 +++++++++-------- app/segments/(team)/blacklist.js | 71 ++++++++++++++ app/segments/(team)/manageForeignRequests.js | 99 ++++++++++++++++++++ dbOperations/hooks/useBlackList.js | 18 ++-- dbOperations/removeBlacklist.js | 18 ++++ update_unique.py | 32 ++++--- 6 files changed, 265 insertions(+), 61 deletions(-) create mode 100644 app/segments/(team)/blacklist.js create mode 100644 app/segments/(team)/manageForeignRequests.js create mode 100644 dbOperations/removeBlacklist.js diff --git a/app/content/team/index.js b/app/content/team/index.js index cd8ff9e2..03a9a4a9 100644 --- a/app/content/team/index.js +++ b/app/content/team/index.js @@ -242,48 +242,62 @@ function Index() {
{ - setMenuVisible(false); - }} - anchor={ - { - setMenuVisible(true); - }} - color={themeColors.accent} - /> - } - statusBarHeight={45} - anchorPosition="bottom" - contentStyle={{ - backgroundColor: themeColors.background, - }} - > - + {currentUserInfo.role === "coach" || + currentUserInfo.role === "owner" ? ( + { - bottomSheetModalRef.current?.present(); - setMenuVisible(false); + router.push("/segments/(team)/manageForeignRequests"); }} - title="Edit Team" + color={themeColors.accent} /> - { - console.log("Reset Season Pressed!"); + ) : ( + <> + )} + {currentUserInfo.role === "owner" ? ( + { setMenuVisible(false); - setResetDialogVisible(true); }} - title="Reset Season" - /> - - ) : ( - <> - ) + anchor={ + { + setMenuVisible(true); + }} + color={themeColors.accent} + /> + } + statusBarHeight={45} + anchorPosition="bottom" + contentStyle={{ + backgroundColor: themeColors.background, + }} + > + { + bottomSheetModalRef.current?.present(); + setMenuVisible(false); + }} + title="Edit Team" + /> + { + console.log("Reset Season Pressed!"); + setMenuVisible(false); + setResetDialogVisible(true); + }} + title="Reset Season" + /> + + ) : ( + <> + )} + } /> ; + + if (blacklistError) return ; + + return ( + } + > + + {Object.keys(blacklist).map((userId, idx) => { + return ( + ( + + + + )} + /> + ); + })} + + + ); +} + +export default Blacklist; diff --git a/app/segments/(team)/manageForeignRequests.js b/app/segments/(team)/manageForeignRequests.js new file mode 100644 index 00000000..da02e979 --- /dev/null +++ b/app/segments/(team)/manageForeignRequests.js @@ -0,0 +1,99 @@ +import { useNavigation } from "expo-router"; +import { useMemo, useState } from "react"; +import { Appbar, SegmentedButtons } from "react-native-paper"; +import { SafeAreaView } from "react-native-safe-area-context"; +import { themeColors } from "~/Constants"; +import Blacklist from "~/app/segments/(team)/blacklist"; +import Header from "~/components/header"; + +function ManageForeignRequests(props) { + const [tabValue, setTabValue] = useState("invites"); + const navigation = useNavigation(); + + const segmentedColor = (tab) => { + switch (tab) { + case "invites": + return "#008001"; + case "waitlist": + return "#FFE900"; + case "blacklist": + return "#FE0100"; + default: + return themeColors.overlay; + } + }; + + const segmentedTextColor = (tab) => { + switch (tab) { + case "invites": + case "blacklist": + return "white"; + case "waitlist": + return "black"; + default: + return "black"; + } + }; + + const tabComponent = useMemo( + () => ({ + invites: <>, + waitlist: <>, + blacklist: , + }), + [], + ); // Recreate pages only if drillId changes + + return ( + +
{ + navigation.goBack(); + }} + color={themeColors.accent} + /> + } + /> + + {tabComponent[tabValue]} + + ); +} + +export default ManageForeignRequests; diff --git a/dbOperations/hooks/useBlackList.js b/dbOperations/hooks/useBlackList.js index 4e4613cf..23b551d6 100644 --- a/dbOperations/hooks/useBlackList.js +++ b/dbOperations/hooks/useBlackList.js @@ -1,5 +1,5 @@ import { useQuery } from "@tanstack/react-query"; -import { doc, getDoc } from "firebase/firestore"; +import { collection, getDocs } from "firebase/firestore"; import { useAuthContext } from "~/context/Auth"; import { db } from "~/firebaseConfig"; @@ -7,18 +7,18 @@ export const useBlackList = ({ enabled = true } = {}) => { const { currentTeamId } = useAuthContext(); const { data, error, isLoading } = useQuery({ - queryKey: ["blackList"], + queryKey: ["blacklist"], queryFn: async () => { console.log("fetching blacklist"); + const newBlacklist = {}; // Fetch all time records - const querySnapshot = await getDoc( - doc(db, "teams", currentTeamId, "blacklist"), + const querySnapshot = await getDocs( + collection(db, "teams", currentTeamId, "blacklist"), ); - const data = querySnapshot.data(); - if (data === undefined) { - return false; - } - return querySnapshot.data(); + querySnapshot.forEach((doc) => { + newBlacklist[doc.id] = doc.data(); + }); + return newBlacklist; }, enabled, }); diff --git a/dbOperations/removeBlacklist.js b/dbOperations/removeBlacklist.js new file mode 100644 index 00000000..e1d43120 --- /dev/null +++ b/dbOperations/removeBlacklist.js @@ -0,0 +1,18 @@ +import { doc, runTransaction } from "firebase/firestore"; +import { db } from "~/firebaseConfig"; + +async function removeBlacklist(teamId, userId) { + try { + await runTransaction(db, async (transaction) => { + //Remove user from user table where UID == userID + const userRef = doc(db, "teams", teamId, "blacklist", userId); + + await transaction.delete(userRef); + }); + } 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 = { removeBlacklist }; diff --git a/update_unique.py b/update_unique.py index 622f9ab8..3c7e5839 100644 --- a/update_unique.py +++ b/update_unique.py @@ -4,24 +4,26 @@ app = firebase_admin.initialize_app() db = firestore.client() -drillInfoRef = db.collection("teams").document("1").collection("drills") -userInfoRef = db.collection("teams").document("1").collection("users") -attemptsRef = db.collection("teams").document("1").collection("attempts") +blacklistRef = db.collection("teams").document("1").collection("blacklist") -newBestAttempts = {} # reset leaderboard -drills = [drill.to_dict() for drill in drillInfoRef.stream()] -users = [user.to_dict() for user in userInfoRef.stream()] -attempts = [attempt.to_dict() for attempt in attemptsRef.stream()] +blacklist = [user for user in blacklistRef.stream()] -userUniqueDrills = {} +for user in blacklist: + userInfoRef = db.collection("users").document(user.id) -for attempt in attempts: - if attempt["uid"] not in userUniqueDrills: - userUniqueDrills[attempt["uid"]] = set() - userUniqueDrills[attempt["uid"]].add(attempt["did"]) + blacklistEntryRef = blacklistRef.document(user.id) + blacklistEntryRef.update({"email": userInfoRef.get().to_dict()["email"]}) + + print(userInfoRef.get().to_dict()["email"]) -for user in users: - userRef = db.collection("teams").document("1").collection("users").document(user["uid"]) - userRef.update({"uniqueDrills": list(userUniqueDrills.get(user["uid"], set()))}) \ No newline at end of file + +# for attempt in attempts: +# if attempt["uid"] not in userUniqueDrills: +# userUniqueDrills[attempt["uid"]] = set() +# userUniqueDrills[attempt["uid"]].add(attempt["did"]) + +# for user in users: +# userRef = db.collection("teams").document("1").collection("users").document(user["uid"]) +# userRef.update({"uniqueDrills": list(userUniqueDrills.get(user["uid"], set()))}) \ No newline at end of file From 9fa672fcc0daa814f1fb8607e1b46faa771fe9de Mon Sep 17 00:00:00 2001 From: Frankreed Date: Tue, 16 Jul 2024 18:17:09 +0700 Subject: [PATCH 03/56] some unused stuff removal --- app/segments/(team)/blacklist.js | 2 +- app/segments/(team)/manageForeignRequests.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/segments/(team)/blacklist.js b/app/segments/(team)/blacklist.js index 7d9ef05b..500c864f 100644 --- a/app/segments/(team)/blacklist.js +++ b/app/segments/(team)/blacklist.js @@ -37,7 +37,7 @@ function Blacklist() { borderRadius: 5, }} > - {Object.keys(blacklist).map((userId, idx) => { + {Object.keys(blacklist).map((userId) => { return ( Date: Fri, 19 Jul 2024 08:44:48 +0700 Subject: [PATCH 04/56] waitlist seems to work --- Utility.js | 3 + app/(auth)/signup.js | 30 +++---- app/content/team/index.js | 9 +- app/segments/(team)/chooseTeam.js | 95 ++++++++++++++++---- app/segments/(team)/manageForeignRequests.js | 3 +- app/segments/(team)/waitlist.js | 87 ++++++++++++++++++ dbOperations/addToTeam.js | 22 +++++ dbOperations/addToWaitlist.js | 28 ++++++ dbOperations/hooks/useWaitlist.js | 30 +++++++ dbOperations/removeWaitlist.js | 13 +++ 10 files changed, 283 insertions(+), 37 deletions(-) create mode 100644 app/segments/(team)/waitlist.js create mode 100644 dbOperations/addToTeam.js create mode 100644 dbOperations/addToWaitlist.js create mode 100644 dbOperations/hooks/useWaitlist.js create mode 100644 dbOperations/removeWaitlist.js 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 477aefb6..417137f9 100644 --- a/app/(auth)/signup.js +++ b/app/(auth)/signup.js @@ -1,5 +1,5 @@ import { Link } from "expo-router"; -import { createUserWithEmailAndPassword, updateProfile } from "firebase/auth"; +import { createUserWithEmailAndPassword } from "firebase/auth"; import { doc, setDoc } from "firebase/firestore"; import { useState } from "react"; import { @@ -45,25 +45,25 @@ export default function SignUp() { email, password, ); - await updateProfile(userCredential.user, { - displayName: name, - }); + // await updateProfile(userCredential.user, { + // displayName: name, + // }); 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: [], - }); + // 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: [], + // }); 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 03a9a4a9..55a7b1e3 100644 --- a/app/content/team/index.js +++ b/app/content/team/index.js @@ -107,9 +107,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) => { diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js index 4aeaa84c..a2c72ee0 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -1,7 +1,7 @@ import { useQueryClient } from "@tanstack/react-query"; import { router } from "expo-router"; import { signOut as signoutFireBase } from "firebase/auth"; -import { doc, setDoc } from "firebase/firestore"; +import { useMemo } from "react"; import { Text, View } from "react-native"; import { Button } from "react-native-paper"; import { SafeAreaView } from "react-native-safe-area-context"; @@ -11,13 +11,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 } = useAlertContext(); @@ -28,11 +36,27 @@ function ChooseTeam() { isLoading: blacklistIsLoading, } = useBlackList(); - if (blacklistIsLoading) { + 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 + + if (blacklistIsLoading || waitlistIsLoading) { return ; } - if (blacklistError) { + if (blacklistError || waitlistError) { return ; } @@ -59,7 +83,7 @@ function ChooseTeam() { alignItems: "center", }} > - {blacklist ? ( + {state === "blacklist" ? ( You've been banned from this team. - ) : ( + ) : state === "waitlist" ? ( + + Your request to join the team has been received + + ) : state === "invited" ? ( { //temporary, should be replaced with multiple team functionality - await setDoc(doc(db, "teams", "1", "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: [], - }); + await addToTeam(currentTeamId, currentUserId, currentUserInfo); setCurrentUserId(currentUserId); await invalidateMultipleKeys(queryClient, [ ["userInfo", { userId: currentUserId }], @@ -113,6 +138,40 @@ function ChooseTeam() { + ) : ( + + + )} ({ invites: <>, - waitlist: <>, + waitlist: , blacklist: , }), [], diff --git a/app/segments/(team)/waitlist.js b/app/segments/(team)/waitlist.js new file mode 100644 index 00000000..c9e8128c --- /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 ( + ( + + + + + )} + /> + ); + })} + + + ); +} + +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..619e9457 --- /dev/null +++ b/dbOperations/addToWaitlist.js @@ -0,0 +1,28 @@ +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(); + console.log("data", currentUserInfo); + 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..4c12e4f1 --- /dev/null +++ b/dbOperations/hooks/useWaitlist.js @@ -0,0 +1,30 @@ +import { collection, getDocs } from "firebase/firestore"; +import { useAuthContext } from "~/context/Auth"; +import { useQuery } from "@tanstack/react-query"; +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 time records + const querySnapshot = await getDocs( + collection(db, "teams", currentTeamId, "waitlist"), + ); + querySnapshot.forEach((doc) => { + newWaitlist[doc.id] = doc.data(); + }); + return newWaitlist; + }, + enabled, + }); + + return { + data, + error, + isLoading, + }; +} \ No newline at end of file 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 }; From f5a185559c34db0284c43abf45347fa921ebc03c Mon Sep 17 00:00:00 2001 From: Frankreed Date: Fri, 19 Jul 2024 08:46:22 +0700 Subject: [PATCH 05/56] simplified removeBlacklist.js --- dbOperations/removeBlacklist.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/dbOperations/removeBlacklist.js b/dbOperations/removeBlacklist.js index e1d43120..2d5020f1 100644 --- a/dbOperations/removeBlacklist.js +++ b/dbOperations/removeBlacklist.js @@ -1,14 +1,9 @@ -import { doc, runTransaction } from "firebase/firestore"; +import { deleteDoc, doc } from "firebase/firestore"; import { db } from "~/firebaseConfig"; async function removeBlacklist(teamId, userId) { try { - await runTransaction(db, async (transaction) => { - //Remove user from user table where UID == userID - const userRef = doc(db, "teams", teamId, "blacklist", userId); - - await transaction.delete(userRef); - }); + await deleteDoc(doc(db, "teams", teamId, "blacklist", 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 From ca85173bc9db323c997c276c40979621db50fb61 Mon Sep 17 00:00:00 2001 From: Frankreed Date: Sat, 20 Jul 2024 17:47:02 +0700 Subject: [PATCH 06/56] pretty --- dbOperations/hooks/useWaitlist.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dbOperations/hooks/useWaitlist.js b/dbOperations/hooks/useWaitlist.js index 4c12e4f1..653a5f03 100644 --- a/dbOperations/hooks/useWaitlist.js +++ b/dbOperations/hooks/useWaitlist.js @@ -1,6 +1,6 @@ +import { useQuery } from "@tanstack/react-query"; import { collection, getDocs } from "firebase/firestore"; import { useAuthContext } from "~/context/Auth"; -import { useQuery } from "@tanstack/react-query"; import { db } from "~/firebaseConfig"; export const useWaitlist = ({ enabled = true } = {}) => { @@ -27,4 +27,4 @@ export const useWaitlist = ({ enabled = true } = {}) => { error, isLoading, }; -} \ No newline at end of file +}; From 852c832ba789653cbb57e1820adef4c2a96efcea Mon Sep 17 00:00:00 2001 From: Frankreed Date: Sun, 21 Jul 2024 17:47:55 +0700 Subject: [PATCH 07/56] removed transaction and hope that it works --- dbOperations/removeUser.js | 61 +++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/dbOperations/removeUser.js b/dbOperations/removeUser.js index d53d8e38..898ec06f 100644 --- a/dbOperations/removeUser.js +++ b/dbOperations/removeUser.js @@ -1,10 +1,11 @@ import { collection, + deleteDoc, deleteField, doc, getDocs, query, - runTransaction, + updateDoc, where, } from "firebase/firestore"; import removePfp from "~/dbOperations/removePfp"; @@ -13,48 +14,46 @@ import { getPfpName } from "~/Utility"; async function removeUser(teamId, userId) { try { - await runTransaction(db, async (transaction) => { - //Remove all attempts from attempts table with UID == userID - const attemptQuery = query( - collection(db, "teams", teamId, "attempts"), - where("uid", "==", userId), - ); + //Remove all attempts from attempts table with UID == userID + const attemptQuery = query( + collection(db, "teams", teamId, "attempts"), + where("uid", "==", userId), + ); - const attemptSnapshot = await getDocs(attemptQuery); + const attemptSnapshot = await getDocs(attemptQuery); - for (const doc of attemptSnapshot.docs) { - await transaction.delete(doc.ref); - } + for (const doc of attemptSnapshot.docs) { + await deleteDoc(doc.ref); + } - //Remove all entries from best_attempts table with UID == userID - const bestAttemptQuery = query( - collection(db, "teams", teamId, "best_attempts"), - ); + //Remove all entries from best_attempts table with UID == userID + const bestAttemptQuery = query( + collection(db, "teams", teamId, "best_attempts"), + ); - const bestAttemptSnapshot = await getDocs(bestAttemptQuery); + const bestAttemptSnapshot = await getDocs(bestAttemptQuery); - for (const doc of bestAttemptSnapshot.docs) { - const docData = doc.data(); + for (const doc of bestAttemptSnapshot.docs) { + const docData = doc.data(); - if (docData[userId]) { - //Delete the field - await transaction.update(doc.ref, { - [userId]: deleteField(), - }); - } + if (docData[userId]) { + //Delete the field + await updateDoc(doc.ref, { + [userId]: deleteField(), + }); } + } - //Remove user from user table where UID == userID - const userRef = doc(db, "teams", teamId, "users", userId); + //Remove user from user table where UID == userID + const userRef = doc(db, "teams", teamId, "users", userId); - await transaction.delete(userRef); + await deleteDoc(userRef); - await removePfp(getPfpName(teamId, userId)); + await removePfp(getPfpName(teamId, userId)); - console.log(" Remove User Transaction has completed"); - }); + console.log(" Remove User has completed"); } catch (e) { - console.log("Remove User Transaction failed: ", e); + console.log("Remove User failed: ", e); throw e; // Rethrow the error to handle it at the caller's level if needed } } From 72c08a6a26a0d2ac8c235bac2ef45003e8c27b09 Mon Sep 17 00:00:00 2001 From: Frankreed Date: Sun, 21 Jul 2024 18:09:42 +0700 Subject: [PATCH 08/56] fixed useBlackList.js hook firestore error, and made blacklist check functional --- app/segments/(team)/chooseTeam.js | 2 +- dbOperations/hooks/useBlackList.js | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js index 4aeaa84c..e612b889 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -59,7 +59,7 @@ function ChooseTeam() { alignItems: "center", }} > - {blacklist ? ( + {blacklist[currentUserId] ? ( { const { currentTeamId } = useAuthContext(); const { data, error, isLoading } = useQuery({ - queryKey: ["blackList"], + queryKey: ["blacklist"], queryFn: async () => { console.log("fetching blacklist"); + const newBlacklist = {}; // Fetch all time records - const querySnapshot = await getDoc( - doc(db, "teams", currentTeamId, "blacklist"), + const querySnapshot = await getDocs( + collection(db, "teams", currentTeamId, "blacklist"), ); - const data = querySnapshot.data(); - if (data === undefined) { - return false; - } - return querySnapshot.data(); + querySnapshot.forEach((doc) => { + newBlacklist[doc.id] = doc.data(); + }); + return newBlacklist; }, enabled, }); From 6ea881f2541d1ce4313dbc0258a5e85a7e154db1 Mon Sep 17 00:00:00 2001 From: Frankreed Date: Sun, 21 Jul 2024 18:12:14 +0700 Subject: [PATCH 09/56] added refresh spinner for chooseTeam.js --- app/segments/(team)/chooseTeam.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js index e612b889..05adfbb2 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -2,13 +2,14 @@ import { useQueryClient } from "@tanstack/react-query"; import { router } from "expo-router"; import { signOut as signoutFireBase } from "firebase/auth"; import { doc, setDoc } from "firebase/firestore"; -import { Text, View } from "react-native"; +import { ScrollView, Text, View } from "react-native"; import { Button } from "react-native-paper"; import { SafeAreaView } from "react-native-safe-area-context"; import { themeColors } from "~/Constants"; import { getErrorString } from "~/Utility"; import ErrorComponent from "~/components/errorComponent"; import Loading from "~/components/loading"; +import RefreshInvalidate from "~/components/refreshInvalidate"; import { useAlertContext } from "~/context/Alert"; import { useAuthContext } from "~/context/Auth"; import { useBlackList } from "~/dbOperations/hooks/useBlackList"; @@ -28,6 +29,8 @@ function ChooseTeam() { isLoading: blacklistIsLoading, } = useBlackList(); + const invalidateKeys = [["blacklist"]]; + if (blacklistIsLoading) { return ; } @@ -49,15 +52,17 @@ function ChooseTeam() { return ( - } > {blacklist[currentUserId] ? ( - + ); } From 07142cdf1906c88bc00f32669beac12aa5e6ceb3 Mon Sep 17 00:00:00 2001 From: Frankreed Date: Sun, 21 Jul 2024 18:16:17 +0700 Subject: [PATCH 10/56] updated invalidateKeys and fixed some styling --- app/segments/(team)/chooseTeam.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js index abed90f6..47b51b59 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -53,7 +53,7 @@ function ChooseTeam() { return "neutral"; }, [blacklist, currentUserId, waitlist]); //blacklist, waitlist, invited, neutral - const invalidateKeys = [["blacklist"]]; + const invalidateKeys = [["blacklist", "waitlist"]]; if (blacklistIsLoading || waitlistIsLoading) { return ; @@ -145,7 +145,6 @@ function ChooseTeam() { ) : ( Date: Sun, 21 Jul 2024 18:30:45 +0700 Subject: [PATCH 11/56] updated faulty invalidateKeys lists --- app/(auth)/signup.js | 8 ++++---- app/content/team/index.js | 5 +++++ app/segments/(team)/chooseTeam.js | 2 +- app/segments/(team)/waitlist.js | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/(auth)/signup.js b/app/(auth)/signup.js index 417137f9..ad933bdd 100644 --- a/app/(auth)/signup.js +++ b/app/(auth)/signup.js @@ -1,5 +1,5 @@ import { Link } from "expo-router"; -import { createUserWithEmailAndPassword } from "firebase/auth"; +import { createUserWithEmailAndPassword, updateProfile } from "firebase/auth"; import { doc, setDoc } from "firebase/firestore"; import { useState } from "react"; import { @@ -45,9 +45,9 @@ export default function SignUp() { email, password, ); - // await updateProfile(userCredential.user, { - // displayName: name, - // }); + await updateProfile(userCredential.user, { + displayName: name, + }); await setDoc(doc(db, "users", userCredential.user.uid), { email: email, }); diff --git a/app/content/team/index.js b/app/content/team/index.js index 55a7b1e3..1f5d7a41 100644 --- a/app/content/team/index.js +++ b/app/content/team/index.js @@ -137,6 +137,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 47b51b59..b7ba1030 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -53,7 +53,7 @@ function ChooseTeam() { return "neutral"; }, [blacklist, currentUserId, waitlist]); //blacklist, waitlist, invited, neutral - const invalidateKeys = [["blacklist", "waitlist"]]; + const invalidateKeys = [["blacklist"], ["waitlist"]]; if (blacklistIsLoading || waitlistIsLoading) { return ; diff --git a/app/segments/(team)/waitlist.js b/app/segments/(team)/waitlist.js index c9e8128c..012ec848 100644 --- a/app/segments/(team)/waitlist.js +++ b/app/segments/(team)/waitlist.js @@ -29,7 +29,7 @@ function Waitlist() { return ; } - const invalidateKeys = [["waitlist", "userInfo"]]; + const invalidateKeys = [["waitlist"], ["userInfo"]]; return ( Date: Sun, 21 Jul 2024 18:38:46 +0700 Subject: [PATCH 12/56] kinda works lmao --- app/content/team/users/[user]/index.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/content/team/users/[user]/index.js b/app/content/team/users/[user]/index.js index e9322460..39e42e5b 100644 --- a/app/content/team/users/[user]/index.js +++ b/app/content/team/users/[user]/index.js @@ -319,8 +319,17 @@ function Index() { ]); navigation.goBack(); } catch (e) { - console.log("Error removing user:", e); - showDialog("Error", getErrorString(e)); + if (e.code === "storage/object-not-found") { + //success kinda weird rn + await invalidateMultipleKeys(queryClient, [ + ["userInfo"], + ["best_attempts"], + ]); + navigation.goBack(); + } else { + console.log("Error removing user:", e); + showDialog("Error", getErrorString(e)); + } } }, ]} From 8fb3f94b6efabf13a360c9050274f6d95b4565d0 Mon Sep 17 00:00:00 2001 From: Frankreed Date: Sun, 21 Jul 2024 21:12:28 +0700 Subject: [PATCH 13/56] updated the invalidateKeys again --- app/(auth)/signup.js | 10 ---------- app/segments/(team)/chooseTeam.js | 12 +++++++----- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/app/(auth)/signup.js b/app/(auth)/signup.js index ad933bdd..d3abc904 100644 --- a/app/(auth)/signup.js +++ b/app/(auth)/signup.js @@ -51,16 +51,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: [], - // }); setCurrentUserId(userCredential.user.uid); setCurrentUserInfo({ ...userCredential.user, displayName: name }); diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js index b7ba1030..ae202b80 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -53,7 +53,11 @@ function ChooseTeam() { return "neutral"; }, [blacklist, currentUserId, waitlist]); //blacklist, waitlist, invited, neutral - const invalidateKeys = [["blacklist"], ["waitlist"]]; + const invalidateKeys = [ + ["blacklist"], + ["waitlist"], + ["userInfo", { userId: currentUserId }], + ]; if (blacklistIsLoading || waitlistIsLoading) { return ; @@ -120,9 +124,7 @@ function ChooseTeam() { //temporary, should be replaced with multiple team functionality await addToTeam(currentTeamId, currentUserId, currentUserInfo); setCurrentUserId(currentUserId); - await invalidateMultipleKeys(queryClient, [ - ["userInfo", { userId: currentUserId }], - ]); + await invalidateMultipleKeys(queryClient, invalidateKeys); router.replace("/"); }} style={{ @@ -156,7 +158,7 @@ function ChooseTeam() { currentUserId, currentUserInfo, ); - await invalidateMultipleKeys(queryClient, [["waitlist"]]); + await invalidateMultipleKeys(queryClient, invalidateKeys); }} style={{ backgroundColor: themeColors.accent, From 91ab448a1ee186c6d614eb96fcf7e16f76c86b8a Mon Sep 17 00:00:00 2001 From: Frankreed Date: Sun, 21 Jul 2024 21:46:31 +0700 Subject: [PATCH 14/56] navigation off chooseTeam works. Tech debt +1 --- app/segments/(team)/chooseTeam.js | 4 ++++ dbOperations/hooks/useUserInfo.js | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js index ae202b80..5d1fe80b 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -15,6 +15,7 @@ import { useAuthContext } from "~/context/Auth"; import { addToTeam } from "~/dbOperations/addToTeam"; import { addToWaitlist } from "~/dbOperations/addToWaitlist"; import { useBlackList } from "~/dbOperations/hooks/useBlackList"; +import { useUserInfo } from "~/dbOperations/hooks/useUserInfo"; import { useWaitlist } from "~/dbOperations/hooks/useWaitlist"; import { invalidateMultipleKeys } from "~/dbOperations/invalidateMultipleKeys"; import { auth } from "~/firebaseConfig"; @@ -43,6 +44,9 @@ function ChooseTeam() { isLoading: waitlistIsLoading, } = useWaitlist(); + //basically to trigger the side effect that navigates off this page + useUserInfo({ userId: currentUserId }); + const state = useMemo(() => { if (blacklist && blacklist[currentUserId]) { return "blacklist"; diff --git a/dbOperations/hooks/useUserInfo.js b/dbOperations/hooks/useUserInfo.js index 6efd0d2d..9542913c 100644 --- a/dbOperations/hooks/useUserInfo.js +++ b/dbOperations/hooks/useUserInfo.js @@ -1,5 +1,5 @@ import { useQuery } from "@tanstack/react-query"; -import { router } from "expo-router"; +import { router, useSegments } from "expo-router"; import { collection, doc, @@ -17,6 +17,7 @@ export const useUserInfo = ({ role = null, enabled = true, } = {}) => { + const segments = useSegments(); const { currentTeamId, currentUserId } = useAuthContext(); const week_milliseconds = 604800000; const currentDate = new Date(); @@ -44,6 +45,11 @@ export const useUserInfo = ({ uniqueDrills: [], }; } + const inChooseTeam = segments.at(-1) === "chooseTeam"; + if (inChooseTeam) { + router.replace("content/assignments"); + } + const filteredAssignedData = data.assigned_data.filter((assignment) => { const timeDifference = currentDateTime - assignment.assignedTime; return timeDifference <= week_milliseconds; From baa4e908424c58597e66152fd39a549de76cb5ee Mon Sep 17 00:00:00 2001 From: Frankreed Date: Tue, 23 Jul 2024 14:18:54 +0700 Subject: [PATCH 15/56] half finished progress --- app/segments/(team)/invitelist.js | 91 ++++++++++++++++++++ app/segments/(team)/manageForeignRequests.js | 10 +-- dbOperations/hooks/useInviteList.js | 30 +++++++ 3 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 app/segments/(team)/invitelist.js create mode 100644 dbOperations/hooks/useInviteList.js diff --git a/app/segments/(team)/invitelist.js b/app/segments/(team)/invitelist.js new file mode 100644 index 00000000..0add7bc2 --- /dev/null +++ b/app/segments/(team)/invitelist.js @@ -0,0 +1,91 @@ +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 { useInvitelist } from "~/dbOperations/hooks/useInviteList"; +import { invalidateMultipleKeys } from "~/dbOperations/invalidateMultipleKeys"; +import { removeWaitlist } from "~/dbOperations/removeWaitlist"; + +function Invitelist() { + const { + data: invitelist, + error: inviteError, + isLoading: inviteIsLoading, + } = useInvitelist(); + + const { currentTeamId } = useAuthContext(); + const queryClient = useQueryClient(); + + if (inviteError) { + return ; + } + + if (inviteIsLoading) { + return ; + } + + const invalidateKeys = [["invitelist"], ["userInfo"]]; + + return ( + } + > + + {Object.keys(invitelist).map((userId) => { + console.log("invitelist", invitelist[userId]); + return ( + ( + + + + + )} + /> + ); + })} + + + ); +} + +export default Invitelist; diff --git a/app/segments/(team)/manageForeignRequests.js b/app/segments/(team)/manageForeignRequests.js index 4ec794dd..25a48b78 100644 --- a/app/segments/(team)/manageForeignRequests.js +++ b/app/segments/(team)/manageForeignRequests.js @@ -8,12 +8,12 @@ import Waitlist from "~/app/segments/(team)/waitlist"; import Header from "~/components/header"; function ManageForeignRequests() { - const [tabValue, setTabValue] = useState("invites"); + const [tabValue, setTabValue] = useState("invitelist"); const navigation = useNavigation(); const segmentedColor = (tab) => { switch (tab) { - case "invites": + case "invitelist": return "#008001"; case "waitlist": return "#FFE900"; @@ -26,7 +26,7 @@ function ManageForeignRequests() { const segmentedTextColor = (tab) => { switch (tab) { - case "invites": + case "invitelist": case "blacklist": return "white"; case "waitlist": @@ -38,7 +38,7 @@ function ManageForeignRequests() { const tabComponent = useMemo( () => ({ - invites: <>, + invites: , waitlist: , blacklist: , }), @@ -79,7 +79,7 @@ function ManageForeignRequests() { }} buttons={[ { - value: "invites", + value: "invitelist", label: "Invites", }, { diff --git a/dbOperations/hooks/useInviteList.js b/dbOperations/hooks/useInviteList.js new file mode 100644 index 00000000..e64da09d --- /dev/null +++ b/dbOperations/hooks/useInviteList.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 useInvitelist = ({ enabled = true } = {}) => { + const { currentTeamId } = useAuthContext(); + const { data, error, isLoading } = useQuery({ + queryKey: ["invitelist"], + queryFn: async () => { + console.log("fetching invitelist"); + const newWaitlist = {}; + // Fetch all time records + const querySnapshot = await getDocs( + collection(db, "teams", currentTeamId, "invitelist"), + ); + querySnapshot.forEach((doc) => { + newWaitlist[doc.id] = doc.data(); + }); + return newWaitlist; + }, + enabled, + }); + + return { + data, + error, + isLoading, + }; +}; From 3f52e48c4890bda9e0a16711d7463aa0a32871ae Mon Sep 17 00:00:00 2001 From: Frankreed Date: Sat, 3 Aug 2024 14:42:00 +0700 Subject: [PATCH 16/56] invite works --- .gitignore | 1 + app/segments/(team)/chooseTeam.js | 30 +++- app/segments/(team)/invitelist.js | 150 ++++++++++++------- app/segments/(team)/manageForeignRequests.js | 3 +- dbOperations/addToInvitelist.js | 14 ++ dbOperations/hooks/useInviteList.js | 42 ++++-- dbOperations/removeInvitelist.js | 13 ++ package.json | 2 +- 8 files changed, 181 insertions(+), 74 deletions(-) create mode 100644 dbOperations/addToInvitelist.js create mode 100644 dbOperations/removeInvitelist.js diff --git a/.gitignore b/.gitignore index dfc823b5..17160714 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ ios android webstorm.config.js firebaseApiKey.js +/.git-branches.toml diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js index 5d1fe80b..82ea1487 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -15,6 +15,7 @@ import { useAuthContext } from "~/context/Auth"; import { addToTeam } from "~/dbOperations/addToTeam"; import { addToWaitlist } from "~/dbOperations/addToWaitlist"; import { useBlackList } from "~/dbOperations/hooks/useBlackList"; +import { useInvitelist } from "~/dbOperations/hooks/useInviteList"; import { useUserInfo } from "~/dbOperations/hooks/useUserInfo"; import { useWaitlist } from "~/dbOperations/hooks/useWaitlist"; import { invalidateMultipleKeys } from "~/dbOperations/invalidateMultipleKeys"; @@ -44,6 +45,12 @@ function ChooseTeam() { isLoading: waitlistIsLoading, } = useWaitlist(); + const { + data: invitelist, + error: invitelistError, + isLoading: invitelistIsLoading, + } = useInvitelist({ email: currentUserInfo.email }); + //basically to trigger the side effect that navigates off this page useUserInfo({ userId: currentUserId }); @@ -54,21 +61,25 @@ function ChooseTeam() { if (waitlist && waitlist[currentUserId]) { return "waitlist"; } + if (invitelist && invitelist["id"] !== undefined) { + return "invitelist"; + } return "neutral"; - }, [blacklist, currentUserId, waitlist]); //blacklist, waitlist, invited, neutral + }, [blacklist, currentUserId, invitelist, waitlist]); //blacklist, waitlist, invitelist, neutral const invalidateKeys = [ + ["invitelist"], ["blacklist"], ["waitlist"], ["userInfo", { userId: currentUserId }], ]; - if (blacklistIsLoading || waitlistIsLoading) { + if (blacklistIsLoading || waitlistIsLoading || invitelistIsLoading) { return ; } - if (blacklistError || waitlistError) { - return ; + if (blacklistError || waitlistError || invitelistError) { + return ; } async function handleSignOut() { @@ -116,13 +127,22 @@ function ChooseTeam() { > Your request to join the team has been received - ) : state === "invited" ? ( + ) : state === "invitelist" ? ( + + You have been invited to the team + - - - )} - /> - ); - })} - - + + + )} + /> + ); + })} + + + + { + setCurrentEmailInput(text); + setCurrentEmailValid(emailRegex.test(text)); + }} + autoCapitalize={"none"} + autoComplete={"email"} + autoCorrect={false} + inputMode={"email"} + keyboardType={"email-address"} + placeholder={"Enter email to invite"} + style={{ + flexGrow: 1, + }} + /> + + + ); } diff --git a/app/segments/(team)/manageForeignRequests.js b/app/segments/(team)/manageForeignRequests.js index 25a48b78..0963d661 100644 --- a/app/segments/(team)/manageForeignRequests.js +++ b/app/segments/(team)/manageForeignRequests.js @@ -4,6 +4,7 @@ import { Appbar, SegmentedButtons } from "react-native-paper"; import { SafeAreaView } from "react-native-safe-area-context"; import { themeColors } from "~/Constants"; import Blacklist from "~/app/segments/(team)/blacklist"; +import Invitelist from "~/app/segments/(team)/invitelist"; import Waitlist from "~/app/segments/(team)/waitlist"; import Header from "~/components/header"; @@ -38,7 +39,7 @@ function ManageForeignRequests() { const tabComponent = useMemo( () => ({ - invites: , + invitelist: , waitlist: , blacklist: , }), diff --git a/dbOperations/addToInvitelist.js b/dbOperations/addToInvitelist.js new file mode 100644 index 00000000..f4cf0c67 --- /dev/null +++ b/dbOperations/addToInvitelist.js @@ -0,0 +1,14 @@ +import { collection, doc, setDoc } from "firebase/firestore"; +import { db } from "~/firebaseConfig"; + +export async function addToInvitelist(currentTeamId, email) { + try { + const newRequestRef = doc( + collection(db, "teams", currentTeamId, "invitelist"), + ); + await setDoc(newRequestRef, { email }); + } 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/useInviteList.js b/dbOperations/hooks/useInviteList.js index e64da09d..6bf04e6f 100644 --- a/dbOperations/hooks/useInviteList.js +++ b/dbOperations/hooks/useInviteList.js @@ -1,23 +1,41 @@ import { useQuery } from "@tanstack/react-query"; -import { collection, getDocs } from "firebase/firestore"; +import { collection, getDocs, query, where } from "firebase/firestore"; import { useAuthContext } from "~/context/Auth"; import { db } from "~/firebaseConfig"; -export const useInvitelist = ({ enabled = true } = {}) => { +export const useInvitelist = ({ enabled = true, email = null } = {}) => { const { currentTeamId } = useAuthContext(); const { data, error, isLoading } = useQuery({ queryKey: ["invitelist"], queryFn: async () => { - console.log("fetching invitelist"); - const newWaitlist = {}; - // Fetch all time records - const querySnapshot = await getDocs( - collection(db, "teams", currentTeamId, "invitelist"), - ); - querySnapshot.forEach((doc) => { - newWaitlist[doc.id] = doc.data(); - }); - return newWaitlist; + console.log("fetching invitelist", { enabled, email }); + if (email) { + const inviteQuery = query( + collection(db, "teams", currentTeamId, "invitelist"), + where("email", "==", email), + ); + + const invite = {}; + + const attemptSnapshot = await getDocs(inviteQuery); + + attemptSnapshot.forEach((doc) => { + invite["id"] = doc.id; + invite["email"] = doc.data()["email"]; + }); + + return invite; + } else { + const newWaitlist = {}; + // Fetch all time records + const querySnapshot = await getDocs( + collection(db, "teams", currentTeamId, "invitelist"), + ); + querySnapshot.forEach((doc) => { + newWaitlist[doc.id] = doc.data(); + }); + return newWaitlist; + } }, enabled, }); diff --git a/dbOperations/removeInvitelist.js b/dbOperations/removeInvitelist.js new file mode 100644 index 00000000..462a378b --- /dev/null +++ b/dbOperations/removeInvitelist.js @@ -0,0 +1,13 @@ +import { deleteDoc, doc } from "firebase/firestore"; +import { db } from "~/firebaseConfig"; + +async function removeInvitelist(teamId, inviteId) { + try { + await deleteDoc(doc(db, "teams", teamId, "invitelist", inviteId)); + } catch (e) { + console.log("Remove Waitlist failed: ", e); + throw e; // Rethrow the error to handle it at the caller's level if needed + } +} + +module.exports = { removeInvitelist }; diff --git a/package.json b/package.json index a12d3d8f..328ac8ee 100644 --- a/package.json +++ b/package.json @@ -44,8 +44,8 @@ "expo-status-bar": "~1.12.1", "expo-system-ui": "~3.0.4", "firebase": "^10.8.0", - "react": "18.2.0", "moment-timezone": "^0.5.45", + "react": "18.2.0", "react-dom": "18.2.0", "react-native": "0.74.1", "react-native-dropdown-picker": "^5.4.6", From 180b0968120964dbcc91f4667802456cdfa7d133 Mon Sep 17 00:00:00 2001 From: Frankreed Date: Sat, 3 Aug 2024 14:45:00 +0700 Subject: [PATCH 17/56] added waitlistError to ErrorComponent --- app/segments/(team)/chooseTeam.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js index ae202b80..71336f94 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -64,7 +64,7 @@ function ChooseTeam() { } if (blacklistError || waitlistError) { - return ; + return ; } async function handleSignOut() { From 27434074cc1763dda7141504df0c86deacb0cf3f Mon Sep 17 00:00:00 2001 From: Frankreed Date: Sat, 3 Aug 2024 14:49:02 +0700 Subject: [PATCH 18/56] pretty --- app/segments/(team)/chooseTeam.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js index 1ad4aeae..e1410ab6 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -79,7 +79,11 @@ function ChooseTeam() { } if (blacklistError || waitlistError || invitelistError) { - return ; + return ( + + ); } async function handleSignOut() { From 46f85e9266fe29d02b20923debeebf442573fe88 Mon Sep 17 00:00:00 2001 From: Frankreed Date: Sat, 3 Aug 2024 15:16:19 +0700 Subject: [PATCH 19/56] text input moves above keyboard now --- app/segments/(team)/invitelist.js | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/app/segments/(team)/invitelist.js b/app/segments/(team)/invitelist.js index 9605fe8f..48a4125e 100644 --- a/app/segments/(team)/invitelist.js +++ b/app/segments/(team)/invitelist.js @@ -1,6 +1,12 @@ import { useQueryClient } from "@tanstack/react-query"; import { useState } from "react"; -import { ScrollView, TextInput, View } from "react-native"; +import { + KeyboardAvoidingView, + Platform, + ScrollView, + TextInput, + View, +} from "react-native"; import { Button, List } from "react-native-paper"; import { themeColors } from "~/Constants"; import { getErrorString } from "~/Utility"; @@ -31,6 +37,11 @@ export function Invitelist() { const [currentEmailValid, setCurrentEmailValid] = useState(false); const onInvite = async () => { + const invitedEmail = Object.values(invitelist).map( + (invite) => invite["email"], + ); + if (invitedEmail.includes(currentEmailInput)) { + } await addToInvitelist(currentTeamId, currentEmailInput); setCurrentEmailInput(""); await invalidateMultipleKeys(queryClient, invalidateKeys); @@ -47,10 +58,11 @@ export function Invitelist() { const emailRegex = /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w\w+)+$/; return ( - } @@ -65,6 +77,7 @@ export function Invitelist() { return ( ( @@ -124,7 +135,7 @@ export function Invitelist() { Invite - + ); } From 35a5a26e5e1d951c62914e6bf3825e0b1ba41e81 Mon Sep 17 00:00:00 2001 From: Frank Nguyen <41023671+FrankreedX@users.noreply.github.com> Date: Sat, 3 Aug 2024 22:57:45 -0700 Subject: [PATCH 20/56] minor comment change Co-authored-by: Jake Gehrke <91503842+Gehrkej@users.noreply.github.com> --- dbOperations/hooks/useBlackList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbOperations/hooks/useBlackList.js b/dbOperations/hooks/useBlackList.js index 23b551d6..51c24e64 100644 --- a/dbOperations/hooks/useBlackList.js +++ b/dbOperations/hooks/useBlackList.js @@ -11,7 +11,7 @@ export const useBlackList = ({ enabled = true } = {}) => { queryFn: async () => { console.log("fetching blacklist"); const newBlacklist = {}; - // Fetch all time records + // Fetch blacklist const querySnapshot = await getDocs( collection(db, "teams", currentTeamId, "blacklist"), ); From 1ae93efc8a0dc9cac1cb5684341b69364397d954 Mon Sep 17 00:00:00 2001 From: Frank Nguyen <41023671+FrankreedX@users.noreply.github.com> Date: Sat, 3 Aug 2024 23:01:20 -0700 Subject: [PATCH 21/56] changed console log wording in removeBlacklist Co-authored-by: Jake Gehrke <91503842+Gehrkej@users.noreply.github.com> --- dbOperations/removeBlacklist.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbOperations/removeBlacklist.js b/dbOperations/removeBlacklist.js index 2d5020f1..1a69eea7 100644 --- a/dbOperations/removeBlacklist.js +++ b/dbOperations/removeBlacklist.js @@ -5,7 +5,7 @@ async function removeBlacklist(teamId, userId) { try { await deleteDoc(doc(db, "teams", teamId, "blacklist", userId)); } catch (e) { - console.log("Remove Blacklist Transaction failed: ", e); + console.log("Remove User from Blacklist failed: ", e); throw e; // Rethrow the error to handle it at the caller's level if needed } } From f869cfb657d6216e99269cf78c60b3a53ded6349 Mon Sep 17 00:00:00 2001 From: Frankreed Date: Sun, 4 Aug 2024 13:05:09 +0700 Subject: [PATCH 22/56] removed copied over comment --- app/segments/(team)/manageForeignRequests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/segments/(team)/manageForeignRequests.js b/app/segments/(team)/manageForeignRequests.js index 2e3e69af..89da5618 100644 --- a/app/segments/(team)/manageForeignRequests.js +++ b/app/segments/(team)/manageForeignRequests.js @@ -42,7 +42,7 @@ function ManageForeignRequests() { blacklist: , }), [], - ); // Recreate pages only if drillId changes + ); return ( Date: Sat, 3 Aug 2024 23:06:25 -0700 Subject: [PATCH 23/56] updated tiny comment Co-authored-by: Jake Gehrke <91503842+Gehrkej@users.noreply.github.com> --- dbOperations/hooks/useWaitlist.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbOperations/hooks/useWaitlist.js b/dbOperations/hooks/useWaitlist.js index 653a5f03..add4fde6 100644 --- a/dbOperations/hooks/useWaitlist.js +++ b/dbOperations/hooks/useWaitlist.js @@ -10,7 +10,7 @@ export const useWaitlist = ({ enabled = true } = {}) => { queryFn: async () => { console.log("fetching waitlist"); const newWaitlist = {}; - // Fetch all time records + // Fetch all Entries on the Waitlist const querySnapshot = await getDocs( collection(db, "teams", currentTeamId, "waitlist"), ); From b5ed7d8fbaa58607d85982e743899ab465bc3149 Mon Sep 17 00:00:00 2001 From: Frank Nguyen <41023671+FrankreedX@users.noreply.github.com> Date: Sat, 3 Aug 2024 23:07:02 -0700 Subject: [PATCH 24/56] removed redundant log Co-authored-by: Jake Gehrke <91503842+Gehrkej@users.noreply.github.com> --- dbOperations/addToWaitlist.js | 1 - 1 file changed, 1 deletion(-) diff --git a/dbOperations/addToWaitlist.js b/dbOperations/addToWaitlist.js index 619e9457..e7a2593c 100644 --- a/dbOperations/addToWaitlist.js +++ b/dbOperations/addToWaitlist.js @@ -15,7 +15,6 @@ export async function addToWaitlist( currentUserId, ); const currentTime = Date.now(); - console.log("data", currentUserInfo); await setDoc(newRequestRef, { displayName: currentUserInfo["displayName"], email: currentUserInfo["email"], From cfd9e15d593d706d333b2d34d7bb4e2c59f178bd Mon Sep 17 00:00:00 2001 From: Jake Gehrke Date: Sun, 4 Aug 2024 00:53:08 -0700 Subject: [PATCH 25/56] fix - added email to blacklist record --- app/content/team/users/[user]/index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/content/team/users/[user]/index.js b/app/content/team/users/[user]/index.js index e9322460..f1488bcc 100644 --- a/app/content/team/users/[user]/index.js +++ b/app/content/team/users/[user]/index.js @@ -26,13 +26,14 @@ import { removeUser } from "~/dbOperations/removeUser"; import { db } from "~/firebaseConfig"; //A function to add a user to the blacklist table with a timestamp -async function blacklistUser(teamId, userId, userInfo) { +async function blacklistUser(teamId, userId, userInfo, userEmail) { //Create new document with userId as the id and a time field try { await setDoc(doc(db, "teams", teamId, "blacklist", userId), { time: Date.now(), name: userInfo["name"], + email: userEmail, }); //remove users data await removeUser(teamId, userId); @@ -336,7 +337,7 @@ function Index() { hideBanDialog, async () => { try { - await blacklistUser(currentTeamId, userId, userInfo); + await blacklistUser(currentTeamId, userId, userInfo, userEmail); await queryClient.removeQueries(["userInfo", userId]); await invalidateMultipleKeys(queryClient, [ ["userInfo"], From 6bff91c4436c727dc4ae01c6f8b376ec71ecc357 Mon Sep 17 00:00:00 2001 From: Jake Gehrke Date: Sun, 4 Aug 2024 00:55:19 -0700 Subject: [PATCH 26/56] fix - added assertion if pfp exists when removing a user --- dbOperations/removeUser.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/dbOperations/removeUser.js b/dbOperations/removeUser.js index d53d8e38..f167b072 100644 --- a/dbOperations/removeUser.js +++ b/dbOperations/removeUser.js @@ -7,9 +7,9 @@ import { runTransaction, where, } from "firebase/firestore"; -import removePfp from "~/dbOperations/removePfp"; -import { db } from "~/firebaseConfig"; import { getPfpName } from "~/Utility"; +import { db } from "~/firebaseConfig"; +import removePfp from "./removePfp"; async function removeUser(teamId, userId) { try { @@ -47,9 +47,14 @@ async function removeUser(teamId, userId) { //Remove user from user table where UID == userID const userRef = doc(db, "teams", teamId, "users", userId); - await transaction.delete(userRef); + const userSnapshot = await transaction.get(userRef); - await removePfp(getPfpName(teamId, userId)); + //remove pfp if there is one + if (userSnapshot.data().pfp !== "") { + await removePfp(getPfpName(teamId, userId)); + } + + await transaction.delete(userRef); console.log(" Remove User Transaction has completed"); }); From 65cff29ea9ea50caa9693e976d3fd85c0ef8e1bf Mon Sep 17 00:00:00 2001 From: Frankreed Date: Tue, 6 Aug 2024 18:09:41 +0700 Subject: [PATCH 27/56] added loading spinner to all buttons --- app/segments/(team)/blacklist.js | 14 +++++- app/segments/(team)/chooseTeam.js | 79 +++++++++++++++++++------------ app/segments/(team)/invitelist.js | 28 +++++++++-- app/segments/(team)/waitlist.js | 75 ++++++++++++++++++++--------- 4 files changed, 140 insertions(+), 56 deletions(-) diff --git a/app/segments/(team)/blacklist.js b/app/segments/(team)/blacklist.js index 500c864f..804185e6 100644 --- a/app/segments/(team)/blacklist.js +++ b/app/segments/(team)/blacklist.js @@ -1,6 +1,7 @@ import { useQueryClient } from "@tanstack/react-query"; +import { useState } from "react"; import { ScrollView, View } from "react-native"; -import { Button, List } from "react-native-paper"; +import { ActivityIndicator, Button, List } from "react-native-paper"; import { themeColors } from "~/Constants"; import ErrorComponent from "~/components/errorComponent"; import Loading from "~/components/loading"; @@ -21,6 +22,8 @@ function Blacklist() { const queryClient = useQueryClient(); // also called here for updating name + const [unbanLoading, setUnbanLoading] = useState({}); + const invalidateKeys = [["blacklist"]]; if (blacklistIsLoading) return ; @@ -51,12 +54,19 @@ function Blacklist() { > )} diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js index e1410ab6..e0d49cab 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -1,9 +1,9 @@ import { useQueryClient } from "@tanstack/react-query"; import { router } from "expo-router"; import { signOut as signoutFireBase } from "firebase/auth"; -import { useMemo } from "react"; +import { useMemo, useState } from "react"; import { ScrollView, Text, View } from "react-native"; -import { Button } from "react-native-paper"; +import { ActivityIndicator, Button } from "react-native-paper"; import { SafeAreaView } from "react-native-safe-area-context"; import { themeColors } from "~/Constants"; import { getErrorString } from "~/Utility"; @@ -31,6 +31,9 @@ function ChooseTeam() { } = useAuthContext(); const queryClient = useQueryClient(); + const [buttonLoading, setButtonLoading] = useState(false); + const [signoutLoading, setSignoutLoading] = useState(false); + const { showDialog } = useAlertContext(); const { @@ -87,6 +90,7 @@ function ChooseTeam() { } async function handleSignOut() { + setSignoutLoading(true); try { await signoutFireBase(auth); signOut(); @@ -94,6 +98,7 @@ function ChooseTeam() { console.log(e); showDialog("Error", getErrorString(e)); } + setSignoutLoading(false); } return ( @@ -149,10 +154,12 @@ function ChooseTeam() { ) : ( @@ -181,12 +192,14 @@ function ChooseTeam() { > )} @@ -220,15 +237,19 @@ function ChooseTeam() { marginTop: 20, }} > - - Sign Out - + {signoutLoading ? ( + + ) : ( + + Sign Out + + )} diff --git a/app/segments/(team)/invitelist.js b/app/segments/(team)/invitelist.js index 48a4125e..c4f6d736 100644 --- a/app/segments/(team)/invitelist.js +++ b/app/segments/(team)/invitelist.js @@ -7,7 +7,7 @@ import { TextInput, View, } from "react-native"; -import { Button, List } from "react-native-paper"; +import { ActivityIndicator, Button, List } from "react-native-paper"; import { themeColors } from "~/Constants"; import { getErrorString } from "~/Utility"; import ErrorComponent from "~/components/errorComponent"; @@ -36,7 +36,11 @@ export function Invitelist() { const [currentEmailInput, setCurrentEmailInput] = useState(""); const [currentEmailValid, setCurrentEmailValid] = useState(false); + const [removeLoading, setRemoveLoading] = useState({}); + const [inviteLoading, setInviteLoading] = useState(false); + const onInvite = async () => { + setInviteLoading(true); const invitedEmail = Object.values(invitelist).map( (invite) => invite["email"], ); @@ -45,6 +49,7 @@ export function Invitelist() { await addToInvitelist(currentTeamId, currentEmailInput); setCurrentEmailInput(""); await invalidateMultipleKeys(queryClient, invalidateKeys); + setInviteLoading(false); }; if (inviteError) { @@ -88,15 +93,28 @@ export function Invitelist() { > )} @@ -132,7 +150,11 @@ export function Invitelist() { onPress={onInvite} textColor={themeColors.accent} > - Invite + {inviteLoading ? ( + + ) : ( + "Invite" + )} diff --git a/app/segments/(team)/waitlist.js b/app/segments/(team)/waitlist.js index 012ec848..4b7fa43f 100644 --- a/app/segments/(team)/waitlist.js +++ b/app/segments/(team)/waitlist.js @@ -1,6 +1,8 @@ import { useQueryClient } from "@tanstack/react-query"; +import { useState } from "react"; import { ScrollView, View } from "react-native"; -import { Button, List } from "react-native-paper"; +import { ActivityIndicator, Button, List } from "react-native-paper"; +import { themeColors } from "~/Constants"; import { getErrorString } from "~/Utility"; import ErrorComponent from "~/components/errorComponent"; import Loading from "~/components/loading"; @@ -21,6 +23,9 @@ function Waitlist() { const { currentTeamId } = useAuthContext(); const queryClient = useQueryClient(); + //this is a pretty blunt implementation... I'm using the same variable here because each entry will disappear after either buttons are pressed + const [loading, setLoading] = useState({}); + if (waitlistError) { return ; } @@ -50,30 +55,56 @@ function Waitlist() { right={() => ( - - + {loading[userId] ? ( + + ) : ( + + + + + )} )} /> From 3cf56c3d510048d9b5e921676329c583861264cd Mon Sep 17 00:00:00 2001 From: Frankreed Date: Tue, 6 Aug 2024 18:24:39 +0700 Subject: [PATCH 28/56] can't invite already invited email --- app/segments/(team)/invitelist.js | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/app/segments/(team)/invitelist.js b/app/segments/(team)/invitelist.js index 48a4125e..a7da255d 100644 --- a/app/segments/(team)/invitelist.js +++ b/app/segments/(team)/invitelist.js @@ -1,9 +1,10 @@ import { useQueryClient } from "@tanstack/react-query"; -import { useState } from "react"; +import { useMemo, useState } from "react"; import { KeyboardAvoidingView, Platform, ScrollView, + Text, TextInput, View, } from "react-native"; @@ -30,17 +31,22 @@ export function Invitelist() { const { currentTeamId } = useAuthContext(); + const invitedEmail = useMemo(() => { + console.log("invitelist", invitelist); + return Object.values(invitelist).map((invite) => invite["email"]); + }, [invitelist]); + const invalidateKeys = [["invitelist"]]; // const queryClient = useQueryClient(); const [currentEmailInput, setCurrentEmailInput] = useState(""); const [currentEmailValid, setCurrentEmailValid] = useState(false); + const [statusText, setStatusText] = useState(""); const onInvite = async () => { - const invitedEmail = Object.values(invitelist).map( - (invite) => invite["email"], - ); if (invitedEmail.includes(currentEmailInput)) { + setStatusText("Email already invited"); + return; } await addToInvitelist(currentTeamId, currentEmailInput); setCurrentEmailInput(""); @@ -105,6 +111,7 @@ export function Invitelist() { })} + {statusText} { setCurrentEmailInput(text); - setCurrentEmailValid(emailRegex.test(text)); + const included = invitedEmail.includes(text); + if (included) setStatusText("Email already invited"); + else setStatusText(""); + + setCurrentEmailValid(!included && emailRegex.test(text)); }} autoCapitalize={"none"} autoComplete={"email"} From fe94315a0ef49a329822e1352d7df811c7e18c6e Mon Sep 17 00:00:00 2001 From: Frankreed Date: Tue, 6 Aug 2024 18:27:30 +0700 Subject: [PATCH 29/56] accepting invite will remove the invite --- app/segments/(team)/chooseTeam.js | 2 ++ dbOperations/removeInvitelist.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js index e1410ab6..f25c783c 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -19,6 +19,7 @@ import { useInvitelist } from "~/dbOperations/hooks/useInviteList"; import { useUserInfo } from "~/dbOperations/hooks/useUserInfo"; import { useWaitlist } from "~/dbOperations/hooks/useWaitlist"; import { invalidateMultipleKeys } from "~/dbOperations/invalidateMultipleKeys"; +import { removeInvitelist } from "~/dbOperations/removeInvitelist"; import { auth } from "~/firebaseConfig"; function ChooseTeam() { @@ -151,6 +152,7 @@ function ChooseTeam() { onPress={async () => { //temporary, should be replaced with multiple team functionality await addToTeam(currentTeamId, currentUserId, currentUserInfo); + await removeInvitelist(currentTeamId, invitelist["id"]); setCurrentUserId(currentUserId); await invalidateMultipleKeys(queryClient, invalidateKeys); router.replace("/"); diff --git a/dbOperations/removeInvitelist.js b/dbOperations/removeInvitelist.js index 462a378b..4970863b 100644 --- a/dbOperations/removeInvitelist.js +++ b/dbOperations/removeInvitelist.js @@ -5,7 +5,7 @@ async function removeInvitelist(teamId, inviteId) { try { await deleteDoc(doc(db, "teams", teamId, "invitelist", inviteId)); } catch (e) { - console.log("Remove Waitlist failed: ", e); + console.log("Remove Invite failed: ", e); throw e; // Rethrow the error to handle it at the caller's level if needed } } From a5b58e8324fb83ca2ea1e13c884259dfe07a9d2f Mon Sep 17 00:00:00 2001 From: Frankreed Date: Tue, 6 Aug 2024 20:32:04 +0700 Subject: [PATCH 30/56] workin on remove user --- app/(auth)/signin.js | 7 +++++-- app/(auth)/signup.js | 8 ++++++-- app/content/team/users/[user]/index.js | 20 ++++++++++++++++++-- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/app/(auth)/signin.js b/app/(auth)/signin.js index 58383fdf..e197d608 100644 --- a/app/(auth)/signin.js +++ b/app/(auth)/signin.js @@ -33,6 +33,7 @@ export default function SignIn() { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [forgotLoading, setForgotLoading] = useState(false); + const [loginLoading, setLoginLoading] = useState(false); const { setCurrentUserId } = useAuthContext(); const { height } = useWindowDimensions(); @@ -62,6 +63,7 @@ export default function SignIn() { }, [timeIntervalPassword]); async function handleSignIn() { + setLoginLoading(true); if (process.env.EXPO_PUBLIC_TEST_UID) { // Only allow login as test user while using `yarn test` to reduce errors setCurrentUserId(process.env.EXPO_PUBLIC_TEST_UID); @@ -74,6 +76,7 @@ export default function SignIn() { showDialog("Error", getErrorString(e)); } } + setLoginLoading(false); } async function handleForgotPassword() { @@ -205,7 +208,7 @@ export default function SignIn() { buttonColor={themeColors.accent} labelStyle={styles.buttonText} > - Login + {loginLoading ? : "Login"} - Sign Up + Sign up diff --git a/app/(auth)/signup.js b/app/(auth)/signup.js index e2097a32..9ed618aa 100644 --- a/app/(auth)/signup.js +++ b/app/(auth)/signup.js @@ -13,7 +13,7 @@ import { useWindowDimensions, } from "react-native"; import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view"; -import { Button } from "react-native-paper"; +import { ActivityIndicator, Button } from "react-native-paper"; import { themeColors } from "~/Constants"; import { getErrorString } from "~/Utility"; import ProfilePicture from "~/components/ProfilePicture"; @@ -32,11 +32,14 @@ export default function SignUp() { const [password, setPassword] = useState(""); const [passwordCheck, setPasswordCheck] = useState(""); + const [signUpLoading, setSignUpLoading] = useState(false); + const { showDialog } = useAlertContext(); const { height } = useWindowDimensions(); async function handleSubmit() { + setSignUpLoading(true); try { if (password !== passwordCheck) { throw "Passwords don't match"; @@ -64,6 +67,7 @@ export default function SignUp() { console.log(e); showDialog("Error", getErrorString(e)); } + setSignUpLoading(false); } const styles = StyleSheet.create({ @@ -174,7 +178,7 @@ export default function SignUp() { buttonColor={themeColors.accent} labelStyle={styles.buttonText} > - Submit + {signUpLoading ? : "Submit"} - {signUpLoading ? : "Submit"} + Submit )} diff --git a/app/content/team/users/[user]/index.js b/app/content/team/users/[user]/index.js index 7ea48e00..de9aaf79 100644 --- a/app/content/team/users/[user]/index.js +++ b/app/content/team/users/[user]/index.js @@ -9,6 +9,7 @@ import { Divider, Menu, SegmentedButtons, + Text, } from "react-native-paper"; import { SafeAreaView } from "react-native-safe-area-context"; import { themeColors } from "~/Constants"; @@ -316,8 +317,20 @@ function Index() { onHide={hideRemoveDialog} buttons={[ "Cancel", - removeUserLoading ? ( - + !removeUserLoading ? ( + + Remove User + + ) : ( "Remove User" ), diff --git a/app/segments/(team)/blacklist.js b/app/segments/(team)/blacklist.js index 804185e6..9f635ee1 100644 --- a/app/segments/(team)/blacklist.js +++ b/app/segments/(team)/blacklist.js @@ -1,7 +1,7 @@ import { useQueryClient } from "@tanstack/react-query"; import { useState } from "react"; import { ScrollView, View } from "react-native"; -import { ActivityIndicator, Button, List } from "react-native-paper"; +import { Button, List } from "react-native-paper"; import { themeColors } from "~/Constants"; import ErrorComponent from "~/components/errorComponent"; import Loading from "~/components/loading"; @@ -60,13 +60,9 @@ function Blacklist() { setUnbanLoading({ ...unbanLoading, [userId]: false }); }} textColor={themeColors.accent} - height={38} //so the button doesn't change size because of the spinner + loading={unbanLoading[userId]} > - {unbanLoading[userId] ? ( - - ) : ( - "Unban" - )} + Unban )} diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js index 85bb86bc..13365657 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -3,7 +3,7 @@ import { router } from "expo-router"; import { signOut as signoutFireBase } from "firebase/auth"; import { useMemo, useState } from "react"; import { ScrollView, Text, View } from "react-native"; -import { ActivityIndicator, Button } from "react-native-paper"; +import { Button } from "react-native-paper"; import { SafeAreaView } from "react-native-safe-area-context"; import { themeColors } from "~/Constants"; import { getErrorString } from "~/Utility"; @@ -169,20 +169,17 @@ function ChooseTeam() { borderRadius: 12, marginTop: 20, }} + loading={buttonLoading} > - {buttonLoading ? ( - - ) : ( - - Join Team - - )} + + Join Team + ) : ( @@ -208,20 +205,17 @@ function ChooseTeam() { borderRadius: 12, marginTop: 20, }} + loading={buttonLoading} > - {buttonLoading ? ( - - ) : ( - - Request to Join Team - - )} + + Request to Join Team + )} @@ -238,20 +232,17 @@ function ChooseTeam() { borderRadius: 12, marginTop: 20, }} + loading={signoutLoading} > - {signoutLoading ? ( - - ) : ( - - Sign Out - - )} + + Sign Out + diff --git a/app/segments/(team)/invitelist.js b/app/segments/(team)/invitelist.js index 02e17115..19360b35 100644 --- a/app/segments/(team)/invitelist.js +++ b/app/segments/(team)/invitelist.js @@ -8,7 +8,7 @@ import { TextInput, View, } from "react-native"; -import { ActivityIndicator, Button, List } from "react-native-paper"; +import { Button, List } from "react-native-paper"; import { themeColors } from "~/Constants"; import { getErrorString } from "~/Utility"; import ErrorComponent from "~/components/errorComponent"; @@ -115,12 +115,9 @@ export function Invitelist() { }} height={38} //so the button doesn't change size because of the spinner textColor={themeColors.accent} + loading={removeLoading[inviteId]} > - {removeLoading[inviteId] ? ( - - ) : ( - "Remove" - )} + Remove )} @@ -160,12 +157,9 @@ export function Invitelist() { disabled={!currentEmailValid} onPress={onInvite} textColor={themeColors.accent} + loading={inviteLoading} > - {inviteLoading ? ( - - ) : ( - "Invite" - )} + Invite diff --git a/app/segments/drill/[id]/assignment/index.js b/app/segments/drill/[id]/assignment/index.js index 5ff8da71..24fdcca4 100644 --- a/app/segments/drill/[id]/assignment/index.js +++ b/app/segments/drill/[id]/assignment/index.js @@ -5,14 +5,7 @@ import { doc, runTransaction } from "firebase/firestore"; import { useCallback, useMemo, useState } from "react"; import { StyleSheet, TouchableOpacity, View } from "react-native"; import { ScrollView } from "react-native-gesture-handler"; -import { - ActivityIndicator, - Appbar, - Button, - List, - Text, - TouchableRipple, -} from "react-native-paper"; +import { Appbar, Button, List, Text } from "react-native-paper"; import { SafeAreaView } from "react-native-safe-area-context"; import Icon from "react-native-vector-icons/MaterialCommunityIcons"; import { once } from "underscore"; @@ -237,31 +230,24 @@ export default function Index() { /> )} - - {loading ? ( - - ) : ( - - Assign - - )} - + Assign + ); } diff --git a/components/dialog.js b/components/dialog.js index 463b5ee4..415ae42a 100644 --- a/components/dialog.js +++ b/components/dialog.js @@ -34,7 +34,7 @@ export default function DialogComponent({ ); }); From 71823f0eecb8c011ea13bdeeff8387f1cf8304a4 Mon Sep 17 00:00:00 2001 From: Frankreed Date: Wed, 7 Aug 2024 13:53:06 +0700 Subject: [PATCH 38/56] fixed "invalid-argument" --- app/content/team/users/[user]/index.js | 2 ++ dbOperations/removeUser.js | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/content/team/users/[user]/index.js b/app/content/team/users/[user]/index.js index f1488bcc..a5c0ba64 100644 --- a/app/content/team/users/[user]/index.js +++ b/app/content/team/users/[user]/index.js @@ -321,6 +321,7 @@ function Index() { navigation.goBack(); } catch (e) { console.log("Error removing user:", e); + hideRemoveDialog(); showDialog("Error", getErrorString(e)); } }, @@ -346,6 +347,7 @@ function Index() { navigation.goBack(); } catch (e) { console.log("Error banning user:", e); + hideBanDialog(); showDialog("Error", getErrorString(e)); } }, diff --git a/dbOperations/removeUser.js b/dbOperations/removeUser.js index f167b072..b7129c4f 100644 --- a/dbOperations/removeUser.js +++ b/dbOperations/removeUser.js @@ -22,6 +22,11 @@ async function removeUser(teamId, userId) { const attemptSnapshot = await getDocs(attemptQuery); + //Remove user from user table where UID == userID + const userRef = doc(db, "teams", teamId, "users", userId); + + const userSnapshot = await transaction.get(userRef); + for (const doc of attemptSnapshot.docs) { await transaction.delete(doc.ref); } @@ -44,11 +49,6 @@ async function removeUser(teamId, userId) { } } - //Remove user from user table where UID == userID - const userRef = doc(db, "teams", teamId, "users", userId); - - const userSnapshot = await transaction.get(userRef); - //remove pfp if there is one if (userSnapshot.data().pfp !== "") { await removePfp(getPfpName(teamId, userId)); From beb38bd4c080b5aa95aaaca5e6cacb34c4367a52 Mon Sep 17 00:00:00 2001 From: Frankreed Date: Wed, 7 Aug 2024 14:16:39 +0700 Subject: [PATCH 39/56] debounced invite button --- app/segments/(team)/invitelist.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/segments/(team)/invitelist.js b/app/segments/(team)/invitelist.js index cdd1a9d1..c744bd9a 100644 --- a/app/segments/(team)/invitelist.js +++ b/app/segments/(team)/invitelist.js @@ -153,7 +153,7 @@ export function Invitelist() { }} /> {/* Sign Out Button */} From a030a08ea854e5cba186ff7c80b99228e4917a8b Mon Sep 17 00:00:00 2001 From: Frankreed Date: Thu, 8 Aug 2024 11:48:05 +0700 Subject: [PATCH 42/56] Fixed Android keyboard avoiding for invitelist --- app.json | 3 +-- app/content/team/index.js | 1 + components/bottomSheetWrapper.js | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app.json b/app.json index 0d730b57..f2db2e97 100644 --- a/app.json +++ b/app.json @@ -22,8 +22,7 @@ "foregroundImage": "./assets/adaptive-icon.png", "backgroundColor": "#ffffff" }, - "package": "com.golfteam.golfapp", - "softwareKeyboardLayoutMode": "pan" + "package": "com.golfteam.golfapp" }, "web": { "favicon": "./assets/favicon.png" diff --git a/app/content/team/index.js b/app/content/team/index.js index f90d4f88..5c41c6b7 100644 --- a/app/content/team/index.js +++ b/app/content/team/index.js @@ -5,6 +5,7 @@ import { BottomSheetTextInput, } from "@gorhom/bottom-sheet"; import { useQueryClient } from "@tanstack/react-query"; +import { router } from "expo-router"; import { doc, updateDoc } from "firebase/firestore"; import { useEffect, useRef, useState } from "react"; import { diff --git a/components/bottomSheetWrapper.js b/components/bottomSheetWrapper.js index 398ebbb8..f36cc084 100644 --- a/components/bottomSheetWrapper.js +++ b/components/bottomSheetWrapper.js @@ -14,6 +14,7 @@ const BottomSheetWrapper = forwardRef( backgroundStyle={{ backgroundColor: themeColors.background }} topInset={insets.top} keyboardBlurBehavior={"restore"} + android_keyboardInputMode={"adjustResize"} backdropComponent={({ animatedIndex, style }) => { return ( Date: Mon, 12 Aug 2024 21:47:58 +0700 Subject: [PATCH 43/56] removed redundant remove user fix --- app/content/team/users/[user]/index.js | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/app/content/team/users/[user]/index.js b/app/content/team/users/[user]/index.js index ae3c3c7c..a5c0ba64 100644 --- a/app/content/team/users/[user]/index.js +++ b/app/content/team/users/[user]/index.js @@ -320,18 +320,9 @@ function Index() { ]); navigation.goBack(); } catch (e) { - if (e.code === "storage/object-not-found") { - //success kinda weird rn - await invalidateMultipleKeys(queryClient, [ - ["userInfo"], - ["best_attempts"], - ]); - navigation.goBack(); - } else { - console.log("Error removing user:", e); - hideRemoveDialog(); - showDialog("Error", getErrorString(e)); - } + console.log("Error removing user:", e); + hideRemoveDialog(); + showDialog("Error", getErrorString(e)); } }, ]} From e924029b36db752533fe9990463ed8a60b542872 Mon Sep 17 00:00:00 2001 From: Frankreed Date: Tue, 13 Aug 2024 12:26:59 +0700 Subject: [PATCH 44/56] pretty --- app/segments/(team)/chooseTeam.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js index 440b517c..13547e63 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -1,11 +1,11 @@ import { useQueryClient } from "@tanstack/react-query"; import { router } from "expo-router"; -import { doc, setDoc } from "firebase/firestore"; import { onIdTokenChanged, sendEmailVerification, signOut as signoutFireBase, } from "firebase/auth"; +import { doc, setDoc } from "firebase/firestore"; import { useCallback, useEffect, useState } from "react"; import { RefreshControl, ScrollView, Text, View } from "react-native"; import { Button } from "react-native-paper"; @@ -79,7 +79,7 @@ function ChooseTeam() { const onRefresh = useCallback(async () => { setRefreshing(true); await auth.currentUser.reload(); - await invalidateMultipleKeys(queryClient, invalidateKeys) + await invalidateMultipleKeys(queryClient, invalidateKeys); setRefreshing(false); }, []); From 9737dc32567721bd628ca9ea0993a4bb82b5aca8 Mon Sep 17 00:00:00 2001 From: Frankreed Date: Tue, 13 Aug 2024 12:35:50 +0700 Subject: [PATCH 45/56] pretty --- app/segments/(team)/chooseTeam.js | 78 +++++++++++++++---------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js index 7ff6b785..5090e7c6 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -5,12 +5,8 @@ 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 { signOut as signoutFireBase } from "firebase/auth"; -import { useMemo } from "react"; -import { ScrollView, Text, View } from "react-native"; import { Button } from "react-native-paper"; import { SafeAreaView } from "react-native-safe-area-context"; import { themeColors } from "~/Constants"; @@ -135,47 +131,51 @@ function ChooseTeam() { alignItems: "center", flexGrow: 1, }} - refreshControl={} + refreshControl={ + + } > - {!verified ? ( - Waiting for email verification... - - ) : state === "blacklist" ? ( + + Resend Verification Email + + + + ) : state === "blacklist" ? ( Date: Tue, 13 Aug 2024 12:41:44 +0700 Subject: [PATCH 46/56] pretty --- app/segments/(team)/chooseTeam.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js index 9ae8d425..eb558df5 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -7,9 +7,6 @@ import { } from "firebase/auth"; import { useCallback, useEffect, useMemo, useState } from "react"; import { RefreshControl, ScrollView, Text, View } from "react-native"; -import { signOut as signoutFireBase } from "firebase/auth"; -import { useMemo, useState } from "react"; -import { ScrollView, Text, View } from "react-native"; import { Button } from "react-native-paper"; import { SafeAreaView } from "react-native-safe-area-context"; import { themeColors } from "~/Constants"; From 92af7130dba72dd4ff5ddd12824a31815948d4c5 Mon Sep 17 00:00:00 2001 From: Frankreed Date: Tue, 13 Aug 2024 13:49:29 +0700 Subject: [PATCH 47/56] pretty --- app/segments/(team)/chooseTeam.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js index 440b517c..13547e63 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -1,11 +1,11 @@ import { useQueryClient } from "@tanstack/react-query"; import { router } from "expo-router"; -import { doc, setDoc } from "firebase/firestore"; import { onIdTokenChanged, sendEmailVerification, signOut as signoutFireBase, } from "firebase/auth"; +import { doc, setDoc } from "firebase/firestore"; import { useCallback, useEffect, useState } from "react"; import { RefreshControl, ScrollView, Text, View } from "react-native"; import { Button } from "react-native-paper"; @@ -79,7 +79,7 @@ function ChooseTeam() { const onRefresh = useCallback(async () => { setRefreshing(true); await auth.currentUser.reload(); - await invalidateMultipleKeys(queryClient, invalidateKeys) + await invalidateMultipleKeys(queryClient, invalidateKeys); setRefreshing(false); }, []); From e6c5e8a1f0ef2e14dc6506cefee408aeb8dc3966 Mon Sep 17 00:00:00 2001 From: Frankreed Date: Tue, 13 Aug 2024 14:36:38 +0700 Subject: [PATCH 48/56] pretty --- app/segments/(team)/chooseTeam.js | 221 +++++++++++++++--------------- 1 file changed, 110 insertions(+), 111 deletions(-) diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js index e828b4f4..a717df42 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -3,11 +3,10 @@ import { router } from "expo-router"; import { onIdTokenChanged, sendEmailVerification, + signOut as signoutFireBase, } from "firebase/auth"; -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import { RefreshControl, ScrollView, Text, View } from "react-native"; -import { signOut as signoutFireBase } from "firebase/auth"; -import { useMemo } from "react"; import { Button } from "react-native-paper"; import { SafeAreaView } from "react-native-safe-area-context"; import { themeColors } from "~/Constants"; @@ -107,7 +106,7 @@ function ChooseTeam() { const onRefresh = useCallback(async () => { setRefreshing(true); await auth.currentUser.reload(); - await invalidateMultipleKeys(queryClient, invalidateKeys) + await invalidateMultipleKeys(queryClient, invalidateKeys); setRefreshing(false); }, []); @@ -132,132 +131,132 @@ function ChooseTeam() { } contentContainerStyle={{ flex: 1, justifyContent: "center" }} > - {!verified ? ( - + Waiting for email verification... + - - ): state === "blacklist" ? ( - - You've been banned from this team. - - ) : state === "waitlist" ? ( - + + + ) : 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 + + + + )} Date: Tue, 13 Aug 2024 14:39:20 +0700 Subject: [PATCH 49/56] pretty --- dbOperations/hooks/useUserInfo.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dbOperations/hooks/useUserInfo.js b/dbOperations/hooks/useUserInfo.js index 6ff96ca8..1d0ab5d7 100644 --- a/dbOperations/hooks/useUserInfo.js +++ b/dbOperations/hooks/useUserInfo.js @@ -18,7 +18,8 @@ export const useUserInfo = ({ enabled = true, } = {}) => { const segments = useSegments(); - const { currentTeamId, currentUserId , currentUserVerified} = useAuthContext(); + const { currentTeamId, currentUserId, currentUserVerified } = + useAuthContext(); const week_milliseconds = 604800000; const currentDate = new Date(); const currentDateTime = currentDate.getTime(); From 472a7087b4f28ca5370e651e54d6c28c7cb79fe2 Mon Sep 17 00:00:00 2001 From: Frank Nguyen <41023671+FrankreedX@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:43:26 +0700 Subject: [PATCH 50/56] IWB-7: allow using the "loading" property in DialogComponent (#313) From 2194eb3b164e65c8f2716467753affd9d23e31ce Mon Sep 17 00:00:00 2001 From: Frankreed Date: Tue, 13 Aug 2024 17:32:37 +0700 Subject: [PATCH 51/56] added missing state from merge --- app/segments/(team)/chooseTeam.js | 3 ++- context/Auth.js | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/segments/(team)/chooseTeam.js b/app/segments/(team)/chooseTeam.js index 13547e63..77c8cbe3 100644 --- a/app/segments/(team)/chooseTeam.js +++ b/app/segments/(team)/chooseTeam.js @@ -36,7 +36,8 @@ function ChooseTeam() { const invalidateKeys = [["blacklist"]]; const [verified, setVerified] = useState(false); - const [refreshing, setRefreshing] = useState(false); + const [refreshing, setRefreshing] = useState(false); //for Refresh Control + const [loading, setLoading] = useState(false); //for resend email button async function handleSignOut() { try { diff --git a/context/Auth.js b/context/Auth.js index e73d4f4f..35fb300a 100644 --- a/context/Auth.js +++ b/context/Auth.js @@ -57,13 +57,11 @@ export const AuthProvider = ({ children }) => { setCurrentUserId(newlyLoggedInUser["uid"] ?? "Error (uid)"); setCurrentUserInfo(newlyLoggedInUser ?? {}); console.log("user changed. userId:", newlyLoggedInUser["uid"]); - if (auth.currentUser.emailVerified) { - setCurrentUserVerified(true); - } + setCurrentUserVerified(auth.currentUser.emailVerified); } } }); - }, [currentUserVerified]); + }, []); return ( Date: Tue, 13 Aug 2024 18:18:02 +0700 Subject: [PATCH 52/56] simple fix --- context/Auth.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/context/Auth.js b/context/Auth.js index e73d4f4f..7b2bbf43 100644 --- a/context/Auth.js +++ b/context/Auth.js @@ -36,7 +36,7 @@ export const AuthProvider = ({ children }) => { const [currentUserId, setCurrentUserId] = useState(null); const [currentUserInfo, setCurrentUserInfo] = useState(null); const [currentTeamId, setCurrentTeamId] = useState("1"); - const [currentUserVerified, setCurrentUserVerified] = useState(false); + const [currentUserVerified, setCurrentUserVerified] = useState(true); useProtectedRoute(currentUserId); From 93a7cb20039d59091689f3834b5cfd4957c7d8d5 Mon Sep 17 00:00:00 2001 From: Frankreed Date: Thu, 15 Aug 2024 16:21:13 +0700 Subject: [PATCH 53/56] better align invite input with above elements --- app/segments/(team)/invitelist.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/segments/(team)/invitelist.js b/app/segments/(team)/invitelist.js index a0faa1f0..df60a6ff 100644 --- a/app/segments/(team)/invitelist.js +++ b/app/segments/(team)/invitelist.js @@ -115,6 +115,8 @@ export function Invitelist() { style={{ flexDirection: "row", padding: 5, + paddingLeft: 20, + paddingRight: 35, }} > Date: Thu, 15 Aug 2024 16:30:37 +0700 Subject: [PATCH 54/56] debounced invitelist without changing the color of the loading wheel --- app/segments/(team)/invitelist.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/segments/(team)/invitelist.js b/app/segments/(team)/invitelist.js index a02c4c6f..bf0bc762 100644 --- a/app/segments/(team)/invitelist.js +++ b/app/segments/(team)/invitelist.js @@ -46,6 +46,7 @@ export function Invitelist() { const [inviteLoading, setInviteLoading] = useState(false); const onInvite = async () => { + if (inviteLoading) return; setInviteLoading(true); if (invitedEmail.includes(currentEmailInput)) { setStatusText("Email already invited"); @@ -155,7 +156,7 @@ export function Invitelist() { }} /> diff --git a/components/dialog.js b/components/dialog.js index c78de339..3efa4725 100644 --- a/components/dialog.js +++ b/components/dialog.js @@ -26,7 +26,7 @@ export default function DialogComponent({ labelStyle = { color: themeColors.accent }; } else { style = { backgroundColor: themeColors.accent }; - labelStyle = { color: "white" }; + labelStyle = { color: themeColors.highlight }; } return ( From 2d7c2f5d4cca28f9a06d1f3331c2deaaf470a181 Mon Sep 17 00:00:00 2001 From: Frankreed Date: Thu, 15 Aug 2024 17:49:14 +0700 Subject: [PATCH 56/56] debounced and error handled Unban --- app/segments/(team)/blacklist.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/app/segments/(team)/blacklist.js b/app/segments/(team)/blacklist.js index e4d54a6f..49b3f9b3 100644 --- a/app/segments/(team)/blacklist.js +++ b/app/segments/(team)/blacklist.js @@ -3,6 +3,7 @@ import { useState } from "react"; import { ScrollView, View } from "react-native"; import { Button, List } from "react-native-paper"; import { themeColors } from "~/Constants"; +import { getErrorString } from "~/Utility"; import ErrorComponent from "~/components/errorComponent"; import Loading from "~/components/loading"; import RefreshInvalidate from "~/components/refreshInvalidate"; @@ -55,10 +56,20 @@ function Blacklist() { >