Récupération de la liste des trains empruntés

This commit is contained in:
Emmy D'Anello 2024-12-12 14:56:17 +01:00
parent 33ee18d7e2
commit 38117ade07
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
4 changed files with 88 additions and 33 deletions

View File

@ -1,8 +1,11 @@
import { useAddTrainMutation } from '@/hooks/mutations/useTrainMutation' import { useAddTrainMutation } from '@/hooks/mutations/useTrainMutation'
import { useAuth } from '@/hooks/useAuth' import { useAuth } from '@/hooks/useAuth'
import { useTrain } from '@/hooks/useTrain'
import { TrainTrip } from '@/utils/features/train/trainSlice'
import { FontAwesome6 } from '@expo/vector-icons'
import { useMemo, useState } from 'react' import { useMemo, useState } from 'react'
import { StyleSheet } from 'react-native' import { FlatList, StyleSheet } from 'react-native'
import { Button, Dialog, FAB, HelperText, Portal, Surface, Text, TextInput } from 'react-native-paper' import { Badge, Button, Dialog, Divider, FAB, HelperText, List, Portal, Surface, Text, TextInput } from 'react-native-paper'
export default function TrainScreen() { export default function TrainScreen() {
const [addTrainVisible, setAddTrainVisible] = useState(false) const [addTrainVisible, setAddTrainVisible] = useState(false)
@ -15,9 +18,13 @@ export default function TrainScreen() {
onPostSuccess: () => setAddTrainVisible(false) onPostSuccess: () => setAddTrainVisible(false)
}) })
const trains = useTrain()
return ( return (
<Surface style={{ flex: 1 }}> <Surface style={{ flex: 1 }}>
<Text variant='bodyMedium'>Ici on aura la page pour ajouter un trajet en train depuis Rail Planner</Text> <FlatList
data={trains.trains}
renderItem={(item) => <TrainListItem train={item.item} />} />
<FAB <FAB
icon='plus' icon='plus'
style={styles.addTrainButton} style={styles.addTrainButton}
@ -63,3 +70,23 @@ const styles = StyleSheet.create({
bottom: 25, bottom: 25,
} }
}) })
function TrainListItem({ train }: { train: TrainTrip }) {
const depDateTime = new Date(train.departureTime)
const depDate = depDateTime.toLocaleDateString()
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' })
const durationInMinutes = (arrDateTime.getTime() - depDateTime.getTime()) / 1000 / 60
const duration = `${Math.floor(durationInMinutes / 60).toString().padStart(2, '0')}:${Math.floor(durationInMinutes % 60).toString().padStart(2, '0')}`
const title = `${train.from} ${depTime} => ${train.to} ${arrTime} (${depDate})`
const distanceKm = Math.ceil(train.distance / 1000)
const cost = 10 * distanceKm
return <>
<List.Item
title={title}
description={<><Text>Durée : {duration}, distance : {distanceKm} km, coût : {cost}</Text> <FontAwesome6 name='coins' /></>}
/>
<Divider />
</>
}

View File

@ -1,5 +1,6 @@
import { useAuth } from '@/hooks/useAuth' import { useAuth } from '@/hooks/useAuth'
import { useGame, useUpdateGameState, useUpdateMoney } from '@/hooks/useGame' import { useGame, useUpdateGameState, useUpdateMoney } from '@/hooks/useGame'
import { useDownloadTrains } from '@/hooks/useTrain'
import { useQuery } from '@tanstack/react-query' import { useQuery } from '@tanstack/react-query'
import { ReactNode, useEffect } from 'react' import { ReactNode, useEffect } from 'react'
@ -8,6 +9,7 @@ export default function GameProvider({ children }: { children: ReactNode }) {
const game = useGame() const game = useGame()
const updateGameState = useUpdateGameState() const updateGameState = useUpdateGameState()
const updateMoney = useUpdateMoney() const updateMoney = useUpdateMoney()
const downloadTrains = useDownloadTrains()
const gameQuery = useQuery({ const gameQuery = useQuery({
queryKey: ['get-game'], queryKey: ['get-game'],
@ -20,10 +22,10 @@ export default function GameProvider({ children }: { children: ReactNode }) {
useEffect(() => { useEffect(() => {
if (gameQuery.isSuccess && gameQuery.data) if (gameQuery.isSuccess && gameQuery.data)
updateGameState(gameQuery.data) updateGameState(gameQuery.data)
}, [gameQuery]) }, [gameQuery.status, gameQuery.dataUpdatedAt])
const playerQuery = useQuery({ const playerQuery = useQuery({
queryKey: ['get-player'], queryKey: ['get-player', game.playerId],
queryFn: () => fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/players/${game.playerId}/`, { queryFn: () => fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/players/${game.playerId}/`, {
headers: { "Authorization": `Bearer ${auth.token}` }} headers: { "Authorization": `Bearer ${auth.token}` }}
).then(resp => resp.json()), ).then(resp => resp.json()),
@ -33,7 +35,20 @@ export default function GameProvider({ children }: { children: ReactNode }) {
useEffect(() => { useEffect(() => {
if (playerQuery.isSuccess && playerQuery.data) if (playerQuery.isSuccess && playerQuery.data)
updateMoney(playerQuery.data.money) updateMoney(playerQuery.data.money)
}, [playerQuery]) }, [playerQuery.status, playerQuery.dataUpdatedAt])
const trainsQuery = useQuery({
queryKey: ['get-trains'],
queryFn: () => fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/trains/`, {
headers: { "Authorization": `Bearer ${auth.token}` }}
).then(resp => resp.json()),
enabled: auth.loggedIn,
refetchInterval: 5000,
})
useEffect(() => {
if (trainsQuery.isSuccess && trainsQuery.data)
downloadTrains(trainsQuery.data)
}, [trainsQuery.status, trainsQuery.dataUpdatedAt])
return <> return <>
{children} {children}

View File

@ -1,3 +1,8 @@
import { useAppSelector } from "./useStore" import { downloadTrains, TrainsPayload } from "@/utils/features/train/trainSlice"
import { useAppDispatch, useAppSelector } from "./useStore"
export const useTrain = () => useAppSelector((state) => state.train) export const useTrain = () => useAppSelector((state) => state.train)
export const useDownloadTrains = () => {
const dispath = useAppDispatch()
return (trainsData: TrainsPayload) => dispath(downloadTrains(trainsData))
}

View File

@ -1,28 +1,4 @@
import { createSlice } from '@reduxjs/toolkit' import { createSlice, PayloadAction } from '@reduxjs/toolkit'
export interface InterrailLeg {
infoJson?: string
info?: InterrailLegInfo
sortOrder: number
}
export interface InterrailTravel {
date: string
infoJson?: string
info?: InterrailTravelInfo
from: string
to: string
type: number
legs: InterrailLeg[]
}
export interface InterrailJourneyData {
travels: InterrailTravel[]
}
export interface InterrailJourney {
data: InterrailJourneyData
}
export interface InterrailTime { export interface InterrailTime {
hours: number hours: number
@ -85,6 +61,8 @@ export interface TrainTrip {
to: string, to: string,
departureTime: number, departureTime: number,
arrivalTime: number, arrivalTime: number,
infoJson?: string,
info?: InterrailLegInfo,
} }
export interface TrainsState { export interface TrainsState {
@ -95,13 +73,43 @@ const initialState: TrainsState = {
trains: [] trains: []
} }
export interface PaginationMeta {
currentPage: number
lastPage: number
nextPage: number
prevPage: number
total: number
totalPerPage: number
}
export interface TrainsPayload {
data: TrainTrip[]
meta: PaginationMeta
}
export const trainSlice = createSlice({ export const trainSlice = createSlice({
name: 'train', name: 'train',
initialState: initialState, initialState: initialState,
reducers: { reducers: {
downloadTrains(state, action: PayloadAction<TrainsPayload>) {
state.trains = state.trains.filter(train => action.payload.data.filter(dlTrain => dlTrain.id === train.id) === null)
for (const dlTrain of action.payload.data) {
const info = dlTrain.infoJson ? JSON.parse(dlTrain.infoJson) : undefined
state.trains.push({
id: dlTrain.id,
distance: dlTrain.distance,
from: dlTrain.from,
to: dlTrain.to,
departureTime: dlTrain.departureTime,
arrivalTime: dlTrain.arrivalTime,
info: info,
})
state.trains.sort((t1, t2) => t1.departureTime > t2.departureTime ? -1 : t1.departureTime == t2.arrivalTime ? 0 : 1)
}
}
}, },
}) })
export const { } = trainSlice.actions export const {downloadTrains } = trainSlice.actions
export default trainSlice.reducer export default trainSlice.reducer