diff --git a/client/app/(tabs)/index.tsx b/client/app/(tabs)/index.tsx
index d8fd3af..b0637d6 100644
--- a/client/app/(tabs)/index.tsx
+++ b/client/app/(tabs)/index.tsx
@@ -1,3 +1,58 @@
-import MapScreen from './map'
+import { StyleSheet } from 'react-native'
+import "maplibre-gl/dist/maplibre-gl.css"
+import { useBackgroundPermissions } from 'expo-location'
+import Map from '@/components/Map'
+import { FAB, Surface, Text } from 'react-native-paper'
+import { useGame } from '@/hooks/useGame'
+import { FontAwesome6 } from '@expo/vector-icons'
+import FreeChaseBanner from '@/components/FreeChaseBanner'
-export default MapScreen
+export default function MapScreen() {
+ const [backgroundStatus, requestBackgroundPermission] = useBackgroundPermissions()
+ if (!backgroundStatus?.granted && backgroundStatus?.canAskAgain)
+ requestBackgroundPermission()
+
+ const game = useGame()
+
+ return (
+
+ {backgroundStatus?.granted ? : La géolocalisation est requise pour utiliser la carte.}
+ 0}
+ icon={(props) => }
+ color='black'
+ label={`${game.money}`} />
+ 0}
+ size='small'
+ color='black'
+ icon={game.currentRunner ? 'run-fast' : () => }
+ label={game.currentRunner ? "Coureuse" : "Poursuiveuse"} />
+
+
+ )
+}
+
+const styles = StyleSheet.create({
+ page: {
+ flex: 1,
+ },
+ map: {
+ flex: 1,
+ alignSelf: 'stretch',
+ },
+ moneyBadge: {
+ position: 'absolute',
+ top: 40,
+ right: 20,
+ backgroundColor: 'orange',
+ },
+ statusBadge: {
+ position: 'absolute',
+ top: 40,
+ left: 20,
+ backgroundColor: 'pink',
+ },
+})
diff --git a/client/app/(tabs)/map.tsx b/client/app/(tabs)/map.tsx
deleted file mode 100644
index 7960bc4..0000000
--- a/client/app/(tabs)/map.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-import { StyleSheet } from 'react-native'
-import "maplibre-gl/dist/maplibre-gl.css"
-import { useBackgroundPermissions } from 'expo-location'
-import Map from '@/components/Map'
-import { FAB, Surface, Text } from 'react-native-paper'
-import { useGame } from '@/hooks/useGame'
-import { FontAwesome6 } from '@expo/vector-icons'
-
-export default function MapScreen() {
- const [backgroundStatus, requestBackgroundPermission] = useBackgroundPermissions()
- if (!backgroundStatus?.granted && backgroundStatus?.canAskAgain)
- requestBackgroundPermission()
-
- const game = useGame()
-
- return (
-
- {backgroundStatus?.granted ? : La géolocalisation est requise pour utiliser la carte.}
- 0}
- icon={(props) => }
- color='black'
- label={`${game.money}`} />
- 0}
- size='small'
- color='black'
- icon={game.currentRunner ? 'run-fast' : () => }
- label={game.currentRunner ? "Coureuse" : "Poursuiveuse"} />
-
- )
-}
-
-const styles = StyleSheet.create({
- page: {
- flex: 1,
- justifyContent: 'center',
- alignItems: 'center'
- },
- map: {
- flex: 1,
- alignSelf: 'stretch',
- },
- moneyBadge: {
- position: 'absolute',
- top: 40,
- right: 20,
- backgroundColor: 'orange',
- },
- statusBadge: {
- position: 'absolute',
- top: 40,
- left: 20,
- backgroundColor: 'pink',
- },
-})
diff --git a/client/components/FreeChaseBanner.tsx b/client/components/FreeChaseBanner.tsx
new file mode 100644
index 0000000..a0ff488
--- /dev/null
+++ b/client/components/FreeChaseBanner.tsx
@@ -0,0 +1,49 @@
+import { useGame } from "@/hooks/useGame"
+import { FontAwesome6 } from "@expo/vector-icons"
+import { useEffect, useMemo, useState } from "react"
+import { View } from "react-native"
+import { Banner, MD3Colors, ProgressBar, Text } from "react-native-paper"
+
+export default function FreeChaseBanner() {
+ const game = useGame()
+ const chaseFreeTime = game.chaseFreeTime
+ const stunChase = game.gameStarted && !game.currentRunner && chaseFreeTime !== null
+ const chaseFreeDate = useMemo(() => new Date(chaseFreeTime || 0), [chaseFreeTime])
+ const chaseFreePretty = chaseFreeDate.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' })
+ const [remainingTime, setRemainingTime] = useState(0)
+ const prettyRemainingTime = useMemo(() => `${Math.floor(remainingTime / 60).toString().padStart(2, '0')}:${Math.floor(remainingTime % 60).toString().padStart(2, '0')}`, [remainingTime])
+ const iconName = useMemo(() => {
+ switch (Math.abs(remainingTime % 4)) {
+ case 0: return 'hourglass-empty'
+ case 1: return 'hourglass-end'
+ case 2: return 'hourglass-half'
+ case 3: return 'hourglass-start'
+ }
+ }, [remainingTime])
+
+ useEffect(() => {
+ if (!stunChase)
+ return
+ const interval = setInterval(() => setRemainingTime(Math.floor((chaseFreeDate.getTime() - new Date().getTime()) / 1000)), 1000)
+ return () => clearInterval(interval)
+ }, [stunChase, chaseFreeDate])
+
+ return (
+
+
+ }
+ style={{ backgroundColor: MD3Colors.secondary40 }}>
+
+ Vous pourrez vous mettre en chasse à {chaseFreePretty}.
+ Temps restant : {prettyRemainingTime}
+
+
+
+ )
+}