| 
						 
							
							
							
						 
					 | 
				
			
			 | 
			 | 
			
				@@ -1,20 +1,29 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import ChallengeCard from "@/components/ChallengeCard"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import { useAddChallengeMutation, useDeleteChallengeMutation, useEditChallengeMutation } from "@/hooks/mutations/useChallengeMutation"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import { useAddChallengeMutation, useAttachNewChallenge, useDeleteChallengeMutation, useEditChallengeMutation } 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 { Challenge } from "@/utils/features/challenges/challengesSlice"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import { FontAwesome6 } from "@expo/vector-icons"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import { useQueryClient } from "@tanstack/react-query"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import { useRouter } from "expo-router"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import { useState } from "react"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import React, { ReactNode, useMemo, useState } from "react"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import { FlatList, StyleSheet } from "react-native"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import { Appbar, Button, Dialog, Divider, FAB, List, MD3Colors, Modal, Portal, Snackbar, Surface, Text, TextInput } from "react-native-paper"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import { ActivityIndicator, Appbar, Button, Dialog, Divider, FAB, List, MD3Colors, Modal, Portal, Snackbar, Surface, Text, TextInput, Tooltip } from "react-native-paper"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				export default function ChallengesList() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const router = useRouter()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const queryClient = useQueryClient()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const auth = useAuth()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const game = useGame()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const challenges = useChallenges()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const challengeActions = useChallengeActions()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const currentChallengeAction = useMemo(() => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (!game.activeChallengeId)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return null
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return challengeActions.find((action) => action.id === game.activeChallengeId)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }, [game, challengeActions])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const [editChallengeVisible, setEditChallengeVisible] = useState(false)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const [editChallengeTitle, setEditChallengeTitle] = useState("")
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -23,6 +32,8 @@ export default function ChallengesList() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const [editChallengeId, setEditChallengeId] = useState<number |null>(null)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const [displayedChallenge, setDisplayedChallenge] = useState<Challenge | null>(null)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const [confirmDeletedVisible, setConfirmDeleteVisible] = useState(false)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const [challengeToAttach, setChallengeToAttach] = useState<Challenge | null>(null)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const [successSnackbarVisible, setSuccessSnackbarVisible] = useState(false)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const [successMessage, setSuccessMessage] = useState("")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const [errorVisible, setErrorVisible] = useState(false)
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -80,6 +91,22 @@ export default function ChallengesList() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        setError([400, error.message])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  })
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const attachNewChallengeMutation = useAttachNewChallenge({
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    auth,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    onPostSuccess: () => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      setChallengeToAttach(null)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      setSuccessMessage("Le défi en cours a bien été modifié !")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      queryClient.invalidateQueries({ predicate: (query) => query.queryKey[0] === 'get-challenges' })
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    onError: ({ response, error }) => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      setChallengeToAttach(null)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      setErrorVisible(true)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (response)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        setError([response.statusCode, response.message])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      else if (error)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        setError([400, error.message])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  })
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  function sendEditChallenge() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (editChallengeId) {
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -103,17 +130,26 @@ export default function ChallengesList() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    displayedChallenge && deleteChallengeMutation.mutate(displayedChallenge)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  function sendAttachNewChallenge() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (!challengeToAttach || !currentChallengeAction) return
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    attachNewChallengeMutation.mutate({ challengeActionId: currentChallengeAction.id, newChallengeId: challengeToAttach.id })
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  return (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    <Surface style={{ flex: 1 }}>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      <Appbar.Header>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        {router.canGoBack() ? <Appbar.BackAction onPress={() => router.back()} /> : undefined}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        <Appbar.BackAction onPress={() => router.canGoBack() ? router.back() : router.navigate('/(tabs)/challenges')} />
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        <Appbar.Content title={"Liste des défis"} />
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      </Appbar.Header>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      <FlatList
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        data={challenges}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        keyExtractor={(challenge) => `challenge-list-item-${challenge.id}`}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        ItemSeparatorComponent={() => <Divider />}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        renderItem={(item) => <ChallengeListItem challenge={item.item} onPress={() => setDisplayedChallenge(item.item)} />} />
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        renderItem={(item) =>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            <ChallengeListItem challenge={item.item}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                               activeRunner={game.currentRunner}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                               onPress={() => setDisplayedChallenge(item.item)}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                               onLongPress={!currentChallengeAction ? undefined : () => setChallengeToAttach(item.item)} />} />
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      <Snackbar
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          key='success-snackbar'
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          visible={successSnackbarVisible}
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -206,18 +242,53 @@ export default function ChallengesList() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            <Button onPress={sendDeleteChallenge} disabled={deleteChallengeMutation.isPending}>Confirmer</Button>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          </Dialog.Actions>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        </Dialog>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        <Dialog visible={challengeToAttach !== null} onDismiss={() => setChallengeToAttach(null)}>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          <Dialog.Title>Traiter ce défi</Dialog.Title>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          <Dialog.Content>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            <Text variant='bodyMedium'>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              Voulez-vous vraiment remplacer votre défi actuel par le défi « {challengeToAttach?.title} » ?
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            </Text>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          </Dialog.Content>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          <Dialog.Actions>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            <Button onPress={() => setChallengeToAttach(null)}>Annuler</Button>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            <Button onPress={sendAttachNewChallenge} disabled={attachNewChallengeMutation.isPending}>Confirmer</Button>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          </Dialog.Actions>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        </Dialog>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      </Portal>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    </Surface>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  )
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				function ChallengeListItem({ challenge, onPress }: { challenge: Challenge, onPress?: () => void }) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				type ChallengeListItemProps = {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  challenge: Challenge,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  activeRunner: boolean,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  onPress?: () => void,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  onLongPress?: () => void,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				function ChallengeListItem({ challenge, activeRunner, onPress, onLongPress }: ChallengeListItemProps) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const challengeActions = useChallengeActions()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const attachedAction = challengeActions.find(challengeAction => challengeAction.challengeId === challenge.id)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const description = <Text>Récompense : {challenge.reward} <FontAwesome6 name='coins' /></Text>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const icon: ReactNode = useMemo(() => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (!activeRunner)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return undefined
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    else if (!attachedAction)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return <Tooltip title="Disponible"><List.Icon icon='cards' /></Tooltip>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    else if (!attachedAction.end)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return <Tooltip title="En cours d'accomplissement"><ActivityIndicator /></Tooltip>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    else if (attachedAction.success)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return <Tooltip title="Précédemment réussi"><List.Icon icon='emoticon-happy' /></Tooltip>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    else
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return <Tooltip title="Raté"><List.Icon icon='emoticon-sad' /></Tooltip>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }, [activeRunner, attachedAction])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  return (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    <List.Item
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        title={challenge.title}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        description={description}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        onPress={onPress} />
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        right={() => icon}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        onPress={onPress}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        onLongPress={attachedAction ? undefined : onLongPress} />
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  )
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				 
 |