mirror of
https://github.com/mudabbir-ahmad/MAD-Treasure-Hunt.git
synced 2026-10-08 03:00:20 +00:00
Add global events, map, cache and leaderboard screens
Introduce four new screens for global events: GlobalEventsScreen (lists public events and handles joining), GlobalMapScreen (map/list view of event caches with user location via expo-location and markers using react-native-maps), GlobalCacheViewScreen (cache detail view with ability to log discoveries), and GlobalLeaderboardScreen (rankings and recent finds). Screens use existing global hooks and SessionStore for fetching/joining events, caches, finds and for storing current global player context; they include loading/error states and navigation between screens. Also add simple tab components, styling, and refresh actions.
This commit is contained in:
1 parent
6e25fe6807
commit
157d69c21c
5 files changed
+800
No files matched your search
@@ -0,0 +1,177 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { ActivityIndicator, Alert, StyleSheet, Text, View } from "react-native";
|
||||
import Screen from "../../layout/Screen";
|
||||
import { Button, ButtonTray } from "../../UI/Button";
|
||||
import Card from "../../UI/Card";
|
||||
import useGlobalHook from "../../../hooks/useGlobalHook";
|
||||
import { getSession } from "../../../hooks/SessionStore";
|
||||
|
||||
const GlobalCacheViewScreen = ({ navigation, route }) => {
|
||||
// Initialisations ---------------------
|
||||
|
||||
const { cache, isFound: initIsFound, onFindLogged } = route.params;
|
||||
const { logFind } = useGlobalHook();
|
||||
const session = getSession();
|
||||
|
||||
// State -------------------------------
|
||||
|
||||
const [isFound, setIsFound] = useState(initIsFound);
|
||||
const [isLogging, setIsLogging] = useState(false);
|
||||
|
||||
// Handlers ----------------------------
|
||||
|
||||
const handleLogFind = async () => {
|
||||
if (!session.currentGlobalPlayerId) {
|
||||
Alert.alert(
|
||||
"Not joined",
|
||||
"You must join the event before logging a find.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
Alert.alert(
|
||||
"Log Discovery",
|
||||
`Record that you found "${cache.CacheName}" and earn ${cache.CachePoints ?? 0} points?`,
|
||||
[
|
||||
{ text: "Cancel", style: "cancel" },
|
||||
{
|
||||
text: "Log Find",
|
||||
onPress: async () => {
|
||||
setIsLogging(true);
|
||||
const result = await logFind({
|
||||
FindPlayerID: session.currentGlobalPlayerId,
|
||||
FindCacheID: cache.CacheID,
|
||||
FindDatetime: new Date().toISOString(),
|
||||
});
|
||||
setIsLogging(false);
|
||||
if (result) {
|
||||
setIsFound(true);
|
||||
if (onFindLogged) onFindLogged();
|
||||
Alert.alert(
|
||||
"Discovery logged!",
|
||||
`+${cache.CachePoints ?? 0} points earned.`,
|
||||
);
|
||||
} else {
|
||||
Alert.alert("Error", "Could not log find. Please try again.");
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
);
|
||||
};
|
||||
|
||||
// View --------------------------------
|
||||
|
||||
return (
|
||||
<Screen showBack>
|
||||
<View style={styles.container}>
|
||||
<Card style={styles.card}>
|
||||
<Text style={styles.title}>{cache.CacheName}</Text>
|
||||
|
||||
<View
|
||||
style={[
|
||||
styles.statusBadge,
|
||||
isFound ? styles.badgeFound : styles.badgeOpen,
|
||||
]}
|
||||
>
|
||||
<Text style={styles.statusText}>
|
||||
{isFound ? "Already Found" : "Not Yet Found"}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.detailRow}>
|
||||
<Text style={styles.label}>Points</Text>
|
||||
<Text style={styles.value}>{cache.CachePoints ?? 0}</Text>
|
||||
</View>
|
||||
|
||||
{cache.CacheDescription ? (
|
||||
<View style={styles.detailRow}>
|
||||
<Text style={styles.label}>Description</Text>
|
||||
<Text style={styles.value}>{cache.CacheDescription}</Text>
|
||||
</View>
|
||||
) : null}
|
||||
|
||||
{cache.CacheClue ? (
|
||||
<View style={styles.detailRow}>
|
||||
<Text style={styles.label}>Clue</Text>
|
||||
<Text style={styles.value}>{cache.CacheClue}</Text>
|
||||
</View>
|
||||
) : null}
|
||||
</Card>
|
||||
|
||||
{isLogging ? (
|
||||
<ActivityIndicator size="large" />
|
||||
) : (
|
||||
<ButtonTray>
|
||||
{!isFound && (
|
||||
<Button
|
||||
label="Log Discovery"
|
||||
onClick={handleLogFind}
|
||||
styleButton={styles.logButton}
|
||||
styleLabel={styles.logButtonLabel}
|
||||
/>
|
||||
)}
|
||||
<Button label="Back" onClick={() => navigation.goBack()} />
|
||||
</ButtonTray>
|
||||
)}
|
||||
</View>
|
||||
</Screen>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
gap: 16,
|
||||
},
|
||||
card: {
|
||||
gap: 12,
|
||||
},
|
||||
title: {
|
||||
fontSize: 22,
|
||||
fontWeight: "700",
|
||||
color: "#111827",
|
||||
},
|
||||
statusBadge: {
|
||||
alignSelf: "flex-start",
|
||||
paddingHorizontal: 10,
|
||||
paddingVertical: 4,
|
||||
borderRadius: 12,
|
||||
},
|
||||
badgeFound: {
|
||||
backgroundColor: "#d1fae5",
|
||||
},
|
||||
badgeOpen: {
|
||||
backgroundColor: "#fef3c7",
|
||||
},
|
||||
statusText: {
|
||||
fontSize: 13,
|
||||
fontWeight: "600",
|
||||
color: "#374151",
|
||||
},
|
||||
detailRow: {
|
||||
gap: 2,
|
||||
},
|
||||
label: {
|
||||
fontSize: 12,
|
||||
fontWeight: "600",
|
||||
color: "#6b7280",
|
||||
textTransform: "uppercase",
|
||||
letterSpacing: 0.5,
|
||||
},
|
||||
value: {
|
||||
fontSize: 15,
|
||||
color: "#111827",
|
||||
},
|
||||
logButton: {
|
||||
backgroundColor: "#16a34a",
|
||||
borderColor: "#16a34a",
|
||||
flex: 2,
|
||||
},
|
||||
logButtonLabel: {
|
||||
color: "#fff",
|
||||
fontWeight: "700",
|
||||
},
|
||||
});
|
||||
|
||||
export default GlobalCacheViewScreen;
|
||||
Reference in new issue
Block a user