mirror of
https://github.com/mudabbir-ahmad/MAD-Treasure-Hunt.git
synced 2026-10-07 19:00:20 +00:00
Refactor GameSettingsScreen: enhance data fetching with useRef for API calls, improve loading state management, and streamline subgroup and waitlist handling.
This commit is contained in:
1 parent
4a0468d155
commit
188c581f37
1 file changed
+71
-39
@@ -1,4 +1,4 @@
|
|||||||
import React, {useCallback, useState} from 'react';
|
import React, {useCallback, useEffect, useRef, useState} from 'react';
|
||||||
import {ActivityIndicator, Alert, ScrollView, StyleSheet, Switch, Text, TextInput, View} from 'react-native';
|
import {ActivityIndicator, Alert, ScrollView, StyleSheet, Switch, Text, TextInput, View} from 'react-native';
|
||||||
import {useFocusEffect} from '@react-navigation/native';
|
import {useFocusEffect} from '@react-navigation/native';
|
||||||
import Screen from '../layout/Screen';
|
import Screen from '../layout/Screen';
|
||||||
@@ -12,6 +12,21 @@ const GameSettingsScreen = ({navigation}) => {
|
|||||||
|
|
||||||
const session = getSession();
|
const session = getSession();
|
||||||
const {getLobby, updateGroup, getSubgroups, createSubgroup, deleteSubgroup, resetGame, getAdminWaitlist, approveAdmin, rejectAdmin, getUser, disbandTeams} = useGameHook();
|
const {getLobby, updateGroup, getSubgroups, createSubgroup, deleteSubgroup, resetGame, getAdminWaitlist, approveAdmin, rejectAdmin, getUser, disbandTeams} = useGameHook();
|
||||||
|
const gameApiRef = useRef({
|
||||||
|
getLobby,
|
||||||
|
getSubgroups,
|
||||||
|
getAdminWaitlist,
|
||||||
|
getUser,
|
||||||
|
});
|
||||||
|
gameApiRef.current = {
|
||||||
|
getLobby,
|
||||||
|
getSubgroups,
|
||||||
|
getAdminWaitlist,
|
||||||
|
getUser,
|
||||||
|
};
|
||||||
|
const isMountedRef = useRef(true);
|
||||||
|
const isRefreshingRef = useRef(false);
|
||||||
|
const hasHydratedRef = useRef(false);
|
||||||
|
|
||||||
// State ----------------------
|
// State ----------------------
|
||||||
|
|
||||||
@@ -34,56 +49,73 @@ const GameSettingsScreen = ({navigation}) => {
|
|||||||
|
|
||||||
// Handlers -------------------
|
// Handlers -------------------
|
||||||
|
|
||||||
const loadWaitlist = useCallback(async (gid) => {
|
useEffect(() => () => {
|
||||||
if (!gid) return;
|
isMountedRef.current = false;
|
||||||
const rows = await getAdminWaitlist(gid);
|
}, []);
|
||||||
setWaitlist(rows || []);
|
|
||||||
const names = {};
|
const refreshSettings = useCallback(async ({showLoader = false} = {}) => {
|
||||||
for (const entry of (rows || [])) {
|
const activeSession = getSession();
|
||||||
const u = await getUser(entry.Uid);
|
if (!activeSession.currentGid) {
|
||||||
if (u) names[entry.Uid] = u.username;
|
if (isMountedRef.current) setLoading(false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
setWaitlistNames(names);
|
|
||||||
}, [getAdminWaitlist, getUser]);
|
|
||||||
|
|
||||||
const loadSubgroups = useCallback(async (gid) => {
|
// Guard against re-entrant focus refresh calls.
|
||||||
if (!gid) return;
|
if (isRefreshingRef.current) return;
|
||||||
const sgs = await getSubgroups(gid);
|
isRefreshingRef.current = true;
|
||||||
setSubgroupList(sgs || []);
|
|
||||||
// Set the default member join code from first non-admin subgroup
|
if (showLoader && isMountedRef.current) setLoading(true);
|
||||||
const memberSg = (sgs || []).find((sg) => !sg.IsAdminGroup);
|
|
||||||
if (memberSg) setMemberJoinCode(memberSg.JoinCode || '');
|
try {
|
||||||
}, [getSubgroups]);
|
const [group, sgs, waitlistRows] = await Promise.all([
|
||||||
|
gameApiRef.current.getLobby(activeSession.currentGid),
|
||||||
|
gameApiRef.current.getSubgroups(activeSession.currentGid),
|
||||||
|
gameApiRef.current.getAdminWaitlist(activeSession.currentGid),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!isMountedRef.current) return;
|
||||||
|
|
||||||
const loadSettings = useCallback(async () => {
|
|
||||||
const activeSession = getSession();
|
|
||||||
if (!activeSession.currentGid) {
|
|
||||||
setLoading(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const group = await getLobby(activeSession.currentGid);
|
|
||||||
if (group) {
|
if (group) {
|
||||||
setGroupName(group.GroupName || '');
|
setGroupName(group.GroupName || '');
|
||||||
setBusinessName(group.BusinessOrSchoolName || '');
|
setBusinessName(group.BusinessOrSchoolName || '');
|
||||||
setIsBusinessGroup(Boolean(group.BusinessOrSchoolName || group.OrgJoinCode));
|
// Organisation mode is based on organisation profile data, not generic org join code presence.
|
||||||
|
setIsBusinessGroup(Boolean(group.BusinessOrSchoolName));
|
||||||
|
|
||||||
const serverTeams = Boolean(group.TeamsEnabled);
|
const serverTeams = Boolean(group.TeamsEnabled);
|
||||||
setTeamsEnabled(serverTeams);
|
setTeamsEnabled(serverTeams);
|
||||||
setServerTeamsEnabled(serverTeams);
|
setServerTeamsEnabled(serverTeams);
|
||||||
setSessionTeamsEnabled(serverTeams);
|
setSessionTeamsEnabled(serverTeams);
|
||||||
|
|
||||||
setCacheTriggerMeters(String(group.CacheTriggerMeters || 20));
|
setCacheTriggerMeters(String(group.CacheTriggerMeters || 20));
|
||||||
setAdminJoinCode(group.AdminJoinCode || '');
|
setAdminJoinCode(group.AdminJoinCode || '');
|
||||||
setOrgJoinCode(group.OrgJoinCode || '');
|
setOrgJoinCode(group.OrgJoinCode || '');
|
||||||
}
|
}
|
||||||
await loadSubgroups(activeSession.currentGid);
|
|
||||||
await loadWaitlist(activeSession.currentGid);
|
setSubgroupList(sgs || []);
|
||||||
setLoading(false);
|
const memberSg = (sgs || []).find((sg) => !sg.IsAdminGroup);
|
||||||
}, [getLobby, loadSubgroups, loadWaitlist]);
|
setMemberJoinCode(memberSg?.JoinCode || '');
|
||||||
|
|
||||||
|
setWaitlist(waitlistRows || []);
|
||||||
|
const names = {};
|
||||||
|
for (const entry of (waitlistRows || [])) {
|
||||||
|
const user = await gameApiRef.current.getUser(entry.Uid);
|
||||||
|
if (user) names[entry.Uid] = user.username;
|
||||||
|
}
|
||||||
|
if (!isMountedRef.current) return;
|
||||||
|
setWaitlistNames(names);
|
||||||
|
hasHydratedRef.current = true;
|
||||||
|
} finally {
|
||||||
|
if (isMountedRef.current && (showLoader || !hasHydratedRef.current)) {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
isRefreshingRef.current = false;
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
useCallback(() => {
|
useCallback(() => {
|
||||||
setLoading(true);
|
refreshSettings({showLoader: !hasHydratedRef.current});
|
||||||
loadSettings();
|
}, [refreshSettings]),
|
||||||
}, [loadSettings]),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// --- Individual save ---
|
// --- Individual save ---
|
||||||
@@ -147,12 +179,12 @@ const GameSettingsScreen = ({navigation}) => {
|
|||||||
|
|
||||||
const handleApproveAdmin = async (entry) => {
|
const handleApproveAdmin = async (entry) => {
|
||||||
await approveAdmin(entry.id);
|
await approveAdmin(entry.id);
|
||||||
await loadWaitlist();
|
await refreshSettings();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRejectAdmin = async (entry) => {
|
const handleRejectAdmin = async (entry) => {
|
||||||
await rejectAdmin(entry.id);
|
await rejectAdmin(entry.id);
|
||||||
await loadWaitlist();
|
await refreshSettings();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Business — create a new department (subgroup)
|
// Business — create a new department (subgroup)
|
||||||
@@ -167,7 +199,7 @@ const GameSettingsScreen = ({navigation}) => {
|
|||||||
CacheTriggerMeters: 20,
|
CacheTriggerMeters: 20,
|
||||||
});
|
});
|
||||||
setNewDeptName('');
|
setNewDeptName('');
|
||||||
await loadSubgroups();
|
await refreshSettings();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Business — delete a department
|
// Business — delete a department
|
||||||
@@ -179,7 +211,7 @@ const GameSettingsScreen = ({navigation}) => {
|
|||||||
style: 'destructive',
|
style: 'destructive',
|
||||||
onPress: async () => {
|
onPress: async () => {
|
||||||
await deleteSubgroup(sg.SGid);
|
await deleteSubgroup(sg.SGid);
|
||||||
await loadSubgroups();
|
await refreshSettings();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
@@ -393,7 +425,7 @@ const GameSettingsScreen = ({navigation}) => {
|
|||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={styles.codeSection}>
|
<View style={styles.codeSection}>
|
||||||
<Text style={styles.codeLabel}>Player Join Code</Text>
|
<Text style={styles.codeLabel}>Game Join Code</Text>
|
||||||
<Text style={styles.codeValue}>{memberJoinCode || '—'}</Text>
|
<Text style={styles.codeValue}>{memberJoinCode || '—'}</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user