mirror of
https://github.com/mudabbir-ahmad/MAD-Treasure-Hunt.git
synced 2026-10-08 03:00:20 +00:00
Refactor admin approval handling by introducing PendingApprovalView component for consistent messaging across screens
This commit is contained in:
1 parent
f69ead8e45
commit
191eb8944c
5 files changed
+106
-20
No files matched your search
@@ -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.'}) => (
|
||||||
|
<Screen style={styles.center}>
|
||||||
|
<Text style={styles.body}>{message}</Text>
|
||||||
|
</Screen>
|
||||||
|
);
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
center: {justifyContent: 'center', alignItems: 'center', flex: 1},
|
||||||
|
body: {color: '#bac2de', fontSize: 15, textAlign: 'center', paddingHorizontal: 20},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default PendingApprovalView;
|
||||||
|
|
||||||
@@ -3,6 +3,7 @@ import {ActivityIndicator, Alert, Pressable, ScrollView, StyleSheet, Text, View}
|
|||||||
import Screen from '../layout/Screen';
|
import Screen from '../layout/Screen';
|
||||||
import Card from '../UI/Card';
|
import Card from '../UI/Card';
|
||||||
import {Button} from '../UI/Button';
|
import {Button} from '../UI/Button';
|
||||||
|
import PendingApprovalView from '../UI/PendingApprovalView';
|
||||||
import useGameHook from '../../hooks/useGameHook';
|
import useGameHook from '../../hooks/useGameHook';
|
||||||
import {getSession} from '../../hooks/SessionStore';
|
import {getSession} from '../../hooks/SessionStore';
|
||||||
|
|
||||||
@@ -185,11 +186,7 @@ const LeaderboardScreen = ({navigation, route}) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (session.isPendingAdmin && !session.isAcceptedAdmin) {
|
if (session.isPendingAdmin && !session.isAcceptedAdmin) {
|
||||||
return (
|
return <PendingApprovalView/>;
|
||||||
<Screen style={styles.center}>
|
|
||||||
<Text style={styles.body}>Waiting for admin approval. You will get access once approved.</Text>
|
|
||||||
</Screen>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isBusiness && isAdmin && !selectedDepartment) {
|
if (isBusiness && isAdmin && !selectedDepartment) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import * as Location from 'expo-location';
|
|||||||
import {useFocusEffect} from '@react-navigation/native';
|
import {useFocusEffect} from '@react-navigation/native';
|
||||||
import Screen from '../layout/Screen';
|
import Screen from '../layout/Screen';
|
||||||
import {Button, ButtonTray} from '../UI/Button';
|
import {Button, ButtonTray} from '../UI/Button';
|
||||||
|
import PendingApprovalView from '../UI/PendingApprovalView';
|
||||||
import CacheCardItem from '../gameplay/CacheCardItem';
|
import CacheCardItem from '../gameplay/CacheCardItem';
|
||||||
import ClaimTimerView from '../gameplay/ClaimTimerView';
|
import ClaimTimerView from '../gameplay/ClaimTimerView';
|
||||||
import PlayerMapView from '../gameplay/PlayerMapView';
|
import PlayerMapView from '../gameplay/PlayerMapView';
|
||||||
@@ -715,11 +716,7 @@ const MapScreen = ({navigation, route}) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (session.isPendingAdmin && !session.isAcceptedAdmin) {
|
if (session.isPendingAdmin && !session.isAcceptedAdmin) {
|
||||||
return (
|
return <PendingApprovalView/>;
|
||||||
<Screen style={styles.center}>
|
|
||||||
<Text style={styles.loadingText}>Waiting for admin approval. You will get access once approved.</Text>
|
|
||||||
</Screen>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Player — loading location
|
// Player — loading location
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {ActivityIndicator, Alert, Pressable, ScrollView, StyleSheet, Text, View}
|
|||||||
import Screen from '../layout/Screen';
|
import Screen from '../layout/Screen';
|
||||||
import Card from '../UI/Card';
|
import Card from '../UI/Card';
|
||||||
import {Button} from '../UI/Button';
|
import {Button} from '../UI/Button';
|
||||||
|
import PendingApprovalView from '../UI/PendingApprovalView';
|
||||||
import useGameHook from '../../hooks/useGameHook';
|
import useGameHook from '../../hooks/useGameHook';
|
||||||
import {getSession} from '../../hooks/SessionStore';
|
import {getSession} from '../../hooks/SessionStore';
|
||||||
|
|
||||||
@@ -23,6 +24,9 @@ const PlayersScreen = ({navigation, route}) => {
|
|||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [players, setPlayers] = useState([]);
|
const [players, setPlayers] = useState([]);
|
||||||
const [departmentList, setDepartmentList] = useState([]);
|
const [departmentList, setDepartmentList] = useState([]);
|
||||||
|
const [adminTeam, setAdminTeam] = useState([]);
|
||||||
|
const [isCurrentUserAdminLead, setIsCurrentUserAdminLead] = useState(false);
|
||||||
|
const [adminTeamExpanded, setAdminTeamExpanded] = useState(false);
|
||||||
|
|
||||||
// Handlers -------------------
|
// Handlers -------------------
|
||||||
|
|
||||||
@@ -32,11 +36,38 @@ const PlayersScreen = ({navigation, route}) => {
|
|||||||
if (isBusiness && isAdmin && !selectedDepartment) {
|
if (isBusiness && isAdmin && !selectedDepartment) {
|
||||||
const sgs = await getSubgroups(session.currentGid);
|
const sgs = await getSubgroups(session.currentGid);
|
||||||
setDepartmentList((sgs || []).filter((sg) => !sg.IsAdminGroup));
|
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([]);
|
setPlayers([]);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setAdminTeam([]);
|
||||||
|
setIsCurrentUserAdminLead(false);
|
||||||
|
|
||||||
// Load subgroup names for department display (business accounts)
|
// Load subgroup names for department display (business accounts)
|
||||||
let subgroupNameMap = {};
|
let subgroupNameMap = {};
|
||||||
if (isBusiness) {
|
if (isBusiness) {
|
||||||
@@ -160,6 +191,25 @@ const PlayersScreen = ({navigation, route}) => {
|
|||||||
await loadData();
|
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 -----------------------
|
// View -----------------------
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
@@ -179,11 +229,7 @@ const PlayersScreen = ({navigation, route}) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (session.isPendingAdmin && !session.isAcceptedAdmin) {
|
if (session.isPendingAdmin && !session.isAcceptedAdmin) {
|
||||||
return (
|
return <PendingApprovalView/>;
|
||||||
<Screen style={styles.center}>
|
|
||||||
<Text style={styles.body}>Waiting for admin approval. You will get access once approved.</Text>
|
|
||||||
</Screen>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isBusiness && isAdmin && !selectedDepartment) {
|
if (isBusiness && isAdmin && !selectedDepartment) {
|
||||||
@@ -191,6 +237,36 @@ const PlayersScreen = ({navigation, route}) => {
|
|||||||
<Screen style={styles.container}>
|
<Screen style={styles.container}>
|
||||||
<Text style={styles.sectionTitle}>Departments</Text>
|
<Text style={styles.sectionTitle}>Departments</Text>
|
||||||
<ScrollView style={styles.listSection}>
|
<ScrollView style={styles.listSection}>
|
||||||
|
<Card>
|
||||||
|
<Pressable onPress={() => setAdminTeamExpanded((prev) => !prev)}>
|
||||||
|
<View style={styles.playerRow}>
|
||||||
|
<Text style={styles.playerName}>Admin Team</Text>
|
||||||
|
<Text style={styles.openLabel}>{adminTeamExpanded ? 'Close' : 'Open'}</Text>
|
||||||
|
</View>
|
||||||
|
</Pressable>
|
||||||
|
{adminTeamExpanded && (
|
||||||
|
<View style={styles.adminTeamWrap}>
|
||||||
|
{adminTeam.map((adminMember, index) => (
|
||||||
|
<View key={adminMember.Uid} style={styles.adminTeamRow}>
|
||||||
|
<Text style={styles.adminTeamName} numberOfLines={1}>
|
||||||
|
{adminMember.username}{index === 0 ? ' (Admin Lead)' : ''}
|
||||||
|
</Text>
|
||||||
|
{isCurrentUserAdminLead && adminMember.Uid !== session.currentUid && (
|
||||||
|
<Button
|
||||||
|
label="Kick Admin"
|
||||||
|
onClick={() => handleKickAdmin(adminMember)}
|
||||||
|
styleButton={styles.removeButton}
|
||||||
|
styleLabel={styles.kickLabel}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
{adminTeam.length === 0 && (
|
||||||
|
<Text style={styles.emptyText}>No approved admins yet.</Text>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
{departmentList.map((department) => (
|
{departmentList.map((department) => (
|
||||||
<Pressable
|
<Pressable
|
||||||
key={department.SGid}
|
key={department.SGid}
|
||||||
@@ -323,6 +399,9 @@ const styles = StyleSheet.create({
|
|||||||
removeButton: {backgroundColor: '#D92800', borderColor: '#D92800', minHeight: 36, flex: 1, paddingHorizontal: 10},
|
removeButton: {backgroundColor: '#D92800', borderColor: '#D92800', minHeight: 36, flex: 1, paddingHorizontal: 10},
|
||||||
actionLabel: {color: '#1e1e2e', fontWeight: '600', fontSize: 13},
|
actionLabel: {color: '#1e1e2e', fontWeight: '600', fontSize: 13},
|
||||||
kickLabel: {color: '#ffffff', fontWeight: '600', fontSize: 13},
|
kickLabel: {color: '#ffffff', fontWeight: '600', fontSize: 13},
|
||||||
|
adminTeamWrap: {gap: 8},
|
||||||
|
adminTeamRow: {flexDirection: 'row', alignItems: 'center', gap: 8},
|
||||||
|
adminTeamName: {flex: 1, fontSize: 14, color: '#cdd6f4', fontWeight: '600'},
|
||||||
departmentName: {fontSize: 14, color: '#6c7086', fontStyle: 'italic'},
|
departmentName: {fontSize: 14, color: '#6c7086', fontStyle: 'italic'},
|
||||||
waitlistCard: {backgroundColor: 'rgba(217, 40, 0, 0.15)', borderColor: '#D92800'},
|
waitlistCard: {backgroundColor: 'rgba(217, 40, 0, 0.15)', borderColor: '#D92800'},
|
||||||
approveButton: {backgroundColor: '#a6e3a1', borderColor: '#a6e3a1', minHeight: 36, flex: 1, paddingHorizontal: 10},
|
approveButton: {backgroundColor: '#a6e3a1', borderColor: '#a6e3a1', minHeight: 36, flex: 1, paddingHorizontal: 10},
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {ActivityIndicator, ScrollView, StyleSheet, Text, TextInput, View} from '
|
|||||||
import Screen from '../layout/Screen';
|
import Screen from '../layout/Screen';
|
||||||
import Card from '../UI/Card';
|
import Card from '../UI/Card';
|
||||||
import {Button, ButtonTray} from '../UI/Button';
|
import {Button, ButtonTray} from '../UI/Button';
|
||||||
|
import PendingApprovalView from '../UI/PendingApprovalView';
|
||||||
import useGameHook from '../../hooks/useGameHook';
|
import useGameHook from '../../hooks/useGameHook';
|
||||||
import {getSession, setPendingAdmin, setSessionTeam, setSessionUser} from '../../hooks/SessionStore';
|
import {getSession, setPendingAdmin, setSessionTeam, setSessionUser} from '../../hooks/SessionStore';
|
||||||
|
|
||||||
@@ -212,11 +213,7 @@ const TeamScreen = ({navigation}) => {
|
|||||||
|
|
||||||
// Waiting for admin approval
|
// Waiting for admin approval
|
||||||
if (onAdminWaitlist) {
|
if (onAdminWaitlist) {
|
||||||
return (
|
return <PendingApprovalView message="Waiting to be approved for Admin Team"/>;
|
||||||
<Screen style={styles.center}>
|
|
||||||
<Text style={styles.waitlistText}>Waiting to be approved for Admin Team</Text>
|
|
||||||
</Screen>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not in a team
|
// Not in a team
|
||||||
|
|||||||
Reference in new issue
Block a user