Interaction avec les boutons de fin de défi

This commit is contained in:
Emmy D'Anello 2024-12-12 23:41:20 +01:00
parent 47ec3da6df
commit 63ad84eb8c
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
3 changed files with 95 additions and 29 deletions

View File

@ -1,6 +1,6 @@
import ChallengeCard from '@/components/ChallengeCard' import ChallengeCard from '@/components/ChallengeCard'
import PenaltyBanner from '@/components/PenalyBanner' import PenaltyBanner from '@/components/PenalyBanner'
import { useDrawRandomChallengeMutation } from '@/hooks/mutations/useChallengeMutation' import { useDrawRandomChallengeMutation, useEndChallenge } from '@/hooks/mutations/useChallengeMutation'
import { useAuth } from '@/hooks/useAuth' import { useAuth } from '@/hooks/useAuth'
import { useChallengeActions } from '@/hooks/useChallengeActions' import { useChallengeActions } from '@/hooks/useChallengeActions'
import { useChallenges } from '@/hooks/useChallenges' import { useChallenges } from '@/hooks/useChallenges'
@ -9,7 +9,7 @@ import { FontAwesome6 } from '@expo/vector-icons'
import { useQueryClient } from '@tanstack/react-query' import { useQueryClient } from '@tanstack/react-query'
import { useEffect, useMemo, useState } from 'react' import { useEffect, useMemo, useState } from 'react'
import { View } from 'react-native' import { View } from 'react-native'
import { ActivityIndicator, Appbar, Banner, FAB, MD3Colors, Surface, Text, TouchableRipple } from 'react-native-paper' import { ActivityIndicator, Appbar, Banner, FAB, MD3Colors, Snackbar, Surface, Text, TouchableRipple } from 'react-native-paper'
function ChallengeScreenHeader() { function ChallengeScreenHeader() {
return <> return <>
@ -38,26 +38,44 @@ function ChallengeScreenBody() {
return challenges.challenges.find((challenge) => challenge.id === currentChallengeAction.challengeId) return challenges.challenges.find((challenge) => challenge.id === currentChallengeAction.challengeId)
}, [currentChallengeAction, challenges]) }, [currentChallengeAction, challenges])
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const [successSnackbarVisible, setSuccessSnackbarVisible] = useState(false)
const drawRandomChallengeMutation = useDrawRandomChallengeMutation({ const drawRandomChallengeMutation = useDrawRandomChallengeMutation({
auth, auth,
onPostSuccess: () => { onPostSuccess: () => {
setLoading(true) setLoading(true)
setSuccessSnackbarVisible(true)
queryClient.invalidateQueries({ predicate: (query) => query.queryKey[0] === 'get-challenges' || query.queryKey[0] === 'get-player' }) queryClient.invalidateQueries({ predicate: (query) => query.queryKey[0] === 'get-challenges' || query.queryKey[0] === 'get-player' })
} }
}) })
const endChallenge = useEndChallenge({
auth,
onPostSuccess: () => {
setLoading(true)
setSuccessSnackbarVisible(true)
queryClient.invalidateQueries({ predicate: (query) => query.queryKey[0] === 'get-challenges' || query.queryKey[0] === 'get-player' })
},
})
useEffect(() => { useEffect(() => {
if (challengeActions) if (challengeActions)
setLoading(false) setLoading(false)
}, [challengeActions]) }, [challengeActions])
return <> return <>
{currentChallenge && <ChallengeCard challenge={currentChallenge} />} {loading &&
{!currentChallenge && game.currentRunner && <> <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 })} />}
{!loading && !currentChallenge && game.currentRunner && <>
<Banner <Banner
visible={!currentChallenge && game.currentRunner && !loading} visible={!currentChallenge && game.currentRunner && !loading}
icon='cancel' icon='cancel'
style={{ backgroundColor: MD3Colors.error40 }}> style={{ backgroundColor: MD3Colors.error40 }}>
<Text variant='titleMedium' style={{ textAlign: 'center' }}>Aucun défi en cours.</Text> Aucun défi n'est en cours.
</Banner> </Banner>
<View style={{ flexGrow: 1, justifyContent: 'center', alignItems: 'center' }}> <View style={{ flexGrow: 1, justifyContent: 'center', alignItems: 'center' }}>
<FAB <FAB
@ -68,15 +86,20 @@ function ChallengeScreenBody() {
onPress={() => drawRandomChallengeMutation.mutate()} onPress={() => drawRandomChallengeMutation.mutate()}
variant='tertiary' variant='tertiary'
customSize={64} /> customSize={64} />
{loading && <ActivityIndicator size={'large'} />}
</View> </View>
</>} </>}
<Banner <Banner
visible={game.gameStarted && !game.currentRunner} visible={!loading && game.gameStarted && !game.currentRunner}
icon={({ size }) => <FontAwesome6 name='cat' size={size} color={'pink'} />} icon={({ size }) => <FontAwesome6 name='cat' size={size} color={'pink'} />}
style={{ backgroundColor: MD3Colors.secondary30 }}> style={{ backgroundColor: MD3Colors.secondary30 }}>
Vous êtes poursuiveuse, et n'avez donc pas de défi à accomplir. Vous êtes poursuiveuse, et n'avez donc pas de défi à accomplir.
</Banner> </Banner>
<Snackbar
visible={successSnackbarVisible}
onDismiss={() => setSuccessSnackbarVisible(false)}
action={{ label: "Fermer", onPress: () => setSuccessSnackbarVisible(false) }}>
Jeu actualisé
</Snackbar>
</> </>
} }

View File

@ -1,30 +1,43 @@
import { Challenge } from "@/utils/features/challenges/challengesSlice" import { Challenge } from "@/utils/features/challenges/challengesSlice"
import { FontAwesome6 } from "@expo/vector-icons" import { FontAwesome6 } from "@expo/vector-icons"
import { View } from "react-native" import { View } from "react-native"
import { Button, Surface, Text } from "react-native-paper" import { Button, Card, IconButton, MD3Colors, Surface, Text } from "react-native-paper"
export default function ChallengeCard({ challenge }: { challenge: Challenge }) { export type ChallengeCardProps = {
challenge: Challenge,
onSuccess?: () => void,
onFail?: () => void,
onDelete?: () => void,
onEdit?: () => void,
}
export default function ChallengeCard({ challenge, onSuccess, onFail, onDelete, onEdit }: ChallengeCardProps) {
return ( return (
<Surface elevation={2} style={{ flex: 1, margin: 20, borderRadius: 20 }}> <Surface elevation={2} style={{ flex: 1, margin: 20, borderRadius: 20 }}>
<View style={{ padding: 10 }}> <Card.Title
<Text variant='headlineMedium' style={{ textAlign: 'center' }}>{challenge.title}</Text> title={challenge.title}
</View> titleStyle={{ textAlign: 'center' }}
<View style={{ flexGrow: 1 }}> titleVariant='headlineMedium'
<Surface elevation={5} mode='flat' style={{ flexGrow: 1, padding: 15 }}> right={(props) => onEdit ? <IconButton {...props} icon='file-document-edit-outline' onPress={() => onEdit()} /> : <></>} />
<Text variant='bodyLarge' style={{ flexGrow: 1 }}>{challenge.description}</Text> <View style={{ flexGrow: 1 }}>
<Text variant='titleMedium'> <Surface elevation={5} mode='flat' style={{ flexGrow: 1, paddingHorizontal: 15, paddingVertical: 20 }}>
Récompense : {challenge.reward} <FontAwesome6 name='coins' /> <Text variant='bodyLarge' style={{ flexGrow: 1 }}>{challenge.description}</Text>
</Text> <Text variant='titleMedium'>
</Surface> Récompense : {challenge.reward} <FontAwesome6 name='coins' />
</View> </Text>
<View style={{ flexWrap: 'wrap', flexDirection: 'row', justifyContent: 'space-around', padding: 15 }}> </Surface>
<Button mode='outlined' icon='cancel'> </View>
Passer <View style={{ flexWrap: 'wrap', flexDirection: 'row', justifyContent: 'space-around', padding: 15 }}>
</Button> {onFail && <Button key='failBtn' mode='outlined' icon='cancel' onPress={() => onFail()}>
<Button mode='contained' icon='check'> Passer
Terminer </Button>}
</Button> {onSuccess && <Button key='successBtn' mode='contained' icon='check' onPress={() => onSuccess()}>
</View> Terminer
</Surface> </Button>}
{onDelete && <Button key='deleteBtn' mode='contained' icon='delete' onPress={() => onDelete()} buttonColor={MD3Colors.error60}>
Supprimer
</Button>}
</View>
</Surface>
) )
} }

View File

@ -43,3 +43,33 @@ export const useDrawRandomChallengeMutation = ({ auth, onPostSuccess, onError }:
} }
}) })
} }
export const useEndChallenge = ({ auth, onPostSuccess, onError }: ChallengeActionProps) => {
return useMutation({
mutationFn: async ({ success }: { success: boolean }) => {
return fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/challenge-actions/end-current/`, {
method: "POST",
headers: {
"Authorization": `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
success: success,
})
}).then(resp => resp.json())
},
onSuccess: async (data) => {
if (data.statusCode) {
if (onError)
onError({ response: data })
return
}
if (onPostSuccess)
onPostSuccess()
},
onError: async (error: Error) => {
if (onError)
onError({ error: error })
}
})
}