diff --git a/src/components/UI/PendingApprovalView.js b/src/components/UI/PendingApprovalView.js new file mode 100644 index 0000000..28aef23 --- /dev/null +++ b/src/components/UI/PendingApprovalView.js @@ -0,0 +1,16 @@ +import {StyleSheet, Text} from 'react-native'; +import Screen from '../layout/Screen'; + +const PendingApprovalView = ({message = 'Waiting for admin approval. You will get access once approved.'}) => ( + + {message} + +); + +const styles = StyleSheet.create({ + center: {justifyContent: 'center', alignItems: 'center', flex: 1}, + body: {color: '#bac2de', fontSize: 15, textAlign: 'center', paddingHorizontal: 20}, +}); + +export default PendingApprovalView; + diff --git a/src/components/screens/LeaderboardScreen.js b/src/components/screens/LeaderboardScreen.js index b7446f3..670da31 100644 --- a/src/components/screens/LeaderboardScreen.js +++ b/src/components/screens/LeaderboardScreen.js @@ -3,6 +3,7 @@ import {ActivityIndicator, Alert, Pressable, ScrollView, StyleSheet, Text, View} import Screen from '../layout/Screen'; import Card from '../UI/Card'; import {Button} from '../UI/Button'; +import PendingApprovalView from '../UI/PendingApprovalView'; import useGameHook from '../../hooks/useGameHook'; import {getSession} from '../../hooks/SessionStore'; @@ -185,11 +186,7 @@ const LeaderboardScreen = ({navigation, route}) => { } if (session.isPendingAdmin && !session.isAcceptedAdmin) { - return ( - - Waiting for admin approval. You will get access once approved. - - ); + return ; } if (isBusiness && isAdmin && !selectedDepartment) { diff --git a/src/components/screens/MapScreen.js b/src/components/screens/MapScreen.js index 4be100d..f192187 100644 --- a/src/components/screens/MapScreen.js +++ b/src/components/screens/MapScreen.js @@ -5,6 +5,7 @@ import * as Location from 'expo-location'; import {useFocusEffect} from '@react-navigation/native'; import Screen from '../layout/Screen'; import {Button, ButtonTray} from '../UI/Button'; +import PendingApprovalView from '../UI/PendingApprovalView'; import CacheCardItem from '../gameplay/CacheCardItem'; import ClaimTimerView from '../gameplay/ClaimTimerView'; import PlayerMapView from '../gameplay/PlayerMapView'; @@ -715,11 +716,7 @@ const MapScreen = ({navigation, route}) => { } if (session.isPendingAdmin && !session.isAcceptedAdmin) { - return ( - - Waiting for admin approval. You will get access once approved. - - ); + return ; } // Player — loading location diff --git a/src/components/screens/PlayersScreen.js b/src/components/screens/PlayersScreen.js index 969a44b..af0b5f5 100644 --- a/src/components/screens/PlayersScreen.js +++ b/src/components/screens/PlayersScreen.js @@ -3,6 +3,7 @@ import {ActivityIndicator, Alert, Pressable, ScrollView, StyleSheet, Text, View} import Screen from '../layout/Screen'; import Card from '../UI/Card'; import {Button} from '../UI/Button'; +import PendingApprovalView from '../UI/PendingApprovalView'; import useGameHook from '../../hooks/useGameHook'; import {getSession} from '../../hooks/SessionStore'; @@ -23,6 +24,9 @@ const PlayersScreen = ({navigation, route}) => { const [loading, setLoading] = useState(true); const [players, setPlayers] = useState([]); const [departmentList, setDepartmentList] = useState([]); + const [adminTeam, setAdminTeam] = useState([]); + const [isCurrentUserAdminLead, setIsCurrentUserAdminLead] = useState(false); + const [adminTeamExpanded, setAdminTeamExpanded] = useState(false); // Handlers ------------------- @@ -32,11 +36,38 @@ const PlayersScreen = ({navigation, route}) => { if (isBusiness && isAdmin && !selectedDepartment) { const sgs = await getSubgroups(session.currentGid); setDepartmentList((sgs || []).filter((sg) => !sg.IsAdminGroup)); + + const allOrgMembers = await getGroupMembers(session.currentGid, null); + const seenAdminUids = new Set(); + const acceptedAdmins = (allOrgMembers || []) + .filter((m) => m.IsAcceptedAdmin) + .sort((a, b) => Number(a.id) - Number(b.id)) + .filter((m) => { + if (seenAdminUids.has(m.Uid)) return false; + seenAdminUids.add(m.Uid); + return true; + }); + + const adminRows = []; + for (const member of acceptedAdmins) { + const user = await getUser(member.Uid); + if (!user) continue; + adminRows.push({ + Uid: member.Uid, + username: user.username || `User ${member.Uid}`, + membershipId: member.id, + }); + } + setAdminTeam(adminRows); + setIsCurrentUserAdminLead(adminRows.length > 0 && adminRows[0].Uid === session.currentUid); setPlayers([]); setLoading(false); return; } + setAdminTeam([]); + setIsCurrentUserAdminLead(false); + // Load subgroup names for department display (business accounts) let subgroupNameMap = {}; if (isBusiness) { @@ -160,6 +191,25 @@ const PlayersScreen = ({navigation, route}) => { await loadData(); }; + const handleKickAdmin = (adminMember) => { + if (!isCurrentUserAdminLead || adminMember.Uid === session.currentUid) return; + Alert.alert( + 'Kick Admin', + `Remove ${adminMember.username} from the admin team?`, + [ + {text: 'Cancel', style: 'cancel'}, + { + text: 'Kick', + style: 'destructive', + onPress: async () => { + await removeMember(adminMember.membershipId); + await loadData(); + }, + }, + ], + ); + }; + // View ----------------------- if (loading) { @@ -179,11 +229,7 @@ const PlayersScreen = ({navigation, route}) => { } if (session.isPendingAdmin && !session.isAcceptedAdmin) { - return ( - - Waiting for admin approval. You will get access once approved. - - ); + return ; } if (isBusiness && isAdmin && !selectedDepartment) { @@ -191,6 +237,36 @@ const PlayersScreen = ({navigation, route}) => { Departments + + setAdminTeamExpanded((prev) => !prev)}> + + Admin Team + {adminTeamExpanded ? 'Close' : 'Open'} + + + {adminTeamExpanded && ( + + {adminTeam.map((adminMember, index) => ( + + + {adminMember.username}{index === 0 ? ' (Admin Lead)' : ''} + + {isCurrentUserAdminLead && adminMember.Uid !== session.currentUid && ( +