Add new screens for game management, team management, and cache handling; implement caching logic and session management

This commit is contained in:
bobbert committed 2026-04-02 22:08:07 +01:00
1 parent 8686f0e1ff
commit 17ed120ce8
70 files changed
+2172 -3892

No files matched your search

+74
View File
@@ -0,0 +1,74 @@
import {Pressable, StyleSheet, Text, View} from 'react-native';
const BottomNavbar = ({ navigation, routeName }) => {
const tabs = [
{
label: 'Map',
route: 'MapScreen',
onPress: () => navigation.navigate('Game', { screen: 'MapScreen' }),
},
{
label: 'Leaderboard',
route: 'LeaderboardScreen',
onPress: () => navigation.navigate('Game', { screen: 'LeaderboardScreen' }),
},
{
label: 'Current Team',
route: 'TeamScreen',
onPress: () => navigation.navigate('Game', { screen: 'TeamScreen' }),
},
];
return (
<View style={styles.container}>
{tabs.map((tab) => {
const isActive = routeName === tab.route;
return (
<Pressable
key={tab.route}
onPress={tab.onPress}
style={[styles.tab, isActive && styles.tabActive]}
>
<Text style={[styles.tabText, isActive && styles.tabTextActive]}>{tab.label}</Text>
</Pressable>
);
})}
</View>
);
};
const styles = StyleSheet.create({
container: {
minHeight: 64,
borderTopWidth: 1,
borderTopColor: '#e5e7eb',
backgroundColor: '#ffffff',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-around',
paddingHorizontal: 8,
},
tab: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingVertical: 12,
borderRadius: 8,
marginHorizontal: 4,
},
tabActive: {
backgroundColor: '#eff6ff',
},
tabText: {
color: '#374151',
fontSize: 12,
fontWeight: '600',
textAlign: 'center',
},
tabTextActive: {
color: '#2563eb',
},
});
export default BottomNavbar;
+53
View File
@@ -0,0 +1,53 @@
import {StatusBar} from "expo-status-bar";
import {StyleSheet, View} from "react-native";
import {useNavigation, useRoute} from "@react-navigation/native";
import TopNavbar from "./TopNavbar";
import BottomNavbar from "./BottomNavbar";
const Screen = ({ children, style }) => {
const navigation = useNavigation();
const route = useRoute();
const titleMap = {
LoginScreen: "Login",
RegisterScreen: "Register",
GameTypeScreen: "Game Type",
JoinPrivateGameScreen: "Join Private Game",
ManagePrivateGameScreen: "Manage Private Game",
CreateGameScreen: "Create Game",
ManageGameScreen: "Manage Game",
GameLobbyScreen: "Leaderboard",
LeaderboardScreen: "Leaderboard",
TeamScreen: "Current Team",
MapScreen: "Map",
AdminHubScreen: "Admin Hub",
ManageSubgroupsScreen: "Manage Subgroups",
};
const routeName = route.name;
const showBack = routeName !== "LoginScreen" && navigation.canGoBack();
const pageTitle = titleMap[routeName] || "Treasure Hunt";
return (
<View style={[styles.screen, style]}>
<TopNavbar title={pageTitle} showBack={showBack} navigation={navigation} />
<View style={styles.content}>{children}</View>
<BottomNavbar navigation={navigation} routeName={routeName} />
<StatusBar style="light" />
</View>
);
};
const styles = StyleSheet.create({
screen: {
flex: 1,
backgroundColor: "#fff",
},
content: {
flex: 1,
padding: 15,
},
});
export default Screen;
+90
View File
@@ -0,0 +1,90 @@
import {Pressable, StyleSheet, Text, View} from 'react-native';
import {clearSession} from '../../hooks/SessionStore';
const TopNavbar = ({ title, showBack, navigation }) => {
const routeName = navigation.getState()?.routes?.[navigation.getState().index]?.name;
const showLogout = routeName !== 'LoginScreen' && routeName !== 'RegisterScreen';
const handleBack = () => {
if (navigation.canGoBack()) {
navigation.goBack();
}
};
const handleLogout = () => {
clearSession();
navigation.reset({
index: 0,
routes: [{ name: 'Auth', params: { screen: 'LoginScreen' } }],
});
};
return (
<View style={styles.container}>
<View style={styles.leftSlot}>
{showBack ? (
<Pressable onPress={handleBack} style={styles.iconButton}>
<Text style={styles.iconText}>{'<'}</Text>
</Pressable>
) : null}
</View>
<Text style={styles.title}>{title}</Text>
<View style={styles.rightSlot}>
{showLogout ? (
<Pressable onPress={handleLogout} style={styles.logoutButton}>
<Text style={styles.logoutText}>Logout</Text>
</Pressable>
) : null}
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
minHeight: 56,
borderBottomWidth: 1,
borderBottomColor: '#e5e7eb',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 12,
backgroundColor: '#ffffff',
},
leftSlot: {
width: 72,
alignItems: 'flex-start',
},
rightSlot: {
width: 72,
alignItems: 'flex-end',
},
iconButton: {
paddingVertical: 8,
paddingHorizontal: 10,
},
iconText: {
fontSize: 20,
color: '#111827',
fontWeight: '700',
},
title: {
flex: 1,
textAlign: 'center',
fontSize: 18,
fontWeight: '700',
color: '#111827',
},
logoutButton: {
paddingVertical: 6,
paddingHorizontal: 8,
},
logoutText: {
color: '#2563eb',
fontSize: 13,
fontWeight: '600',
},
});
export default TopNavbar;