146 lines
5.4 KiB
TypeScript
146 lines
5.4 KiB
TypeScript
import ChallengeCard from '@/components/ChallengeCard'
|
|
import PenaltyBanner from '@/components/PenalyBanner'
|
|
import { useDrawRandomChallengeMutation, useEndChallenge } from '@/hooks/mutations/useChallengeMutation'
|
|
import { useAuth } from '@/hooks/useAuth'
|
|
import { useChallengeActions } from '@/hooks/useChallengeActions'
|
|
import { useChallenges } from '@/hooks/useChallenges'
|
|
import { useGame } from '@/hooks/useGame'
|
|
import { FontAwesome6, MaterialCommunityIcons } from '@expo/vector-icons'
|
|
import { useQueryClient } from '@tanstack/react-query'
|
|
import { useRouter } from 'expo-router'
|
|
import { useEffect, useMemo, useState } from 'react'
|
|
import { View } from 'react-native'
|
|
import { ActivityIndicator, Appbar, Banner, FAB, MD3Colors, Snackbar, Surface, Text, TouchableRipple } from 'react-native-paper'
|
|
|
|
function ChallengeScreenHeader() {
|
|
const router = useRouter()
|
|
return <>
|
|
<Appbar.Header>
|
|
<Appbar.Content title={"Défi en cours"} />
|
|
<Appbar.Action icon='format-list-bulleted' onPress={() => router.navigate('/challenges-list')} />
|
|
</Appbar.Header>
|
|
<PenaltyBanner />
|
|
</>
|
|
}
|
|
|
|
function ChallengeScreenBody() {
|
|
const queryClient = useQueryClient()
|
|
const auth = useAuth()
|
|
const game = useGame()
|
|
const challengeActions = useChallengeActions()
|
|
const challenges = useChallenges()
|
|
const currentChallengeAction = useMemo(() => {
|
|
if (!game.activeChallengeId)
|
|
return null
|
|
return challengeActions.find((action) => action.id === game.activeChallengeId)
|
|
}, [game, challengeActions])
|
|
const currentChallenge = useMemo(() => {
|
|
if (!currentChallengeAction)
|
|
return null
|
|
return challenges.find((challenge) => challenge.id === currentChallengeAction.challengeId)
|
|
}, [currentChallengeAction, challenges])
|
|
const [loading, setLoading] = useState(false)
|
|
const [successSnackbarVisible, setSuccessSnackbarVisible] = useState(false)
|
|
const [errorVisible, setErrorVisible] = useState(false)
|
|
const [error, setError] = useState([200, ""])
|
|
const drawRandomChallengeMutation = useDrawRandomChallengeMutation({
|
|
auth,
|
|
onPostSuccess: () => {
|
|
setLoading(true)
|
|
setSuccessSnackbarVisible(true)
|
|
queryClient.invalidateQueries({ predicate: (query) => query.queryKey[0] === 'get-challenges' || query.queryKey[0] === 'get-player' })
|
|
},
|
|
onError: ({ response, error }) => {
|
|
setErrorVisible(true)
|
|
if (response)
|
|
setError([response.statusCode, response.message])
|
|
else if (error)
|
|
setError([400, error.message])
|
|
},
|
|
})
|
|
const endChallenge = useEndChallenge({
|
|
auth,
|
|
onPostSuccess: () => {
|
|
setLoading(true)
|
|
setSuccessSnackbarVisible(true)
|
|
queryClient.invalidateQueries({ predicate: (query) => query.queryKey[0] === 'get-challenges' || query.queryKey[0] === 'get-player' })
|
|
},
|
|
onError: ({ response, error }) => {
|
|
setErrorVisible(true)
|
|
if (response)
|
|
setError([response.statusCode, response.message])
|
|
else if (error)
|
|
setError([400, error.message])
|
|
},
|
|
})
|
|
useEffect(() => {
|
|
if (challengeActions)
|
|
setLoading(false)
|
|
}, [challengeActions])
|
|
|
|
return <>
|
|
{loading &&
|
|
<View style={{ flexGrow: 1, justifyContent: 'center', alignItems: 'center' }}>
|
|
<ActivityIndicator size={'large'} />
|
|
</View>}
|
|
{!loading && currentChallenge &&
|
|
<ChallengeCard
|
|
challenge={currentChallenge}
|
|
onSuccess={() => { setLoading(true); endChallenge.mutate({ success: true }) }}
|
|
onFail={() => endChallenge.mutate({ success: false })}
|
|
style={{ flex: 1, margin: 20 }} />}
|
|
{!loading && !game.penaltyEnd && !currentChallenge && game.currentRunner && <>
|
|
<Banner
|
|
elevation={4}
|
|
visible={!currentChallenge && game.currentRunner && !loading}
|
|
icon='vanish'>
|
|
Aucun défi n'est en cours. Veuillez tirer un défi en cliquant sur le bouton central.
|
|
Pour rappel, il faut être hors d'un train pour tirer un défi.
|
|
</Banner>
|
|
<View style={{ flexGrow: 1, justifyContent: 'center', alignItems: 'center' }}>
|
|
<FAB
|
|
label='Tirer un défi'
|
|
icon='cards'
|
|
disabled={drawRandomChallengeMutation.isPending}
|
|
visible={!currentChallenge && game.currentRunner && !loading}
|
|
onPress={() => drawRandomChallengeMutation.mutate()}
|
|
variant='tertiary'
|
|
customSize={64} />
|
|
</View>
|
|
</>}
|
|
<Banner
|
|
visible={!loading && game.gameStarted && !game.currentRunner}
|
|
icon={({ size }) => <FontAwesome6 name='cat' size={size} color={'pink'} />}
|
|
style={{ backgroundColor: MD3Colors.secondary30 }}>
|
|
Vous êtes poursuiveuse, et n'avez donc pas de défi à accomplir.
|
|
</Banner>
|
|
<Snackbar
|
|
key='success-snackbar'
|
|
visible={successSnackbarVisible}
|
|
icon={'close'}
|
|
onDismiss={() => setSuccessSnackbarVisible(false)}
|
|
onIconPress={() => setSuccessSnackbarVisible(false)}>
|
|
Jeu actualisé
|
|
</Snackbar>
|
|
<Snackbar
|
|
key='error-snackbar'
|
|
visible={errorVisible}
|
|
icon={'close'}
|
|
onDismiss={() => setErrorVisible(false)}
|
|
onIconPress={() => setErrorVisible(false)}>
|
|
<Text variant='bodyMedium' style={{ color: MD3Colors.secondary0 }}>
|
|
Erreur {error[0]} : {error[1]}
|
|
</Text>
|
|
</Snackbar>
|
|
</>
|
|
}
|
|
|
|
export default function ChallengesScreen() {
|
|
return (
|
|
<Surface style={{ flex: 1 }}>
|
|
<ChallengeScreenHeader />
|
|
<ChallengeScreenBody />
|
|
</Surface>
|
|
)
|
|
}
|