Added global gameplay screens and API hook

fixed routings to global game screen. Fixed navbar layouts on the screen. Updated api keys to use private key and added .env file. Configured useGlobalHook to use api from env variable.
This commit is contained in:
suddenlyoranges committed 2026-04-09 16:48:13 +01:00
1 parent 157d69c21c
commit 9111b38708
6 files changed
+179 -4

No files matched your search

+30
View File
@@ -12,6 +12,10 @@ import GameSettingsScreen from "./src/components/screens/GameSettingsScreen";
import PlayersScreen from "./src/components/screens/PlayersScreen"; import PlayersScreen from "./src/components/screens/PlayersScreen";
import ExpandedMapScreen from "./src/components/screens/ExpandedMapScreen"; import ExpandedMapScreen from "./src/components/screens/ExpandedMapScreen";
import GameSelectionScreen from "./src/components/screens/GameSelectionScreen"; import GameSelectionScreen from "./src/components/screens/GameSelectionScreen";
import GlobalEventsScreen from "./src/components/screens/global/GlobalEventsScreen";
import GlobalMapScreen from "./src/components/screens/global/GlobalMapScreen";
import GlobalCacheViewScreen from "./src/components/screens/global/GlobalCacheViewScreen";
import GlobalLeaderboardScreen from "./src/components/screens/global/GlobalLeaderboardScreen";
import { loadSession } from "./src/hooks/SessionStore"; import { loadSession } from "./src/hooks/SessionStore";
const RootStack = createNativeStackNavigator(); const RootStack = createNativeStackNavigator();
@@ -50,6 +54,19 @@ const GameStack = () => (
name="ExpandedMapScreen" name="ExpandedMapScreen"
component={ExpandedMapScreen} component={ExpandedMapScreen}
/> />
<GameStackNav.Screen
name="GlobalEventsScreen"
component={GlobalEventsScreen}
/>
<GameStackNav.Screen name="GlobalMapScreen" component={GlobalMapScreen} />
<GameStackNav.Screen
name="GlobalCacheViewScreen"
component={GlobalCacheViewScreen}
/>
<GameStackNav.Screen
name="GlobalLeaderboardScreen"
component={GlobalLeaderboardScreen}
/>
</GameStackNav.Navigator> </GameStackNav.Navigator>
); );
@@ -74,6 +91,19 @@ const AdminStack = () => (
component={ExpandedMapScreen} component={ExpandedMapScreen}
/> />
<AdminStackNav.Screen name="TeamScreen" component={TeamScreen} /> <AdminStackNav.Screen name="TeamScreen" component={TeamScreen} />
<AdminStackNav.Screen
name="GlobalEventsScreen"
component={GlobalEventsScreen}
/>
<AdminStackNav.Screen name="GlobalMapScreen" component={GlobalMapScreen} />
<AdminStackNav.Screen
name="GlobalCacheViewScreen"
component={GlobalCacheViewScreen}
/>
<AdminStackNav.Screen
name="GlobalLeaderboardScreen"
component={GlobalLeaderboardScreen}
/>
</AdminStackNav.Navigator> </AdminStackNav.Navigator>
); );
+10
View File
@@ -35,6 +35,11 @@ const BottomNavbar = ({ navigation, routeName }) => {
route: "GameSelectionScreen", route: "GameSelectionScreen",
onPress: () => navigation.navigate("GameSelectionScreen"), onPress: () => navigation.navigate("GameSelectionScreen"),
}, },
{
label: "Global",
route: "GlobalEventsScreen",
onPress: () => navigation.navigate("GlobalEventsScreen"),
},
]; ];
const playerTabs = [ const playerTabs = [
@@ -58,6 +63,11 @@ const BottomNavbar = ({ navigation, routeName }) => {
route: "GameSelectionScreen", route: "GameSelectionScreen",
onPress: () => navigation.navigate("GameSelectionScreen"), onPress: () => navigation.navigate("GameSelectionScreen"),
}, },
{
label: "Global",
route: "GlobalEventsScreen",
onPress: () => navigation.navigate("GlobalEventsScreen"),
},
{ label: "Leave", route: "__leave__", onPress: () => handleLeaveGame() }, { label: "Leave", route: "__leave__", onPress: () => handleLeaveGame() },
]; ];
+4
View File
@@ -20,6 +20,10 @@ const Screen = ({ children, style, showBack = false }) => {
GameSelectionScreen: "Games", GameSelectionScreen: "Games",
PlayersScreen: "Players", PlayersScreen: "Players",
ExpandedMapScreen: "Map View", ExpandedMapScreen: "Map View",
GlobalEventsScreen: "Global Events",
GlobalMapScreen: "Global Map",
GlobalCacheViewScreen: "Cache Details",
GlobalLeaderboardScreen: "Global Leaderboard",
}; };
// State ---------------------- // State ----------------------
@@ -35,7 +35,7 @@ const GameSelectionScreen = ({ navigation }) => {
}; };
const handleExplore = () => { const handleExplore = () => {
navigation.navigate("MapScreen"); navigation.navigate("GlobalEventsScreen");
}; };
// View -------------------------------- // View --------------------------------
+31 -3
View File
@@ -1,8 +1,8 @@
// --- Session Store (with AsyncStorage persistence) --- // --- Session Store (with AsyncStorage persistence) ---
import AsyncStorage from '@react-native-async-storage/async-storage'; import AsyncStorage from "@react-native-async-storage/async-storage";
const STORAGE_KEY = '@mad_session'; const STORAGE_KEY = "@mad_session";
const session = { const session = {
currentUid: null, currentUid: null,
@@ -12,6 +12,9 @@ const session = {
isBusiness: null, isBusiness: null,
isAcceptedAdmin: false, isAcceptedAdmin: false,
teamsEnabled: false, teamsEnabled: false,
// Global gameplay
currentGlobalEventId: null,
currentGlobalPlayerId: null,
}; };
// --- Handlers --- // --- Handlers ---
@@ -46,6 +49,18 @@ const setSessionTeamsEnabled = (val) => {
const getSession = () => ({ ...session }); const getSession = () => ({ ...session });
const setGlobalSession = (eventId, playerId) => {
session.currentGlobalEventId = eventId ?? null;
session.currentGlobalPlayerId = playerId ?? null;
persistSession();
};
const clearGlobalSession = () => {
session.currentGlobalEventId = null;
session.currentGlobalPlayerId = null;
persistSession();
};
const clearSession = () => { const clearSession = () => {
session.currentUid = null; session.currentUid = null;
session.currentGid = null; session.currentGid = null;
@@ -53,6 +68,8 @@ const clearSession = () => {
session.currentTid = null; session.currentTid = null;
session.isBusiness = null; session.isBusiness = null;
session.isAcceptedAdmin = false; session.isAcceptedAdmin = false;
session.currentGlobalEventId = null;
session.currentGlobalPlayerId = null;
AsyncStorage.removeItem(STORAGE_KEY).catch(() => {}); AsyncStorage.removeItem(STORAGE_KEY).catch(() => {});
}; };
@@ -85,4 +102,15 @@ const loadSession = async () => {
return { ...session }; return { ...session };
}; };
export { setSessionUser, setSessionGroup, setSessionTeam, setSessionTeamsEnabled, getSession, clearSession, clearGameSession, loadSession }; export {
setSessionUser,
setSessionGroup,
setSessionTeam,
setSessionTeamsEnabled,
getSession,
clearSession,
clearGameSession,
loadSession,
setGlobalSession,
clearGlobalSession,
};
+103
View File
@@ -0,0 +1,103 @@
import API from "../components/API/API";
const GLOBAL_BASE = process.env.EXPO_PUBLIC_GLOBAL_API_BASE;
const GLOBAL_KEY = process.env.EXPO_PUBLIC_GLOBAL_API_KEY;
// Appends the API key as a query param to any URL
const withKey = (url) => {
const separator = url.includes("?") ? "&" : "?";
return `${url}${separator}key=${GLOBAL_KEY}`;
};
const useGlobalHook = () => {
// Initialisations ---------------------
const eventsEndpoint = `${GLOBAL_BASE}/api/events`;
const playersEndpoint = `${GLOBAL_BASE}/api/players`;
const cachesEndpoint = `${GLOBAL_BASE}/api/caches`;
const findsEndpoint = `${GLOBAL_BASE}/api/finds`;
const usersEndpoint = `${GLOBAL_BASE}/api/users`;
// Handlers ----------------------------
// Events
const getPublicEvents = async () => {
const response = await API.get(withKey(eventsEndpoint));
if (!response.isSuccess) return [];
return response.result.filter((e) => e.EventIspublic);
};
const getEvent = async (eventId) => {
const response = await API.get(withKey(`${eventsEndpoint}/${eventId}`));
return response.isSuccess ? response.result : null;
};
// Players
const getPlayersByEvent = async (eventId) => {
const response = await API.get(
withKey(`${playersEndpoint}/events/${eventId}`),
);
return response.isSuccess ? response.result : [];
};
const joinEvent = async (data) => {
const response = await API.post(withKey(playersEndpoint), data);
return response.isSuccess ? response.result : null;
};
// Caches
const getCachesByEvent = async (eventId) => {
const response = await API.get(
withKey(`${cachesEndpoint}/events/${eventId}`),
);
return response.isSuccess ? response.result : [];
};
const getCache = async (cacheId) => {
const response = await API.get(withKey(`${cachesEndpoint}/${cacheId}`));
return response.isSuccess ? response.result : null;
};
// Finds
const getFindsByEvent = async (eventId) => {
const response = await API.get(
withKey(`${findsEndpoint}/events/${eventId}`),
);
return response.isSuccess ? response.result : [];
};
const getFindsByPlayer = async (playerId) => {
const response = await API.get(
withKey(`${findsEndpoint}/players/${playerId}`),
);
return response.isSuccess ? response.result : [];
};
const logFind = async (data) => {
const response = await API.post(withKey(findsEndpoint), data);
return response.isSuccess ? response.result : null;
};
// Users
const getUser = async (userId) => {
const response = await API.get(withKey(`${usersEndpoint}/${userId}`));
return response.isSuccess ? response.result : null;
};
// Return --------------------------------
return {
getPublicEvents,
getEvent,
getPlayersByEvent,
joinEvent,
getCachesByEvent,
getCache,
getFindsByEvent,
getFindsByPlayer,
logFind,
getUser,
};
};
export default useGlobalHook;