diff --git a/App.js b/App.js
index 1ba19b5..542d48d 100644
--- a/App.js
+++ b/App.js
@@ -12,6 +12,10 @@ import GameSettingsScreen from "./src/components/screens/GameSettingsScreen";
import PlayersScreen from "./src/components/screens/PlayersScreen";
import ExpandedMapScreen from "./src/components/screens/ExpandedMapScreen";
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";
const RootStack = createNativeStackNavigator();
@@ -50,6 +54,19 @@ const GameStack = () => (
name="ExpandedMapScreen"
component={ExpandedMapScreen}
/>
+
+
+
+
);
@@ -74,6 +91,19 @@ const AdminStack = () => (
component={ExpandedMapScreen}
/>
+
+
+
+
);
diff --git a/src/components/layout/BottomNavbar.js b/src/components/layout/BottomNavbar.js
index 0e68805..5e210c0 100644
--- a/src/components/layout/BottomNavbar.js
+++ b/src/components/layout/BottomNavbar.js
@@ -35,6 +35,11 @@ const BottomNavbar = ({ navigation, routeName }) => {
route: "GameSelectionScreen",
onPress: () => navigation.navigate("GameSelectionScreen"),
},
+ {
+ label: "Global",
+ route: "GlobalEventsScreen",
+ onPress: () => navigation.navigate("GlobalEventsScreen"),
+ },
];
const playerTabs = [
@@ -58,6 +63,11 @@ const BottomNavbar = ({ navigation, routeName }) => {
route: "GameSelectionScreen",
onPress: () => navigation.navigate("GameSelectionScreen"),
},
+ {
+ label: "Global",
+ route: "GlobalEventsScreen",
+ onPress: () => navigation.navigate("GlobalEventsScreen"),
+ },
{ label: "Leave", route: "__leave__", onPress: () => handleLeaveGame() },
];
diff --git a/src/components/layout/Screen.js b/src/components/layout/Screen.js
index 25ffb0a..9342601 100644
--- a/src/components/layout/Screen.js
+++ b/src/components/layout/Screen.js
@@ -20,6 +20,10 @@ const Screen = ({ children, style, showBack = false }) => {
GameSelectionScreen: "Games",
PlayersScreen: "Players",
ExpandedMapScreen: "Map View",
+ GlobalEventsScreen: "Global Events",
+ GlobalMapScreen: "Global Map",
+ GlobalCacheViewScreen: "Cache Details",
+ GlobalLeaderboardScreen: "Global Leaderboard",
};
// State ----------------------
diff --git a/src/components/screens/GameSelectionScreen.js b/src/components/screens/GameSelectionScreen.js
index 5377e5c..969d70a 100644
--- a/src/components/screens/GameSelectionScreen.js
+++ b/src/components/screens/GameSelectionScreen.js
@@ -35,7 +35,7 @@ const GameSelectionScreen = ({ navigation }) => {
};
const handleExplore = () => {
- navigation.navigate("MapScreen");
+ navigation.navigate("GlobalEventsScreen");
};
// View --------------------------------
diff --git a/src/hooks/SessionStore.js b/src/hooks/SessionStore.js
index a3e3774..341b68d 100644
--- a/src/hooks/SessionStore.js
+++ b/src/hooks/SessionStore.js
@@ -1,8 +1,8 @@
// --- 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 = {
currentUid: null,
@@ -12,6 +12,9 @@ const session = {
isBusiness: null,
isAcceptedAdmin: false,
teamsEnabled: false,
+ // Global gameplay
+ currentGlobalEventId: null,
+ currentGlobalPlayerId: null,
};
// --- Handlers ---
@@ -46,6 +49,18 @@ const setSessionTeamsEnabled = (val) => {
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 = () => {
session.currentUid = null;
session.currentGid = null;
@@ -53,6 +68,8 @@ const clearSession = () => {
session.currentTid = null;
session.isBusiness = null;
session.isAcceptedAdmin = false;
+ session.currentGlobalEventId = null;
+ session.currentGlobalPlayerId = null;
AsyncStorage.removeItem(STORAGE_KEY).catch(() => {});
};
@@ -85,4 +102,15 @@ const loadSession = async () => {
return { ...session };
};
-export { setSessionUser, setSessionGroup, setSessionTeam, setSessionTeamsEnabled, getSession, clearSession, clearGameSession, loadSession };
+export {
+ setSessionUser,
+ setSessionGroup,
+ setSessionTeam,
+ setSessionTeamsEnabled,
+ getSession,
+ clearSession,
+ clearGameSession,
+ loadSession,
+ setGlobalSession,
+ clearGlobalSession,
+};
diff --git a/src/hooks/useGlobalHook.js b/src/hooks/useGlobalHook.js
new file mode 100644
index 0000000..734c824
--- /dev/null
+++ b/src/hooks/useGlobalHook.js
@@ -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;