191 lines
7.5 KiB
TypeScript
191 lines
7.5 KiB
TypeScript
import { useDeleteChallengeActionMutation } from '@/hooks/mutations/useChallengeMutation'
|
|
import { useGameRepairMutation } from '@/hooks/mutations/useGameMutation'
|
|
import { useDeleteTrainMutation } from '@/hooks/mutations/useTrainMutation'
|
|
import { useAuth } from '@/hooks/useAuth'
|
|
import { useChallengeActions } from '@/hooks/useChallengeActions'
|
|
import { useChallenges } from '@/hooks/useChallenges'
|
|
import { useMoneyUpdates } from '@/hooks/useMoneyUpdates'
|
|
import { useTrain } from '@/hooks/useTrain'
|
|
import { MoneyUpdate } from '@/utils/features/moneyUpdates/moneyUpdatesSlice'
|
|
import { FontAwesome6 } from '@expo/vector-icons'
|
|
import { useQueryClient } from '@tanstack/react-query'
|
|
import { useMemo, useState } from 'react'
|
|
import { FlatList } from 'react-native'
|
|
import { Button, Dialog, Divider, List, MD3Colors, Portal, Snackbar, Surface, Text } from 'react-native-paper'
|
|
|
|
export default function HistoryScreen() {
|
|
const auth = useAuth()
|
|
const queryClient = useQueryClient()
|
|
const moneyUpdates = useMoneyUpdates()
|
|
const [deletingMoneyUpdate, setDeletingMoneyUpdate] = useState<MoneyUpdate | null>(null)
|
|
|
|
const [successVisible, setSuccessVisible] = useState(false)
|
|
const [successMessage, setSuccessMessage] = useState("")
|
|
const [errorVisible, setErrorVisible] = useState(false)
|
|
const [error, setError] = useState([200, ""])
|
|
|
|
const deleteTrainMutation = useDeleteTrainMutation({
|
|
auth,
|
|
onPostSuccess: () => {
|
|
setDeletingMoneyUpdate(null)
|
|
setSuccessVisible(true)
|
|
setSuccessMessage("Train supprimé")
|
|
gameRepairMutation.mutate()
|
|
queryClient.invalidateQueries({ predicate: (query) => query.queryKey[0] === 'get-money-updates' || query.queryKey[0] === 'get-trains' })
|
|
},
|
|
onError: ({ response, error }) => {
|
|
setErrorVisible(true)
|
|
if (response)
|
|
setError([response.statusCode, response.message])
|
|
else if (error)
|
|
setError([400, error.message])
|
|
},
|
|
})
|
|
const deleteChallengeActionMutation = useDeleteChallengeActionMutation({
|
|
auth,
|
|
onPostSuccess: () => {
|
|
setDeletingMoneyUpdate(null)
|
|
setSuccessVisible(true)
|
|
setSuccessMessage("Réalisation du défi supprimée")
|
|
gameRepairMutation.mutate()
|
|
queryClient.invalidateQueries({ predicate: (query) => query.queryKey[0] === 'get-money-updates' || query.queryKey[0] === 'get-challenges' })
|
|
},
|
|
onError: ({ response, error }) => {
|
|
setErrorVisible(true)
|
|
if (response)
|
|
setError([response.statusCode, response.message])
|
|
else if (error)
|
|
setError([400, error.message])
|
|
},
|
|
})
|
|
const gameRepairMutation = useGameRepairMutation({
|
|
auth,
|
|
onPostSuccess: () => {
|
|
queryClient.invalidateQueries({ predicate: (query) => query.queryKey[0] === 'get-player' })
|
|
},
|
|
onError: ({ response, error }) => {
|
|
setErrorVisible(true)
|
|
if (response)
|
|
setError([response.statusCode, response.message])
|
|
else if (error)
|
|
setError([400, error.message])
|
|
},
|
|
})
|
|
|
|
function deleteMoneyUpdate(): void {
|
|
if (!deletingMoneyUpdate)
|
|
return
|
|
switch (deletingMoneyUpdate.reason) {
|
|
case 'BUY_TRAIN':
|
|
if (!deletingMoneyUpdate.tripId) return
|
|
deleteTrainMutation.mutate(deletingMoneyUpdate.tripId)
|
|
break
|
|
case 'CHALLENGE':
|
|
if (!deletingMoneyUpdate.actionId) return
|
|
deleteChallengeActionMutation.mutate(deletingMoneyUpdate.actionId)
|
|
break
|
|
}
|
|
setDeletingMoneyUpdate(null)
|
|
}
|
|
|
|
return (
|
|
<Surface style={{ flex :1 }}>
|
|
<FlatList
|
|
data={moneyUpdates}
|
|
keyExtractor={(moneyUpdate) => `money-update-list-item-${moneyUpdate.id}`}
|
|
ItemSeparatorComponent={() => <Divider />}
|
|
renderItem={(item) =>
|
|
<MoneyUpdateListItem moneyUpdate={item.item}
|
|
onDelete={['START', 'NEW_RUN'].includes(item.item.reason) ? undefined : () => setDeletingMoneyUpdate(item.item)} />} />
|
|
<Snackbar
|
|
key='success-snackbar'
|
|
visible={successVisible}
|
|
icon={'close'}
|
|
onDismiss={() => setSuccessVisible(false)}
|
|
onIconPress={() => setSuccessVisible(false)}>
|
|
<Text variant='bodyMedium' style={{ color: MD3Colors.secondary0 }}>
|
|
{successMessage}
|
|
</Text>
|
|
</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>
|
|
<Portal>
|
|
<Dialog visible={deletingMoneyUpdate !== null} onDismiss={() => setDeletingMoneyUpdate(null)}>
|
|
<Dialog.Title>Êtes-vous sûre ?</Dialog.Title>
|
|
<Dialog.Content>
|
|
<Text>Voulez-vous vraiment supprimer ce mouvement de fonds ?</Text>
|
|
{deletingMoneyUpdate && <MoneyUpdateListItem moneyUpdate={deletingMoneyUpdate} />}
|
|
</Dialog.Content>
|
|
<Dialog.Actions>
|
|
<Button onPress={() => setDeletingMoneyUpdate(null)}>Annuler</Button>
|
|
<Button onPress={() => deleteMoneyUpdate()}>Confirmer</Button>
|
|
</Dialog.Actions>
|
|
</Dialog>
|
|
</Portal>
|
|
</Surface>
|
|
)
|
|
}
|
|
|
|
function MoneyUpdateListItem({ moneyUpdate, onDelete }: { moneyUpdate: MoneyUpdate, onDelete?: () => void }) {
|
|
const trains = useTrain()
|
|
const challengeActions = useChallengeActions()
|
|
const challenges = useChallenges()
|
|
|
|
const icon = useMemo(() => {
|
|
switch (moneyUpdate.reason) {
|
|
case 'START': return 'star'
|
|
case 'NEW_RUN': return 'run'
|
|
case 'BUY_TRAIN': return 'train'
|
|
case 'CHALLENGE': return 'cards'
|
|
}
|
|
}, [moneyUpdate.reason])
|
|
|
|
const title = useMemo(() => {
|
|
switch (moneyUpdate.reason) {
|
|
case 'START':
|
|
return "Début de la partie"
|
|
case 'NEW_RUN':
|
|
return "Nouvelle tentative"
|
|
case 'BUY_TRAIN':
|
|
const train = trains.find((train) => train.id === moneyUpdate.tripId)
|
|
if (!train) return "Train"
|
|
const depDateTime = new Date(train.departureTime)
|
|
const depTime = depDateTime.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' })
|
|
const arrDateTime = new Date(train.arrivalTime)
|
|
const arrTime = arrDateTime.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' })
|
|
return `${train.from} ${depTime} => ${train.to} ${arrTime}`
|
|
case 'CHALLENGE':
|
|
const challengeAction = challengeActions.find((challengeAction) => challengeAction.id === moneyUpdate.actionId)
|
|
if (!challengeAction) return "Défi"
|
|
const challenge = challenges.find((challenge) => challenge.id === challengeAction.challengeId)
|
|
if (!challenge) return "Défi"
|
|
return challenge.title
|
|
}
|
|
}, [moneyUpdate.reason, moneyUpdate.tripId, moneyUpdate.actionId])
|
|
|
|
const description = useMemo(() => {
|
|
const earnDate = new Date(moneyUpdate.timestamp).toLocaleDateString(undefined, { day: '2-digit', month: '2-digit' })
|
|
const earnTime = new Date(moneyUpdate.timestamp).toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' })
|
|
const verb = moneyUpdate.amount >= 0 ? "Gagné" : "Dépensé"
|
|
return <Text>
|
|
{verb} {Math.abs(moneyUpdate.amount)} <FontAwesome6 name='coins' /> le {earnDate} à {earnTime}
|
|
</Text>
|
|
}, [moneyUpdate.amount])
|
|
|
|
return (
|
|
<List.Item
|
|
left={(props) => <List.Icon {...props} icon={icon} />}
|
|
title={title}
|
|
description={description}
|
|
onLongPress={onDelete} />
|
|
)
|
|
}
|