Compare commits
	
		
			3 Commits
		
	
	
		
			e623dad81f
			...
			291e7ff8a7
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 291e7ff8a7 | |||
| 9543177db6 | |||
| 9c7a447e4e | 
| @@ -25,8 +25,8 @@ export default function TabLayout() { | ||||
|       <Tabs.Screen | ||||
|         name="challenges" | ||||
|         options={{ | ||||
|           title: 'Challenges', | ||||
|           headerTitleStyle: {fontSize: 32}, | ||||
|           title: 'Défis', | ||||
|           headerShown: false, | ||||
|           tabBarIcon: ({ color }) => <FontAwesome6 name="coins" size={24} color={color} />, | ||||
|         }} | ||||
|       /> | ||||
|   | ||||
| @@ -1,9 +1,37 @@ | ||||
| import { Surface, Text } from 'react-native-paper' | ||||
| import PenaltyBanner from '@/components/PenalyBanner' | ||||
| import { FontAwesome6 } from '@expo/vector-icons' | ||||
| import { View } from 'react-native' | ||||
| import { Appbar, Button, Surface, Text } from 'react-native-paper' | ||||
|  | ||||
| export default function ChallengesScreen() { | ||||
|   return ( | ||||
|     <Surface> | ||||
|       <Text>Ici on aura la gestion des challenges</Text> | ||||
|     <Surface style={{ flex: 1 }}> | ||||
|       <Appbar.Header> | ||||
|         <Appbar.Content title={"Défis"} /> | ||||
|         <Appbar.Action icon='format-list-bulleted' /> | ||||
|       </Appbar.Header> | ||||
|       <PenaltyBanner /> | ||||
|       <Surface elevation={2} style={{ flex: 1, margin: 20, borderRadius: 20 }}> | ||||
|         <View style={{ padding: 10 }}> | ||||
|           <Text variant='headlineMedium' style={{ textAlign: 'center' }}>Titre</Text> | ||||
|         </View> | ||||
|         <View style={{ flexGrow: 1 }}> | ||||
|           <Surface elevation={5} mode='flat' style={{ flexGrow: 1, padding: 15 }}> | ||||
|             <Text variant='bodyLarge' style={{ flexGrow: 1 }}>Description</Text> | ||||
|             <Text variant='titleMedium'> | ||||
|               Récompense : 500 <FontAwesome6 name='coins' /> | ||||
|             </Text> | ||||
|           </Surface> | ||||
|         </View> | ||||
|         <View style={{ flexWrap: 'wrap', flexDirection: 'row', justifyContent: 'space-around', padding: 15 }}> | ||||
|           <Button mode='outlined' icon='cancel'> | ||||
|             Passer | ||||
|           </Button> | ||||
|           <Button mode='contained' icon='check'> | ||||
|             Terminer | ||||
|           </Button> | ||||
|         </View> | ||||
|       </Surface> | ||||
|     </Surface> | ||||
|   ) | ||||
| } | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| import PenaltyBanner from '@/components/PenalyBanner' | ||||
| import { useAddTrainMutation } from '@/hooks/mutations/useTrainMutation' | ||||
| import { useAuth } from '@/hooks/useAuth' | ||||
| import { useTrain } from '@/hooks/useTrain' | ||||
| @@ -22,6 +23,7 @@ export default function TrainScreen() { | ||||
|  | ||||
|   return ( | ||||
|     <Surface style={{ flex: 1 }}> | ||||
|       <PenaltyBanner /> | ||||
|       <FlatList | ||||
|           data={trains.trains} | ||||
|           keyExtractor={(train) => train.id} | ||||
|   | ||||
| @@ -43,7 +43,7 @@ export default function GameProvider({ children }: { children: ReactNode }) { | ||||
|     queryFn: () => fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/trains/?playerId=${game.playerId}&size=10000`, { | ||||
|       headers: { "Authorization": `Bearer ${auth.token}` }} | ||||
|     ).then(resp => resp.json()), | ||||
|     enabled: isAuthValid(auth) && !game.playerId, | ||||
|     enabled: isAuthValid(auth) && !!game.playerId, | ||||
|     refetchInterval: 5000, | ||||
|   }) | ||||
|   useEffect(() => { | ||||
|   | ||||
							
								
								
									
										49
									
								
								client/components/PenalyBanner.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								client/components/PenalyBanner.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -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 PenaltyBanner() { | ||||
|   const game = useGame() | ||||
|   const penaltyEnd = game.penaltyEnd | ||||
|   const hasPenalty = penaltyEnd !== null | ||||
|   const penaltyEndDate = useMemo(() => new Date(penaltyEnd || 0), [penaltyEnd]) | ||||
|   const penaltyEndPretty = penaltyEndDate.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 (!hasPenalty) | ||||
|       return | ||||
|     const interval = setInterval(() => setRemainingTime(Math.floor((penaltyEndDate.getTime() - new Date().getTime()) / 1000)), 1000) | ||||
|     return () => clearInterval(interval) | ||||
|   }, [hasPenalty, penaltyEndDate]) | ||||
|  | ||||
|   return ( | ||||
|     <View> | ||||
|       <Banner | ||||
|           visible={hasPenalty} | ||||
|           icon={({ size }) => <FontAwesome6 name={iconName} size={size} color={MD3Colors.tertiary80} />} | ||||
|           style={{ backgroundColor: MD3Colors.primary30 }}> | ||||
|         <View> | ||||
|           <Text variant='titleMedium'>Vous avez actuellement une pénalité jusqu'à {penaltyEndPretty}.</Text> | ||||
|           <Text variant='titleSmall'>Temps restant : {prettyRemainingTime}</Text> | ||||
|         </View> | ||||
|       </Banner> | ||||
|       <ProgressBar | ||||
|           visible={hasPenalty} | ||||
|           animatedValue={1 - remainingTime / (3 * 60)} | ||||
|           color={MD3Colors.error40} | ||||
|           style={{ height: 6 }} /> | ||||
|     </View> | ||||
|   ) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user