diff --git a/app/content/profile/index.js b/app/content/profile/index.js
index e6764a80..e69ba85b 100644
--- a/app/content/profile/index.js
+++ b/app/content/profile/index.js
@@ -1,4 +1,5 @@
import { MaterialIcons } from "@expo/vector-icons";
+import { KeyboardAvoiderScrollView } from "@good-react-native/keyboard-avoider";
import {
BottomSheetModalProvider,
BottomSheetScrollView,
@@ -320,150 +321,157 @@ function Index() {
}}
>
- {/* Profile Picture */}
- {
- try {
- await handleImageUpload(
- setImageUploading,
- showSnackBar,
- getPfpName(currentTeamId, userId),
- userRef,
- profilePicSize,
- profilePicSize,
- );
- await invalidateMultipleKeys(queryClient, [["userInfo"]]);
- } catch (e) {
- console.log(e);
- showDialog("Error", getErrorString(e));
- }
- }}
- >
-
- {imageUploading ? (
-
- ) : (
-
- )}
-
-
-
-
-
- {/* Display Name */}
-
- {userData.name}
-
+
+
+ {/* Profile Picture */}
+ {
+ try {
+ await handleImageUpload(
+ setImageUploading,
+ showSnackBar,
+ getPfpName(currentTeamId, userId),
+ userRef,
+ profilePicSize,
+ profilePicSize,
+ );
+ await invalidateMultipleKeys(queryClient, [["userInfo"]]);
+ } catch (e) {
+ console.log(e);
+ showDialog("Error", getErrorString(e));
+ }
+ }}
+ >
+
+ {imageUploading ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
+ {/* Display Name */}
+
+ {userData.name}
+
- {/* Display Email */}
-
- {email}
-
-
- {/* Name Update input field */}
-
- Update your name
-
- setNewName(text)}
- placeholder="Update your name"
- />
-
- {/* Change Password Button */}
-
- Change Password
- {
- resetForm();
- setPasswordInputVisible(newValue);
- }}
- theme={{
- colors: {
- primary: themeColors.accent,
- },
- }}
- />
-
+ {/* Display Email */}
+
+ {email}
+
- {/* Password Input Field */}
- {passwordInputVisible && (
- <>
-
-
+ {/* Name Update input field */}
+
+
+ Update your name
+
+
setNewName(text)}
+ placeholder="Update your name"
/>
- >
- )}
- {/* Save Button */}
-
+ {/* Change Password Button */}
+
+
+ Change Password
+
+ {
+ resetForm();
+ setPasswordInputVisible(newValue);
+ }}
+ theme={{
+ colors: {
+ primary: themeColors.accent,
+ },
+ }}
+ />
+
+
+ {/* Password Input Field */}
+ {passwordInputVisible && (
+ <>
+
+
+
+ >
+ )}
+
+ {/* Save Button */}
+
- {/* Sign Out Button */}
-
- Sign Out
-
+ {/* Sign Out Button */}
+
+ Sign Out
+
+
+
{uniqueDrills.length > 0 && userData.role === "player" ? (
diff --git a/app/content/team/users/[user]/index.js b/app/content/team/users/[user]/index.js
index 4d934265..a06d86c6 100644
--- a/app/content/team/users/[user]/index.js
+++ b/app/content/team/users/[user]/index.js
@@ -3,7 +3,14 @@ import { useLocalSearchParams, useNavigation } from "expo-router";
import { doc, setDoc, updateDoc } from "firebase/firestore";
import { useState } from "react";
import { FlatList, View } from "react-native";
-import { Appbar, Divider, Menu, SegmentedButtons } from "react-native-paper";
+import {
+ ActivityIndicator,
+ Appbar,
+ Divider,
+ Menu,
+ SegmentedButtons,
+ Text,
+} from "react-native-paper";
import { SafeAreaView } from "react-native-safe-area-context";
import { themeColors } from "~/Constants";
import { getErrorString } from "~/Utility";
@@ -71,6 +78,8 @@ function Index() {
const hideBanDialog = () => setBanDialogVisible(false);
const [banLoading, setBanLoading] = useState(false);
+ const [promoteLoading, setPromoteLoading] = useState(false);
+
const { showDialog, showSnackBar } = useAlertContext();
const { currentUserId, currentTeamId } = useAuthContext();
@@ -246,6 +255,7 @@ function Index() {
}
onPress={async () => {
try {
+ setPromoteLoading(true);
await changeRole(
currentTeamId,
userId,
@@ -258,8 +268,19 @@ function Index() {
console.log(e);
showDialog("Error", getErrorString(e));
}
+ setPromoteLoading(false);
}}
- title={userInfo.role === "player" ? "Promote" : "Demote"}
+ title={
+ <>
+ {promoteLoading ? (
+
+ ) : (
+
+ {userInfo.role === "player" ? "Promote" : "Demote"}
+
+ )}
+ >
+ }
/>
}
>
+ 1 ? "s" : ""}`}
+ onHide={() => {
+ setSnackbarVisible(false);
+ setUnbanCounter(0);
+ }}
+ />
prev + 1);
+ setSnackbarVisible(true);
setUnbanLoading({ ...unbanLoading, [userId]: false });
} catch (e) {
console.log(e);
diff --git a/app/segments/(team)/invitelist.js b/app/segments/(team)/invitelist.js
index bf0bc762..ca2f5c7e 100644
--- a/app/segments/(team)/invitelist.js
+++ b/app/segments/(team)/invitelist.js
@@ -11,6 +11,7 @@ import {
import { Button, List } from "react-native-paper";
import { themeColors } from "~/Constants";
import { getErrorString } from "~/Utility";
+import DialogComponent from "~/components/dialog";
import ErrorComponent from "~/components/errorComponent";
import Loading from "~/components/loading";
import RefreshInvalidate from "~/components/refreshInvalidate";
@@ -45,6 +46,10 @@ export function Invitelist() {
const [removeLoading, setRemoveLoading] = useState({});
const [inviteLoading, setInviteLoading] = useState(false);
+ const [removeCounter, setRemoveCounter] = useState(0);
+
+ const [snackbarVisible, setSnackbarVisible] = useState(false);
+
const onInvite = async () => {
if (inviteLoading) return;
setInviteLoading(true);
@@ -54,6 +59,7 @@ export function Invitelist() {
}
await addToInvitelist(currentTeamId, currentEmailInput);
setCurrentEmailInput("");
+ setCurrentEmailValid(false);
await invalidateMultipleKeys(queryClient, invalidateKeys);
setInviteLoading(false);
};
@@ -75,6 +81,15 @@ export function Invitelist() {
}}
behavior={Platform.OS === "ios" ? "padding" : "height"}
>
+ 1 ? "s" : ""}`}
+ onHide={() => {
+ setSnackbarVisible(false);
+ setRemoveCounter(0);
+ }}
+ />
}
>
@@ -108,6 +123,8 @@ export function Invitelist() {
queryClient,
invalidateKeys,
);
+ setRemoveCounter((prev) => prev + 1);
+ setSnackbarVisible(true);
setRemoveLoading({
...removeLoading,
[inviteId]: false,
diff --git a/app/segments/(team)/waitlist.js b/app/segments/(team)/waitlist.js
index 4b7fa43f..45b18875 100644
--- a/app/segments/(team)/waitlist.js
+++ b/app/segments/(team)/waitlist.js
@@ -4,6 +4,7 @@ import { ScrollView, View } from "react-native";
import { ActivityIndicator, Button, List } from "react-native-paper";
import { themeColors } from "~/Constants";
import { getErrorString } from "~/Utility";
+import DialogComponent from "~/components/dialog";
import ErrorComponent from "~/components/errorComponent";
import Loading from "~/components/loading";
import RefreshInvalidate from "~/components/refreshInvalidate";
@@ -26,6 +27,11 @@ function Waitlist() {
//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({});
+ const [snackbarCounter, setSnackbarCounter] = useState(0);
+ const [lastDecision, setLastDecision] = useState("");
+
+ const [snackbarVisible, setSnackbarVisible] = useState(false);
+
if (waitlistError) {
return ;
}
@@ -40,6 +46,15 @@ function Waitlist() {
}
>
+ 1 ? "s" : ""}`}
+ onHide={() => {
+ setSnackbarVisible(false);
+ setSnackbarCounter(0);
+ }}
+ />
prev + 1);
+ }
+ setSnackbarVisible(true);
setLoading({ ...loading, [userId]: false });
}}
textColor={"green"}
@@ -97,6 +119,13 @@ function Waitlist() {
queryClient,
invalidateKeys,
);
+ if (lastDecision !== "Rejected") {
+ setLastDecision("Rejected");
+ setSnackbarCounter(1);
+ } else {
+ setSnackbarCounter((prev) => prev + 1);
+ }
+ setSnackbarVisible(true);
setLoading({ ...loading, [userId]: false });
}}
textColor={"red"}
diff --git a/package.json b/package.json
index 328ac8ee..b328ed6e 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
"dependencies": {
"@expo/ngrok": "^4.1.0",
"@expo/webpack-config": "^19.0.0",
+ "@good-react-native/keyboard-avoider": "^1.1.4",
"@gorhom/bottom-sheet": "^4",
"@react-native-async-storage/async-storage": "1.23.1",
"@tanstack/query-async-storage-persister": "^5.27.5",
diff --git a/yarn.lock b/yarn.lock
index 2df24088..ff3bf680 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1749,6 +1749,13 @@
resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.1.tgz#0b62c9f47f557a5b4adc073bb0a47542ce6af4c4"
integrity sha512-jmEnr/pk0yVkA7mIlHNnxCi+wWzOFUg0WyIotgkKAb2u1J7fAeDBcVNSTjTihbAYNusCLQdW5s9IJ5qwnEufcQ==
+"@good-react-native/keyboard-avoider@^1.1.4":
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/@good-react-native/keyboard-avoider/-/keyboard-avoider-1.1.4.tgz#634a18d8634d100b2b4e1f419c4b56dc0ab831ab"
+ integrity sha512-Yfbr3b7pOdjdZW03cyHC5kVzFX7D1kPP2jr8yvT7hzI3zoCPuvwTjxzl80vjs3NWCGt1ZAPAbhEkG4oFzGaCSg==
+ dependencies:
+ react-native-uuid "^2.0.1"
+
"@gorhom/bottom-sheet@^4":
version "4.6.3"
resolved "https://registry.yarnpkg.com/@gorhom/bottom-sheet/-/bottom-sheet-4.6.3.tgz#0e16999de7468efc6b730f680692f6d53f0abd8e"
@@ -9360,6 +9367,11 @@ react-native-svg@15.2.0:
css-select "^5.1.0"
css-tree "^1.1.3"
+react-native-uuid@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/react-native-uuid/-/react-native-uuid-2.0.2.tgz#3da192e342ef35ee95a7def676ab41c1256dfd66"
+ integrity sha512-5ypj/hV58P+6VREdjkW0EudSibsH3WdqDERoHKnD9syFWjF+NfRWWrJb2sa3LIwI5zpzMvUiabs+DX40WHpEMw==
+
react-native-web@~0.19.6:
version "0.19.12"
resolved "https://registry.yarnpkg.com/react-native-web/-/react-native-web-0.19.12.tgz#30d1fd70bdff7886f43c0c2698629d830fade6bc"