Use MOTIS API now
This commit is contained in:
parent
e3fd6a7f88
commit
1c99c5ca47
18
src/App.js
18
src/App.js
|
@ -6,10 +6,9 @@ import {frFR, LocalizationProvider} from "@mui/x-date-pickers"
|
||||||
import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs"
|
import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs"
|
||||||
import 'dayjs/locale/fr'
|
import 'dayjs/locale/fr'
|
||||||
import './App.css'
|
import './App.css'
|
||||||
import {QueryClient, QueryClientProvider} from "@tanstack/react-query";
|
import {QueryClient, QueryClientProvider} from "@tanstack/react-query"
|
||||||
import {createSyncStoragePersister} from "@tanstack/query-sync-storage-persister";
|
import Home from "./Home"
|
||||||
import {persistQueryClient} from "@tanstack/react-query-persist-client";
|
import dayjs from "dayjs"
|
||||||
import Home from "./Home";
|
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
|
@ -18,7 +17,7 @@ function App() {
|
||||||
element: <Home />,
|
element: <Home />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/station/:theme/:stationSlug",
|
path: "/station/:theme/:stationId",
|
||||||
element: <Station />
|
element: <Station />
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
@ -54,14 +53,7 @@ function App() {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const localStoragePersister = createSyncStoragePersister({
|
dayjs.locale('fr')
|
||||||
storage: window.localStorage,
|
|
||||||
})
|
|
||||||
|
|
||||||
persistQueryClient({
|
|
||||||
queryClient,
|
|
||||||
persister: localStoragePersister,
|
|
||||||
})
|
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import {Autocomplete, TextField} from "@mui/material";
|
import {Autocomplete, TextField} from "@mui/material";
|
||||||
import {useRef, useState} from "react";
|
import {useState} from "react";
|
||||||
|
|
||||||
function AutocompleteStation(params) {
|
function AutocompleteStation(params) {
|
||||||
const [options, setOptions] = useState([])
|
const [options, setOptions] = useState([])
|
||||||
const previousController = useRef()
|
|
||||||
|
|
||||||
function onInputChange(event, value) {
|
function onInputChange(event, value) {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
|
@ -11,17 +10,9 @@ function AutocompleteStation(params) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (previousController.current)
|
fetch(`${process.env.REACT_APP_MOTIS_SERVER}/api/v1/geocode?language=fr&text=${value}`)
|
||||||
previousController.current.abort()
|
|
||||||
|
|
||||||
const controller = new AbortController()
|
|
||||||
const signal = controller.signal
|
|
||||||
previousController.current = controller
|
|
||||||
fetch("/api/core/station/?search=" + value, {signal})
|
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => data.results)
|
|
||||||
.then(setOptions)
|
.then(setOptions)
|
||||||
.catch()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
|
@ -29,7 +20,7 @@ function AutocompleteStation(params) {
|
||||||
id="stop"
|
id="stop"
|
||||||
options={options}
|
options={options}
|
||||||
onInputChange={onInputChange}
|
onInputChange={onInputChange}
|
||||||
filterOptions={(x) => x}
|
filterOptions={(x) => x.filter(stop => stop.type === "STOP").filter(stop => !stop.id.startsWith("node/"))}
|
||||||
getOptionKey={option => option.id}
|
getOptionKey={option => option.id}
|
||||||
getOptionLabel={option => option.name}
|
getOptionLabel={option => option.name}
|
||||||
groupBy={option => getOptionGroup(option)}
|
groupBy={option => getOptionGroup(option)}
|
||||||
|
@ -40,7 +31,7 @@ function AutocompleteStation(params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOptionGroup(option) {
|
function getOptionGroup(option) {
|
||||||
return option.country
|
return option.id.split('_')[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AutocompleteStation;
|
export default AutocompleteStation;
|
||||||
|
|
|
@ -5,7 +5,7 @@ function Home() {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
|
||||||
function onStationSelected(event, station) {
|
function onStationSelected(event, station) {
|
||||||
navigate(`/station/sncf/${station.slug}/`)
|
navigate(`/station/sncf/${station.id}/`)
|
||||||
}
|
}
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
import {useNavigate, useParams, useSearchParams} from "react-router-dom"
|
import {useNavigate, useParams, useSearchParams} from "react-router-dom"
|
||||||
import TrainsTable from "./TrainsTable"
|
import TrainsTable from "./TrainsTable"
|
||||||
import TripsFilter from "./TripsFilter"
|
import TripsFilter from "./TripsFilter"
|
||||||
import {useState} from "react";
|
import {useState} from "react"
|
||||||
import {Box, Button, FormLabel} from "@mui/material";
|
import {Box, Button, FormLabel} from "@mui/material"
|
||||||
import {DatePicker, TimePicker} from "@mui/x-date-pickers";
|
import {DateTimePicker} from "@mui/x-date-pickers"
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs"
|
||||||
import {useQuery, useQueryClient} from "@tanstack/react-query";
|
import {useQuery, useQueryClient} from "@tanstack/react-query"
|
||||||
import AutocompleteStation from "./AutocompleteStation";
|
import AutocompleteStation from "./AutocompleteStation"
|
||||||
|
|
||||||
function DateTimeSelector({station, date, time}) {
|
function DateTimeSelector({datetime, setDatetime}) {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
|
||||||
function onStationSelected(event, station) {
|
function onStationSelected(event, station) {
|
||||||
if (station !== null)
|
if (station !== null)
|
||||||
navigate(`/station/sncf/${station.slug}/`)
|
navigate(`/station/sncf/${station.id}/`)
|
||||||
}
|
}
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
|
@ -25,38 +25,31 @@ function DateTimeSelector({station, date, time}) {
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
Modifier la date et l'heure de recherche :
|
Modifier la date et l'heure de recherche :
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<DatePicker name="date" label="Date" format="YYYY-MM-DD" defaultValue={dayjs(`${date}`)} />
|
<DateTimePicker name="date" label="Date" onChange={setDatetime} value={datetime} />
|
||||||
<TimePicker name="time" label="Heure" format="HH:mm" defaultValue={dayjs(`${date} ${time}`)} />
|
|
||||||
<Button type="submit">Rechercher</Button>
|
<Button type="submit">Rechercher</Button>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
function Station() {
|
function Station() {
|
||||||
let {theme, stationSlug} = useParams()
|
// eslint-disable-next-line no-unused-vars
|
||||||
let [searchParams, _setSearchParams] = useSearchParams()
|
let {theme, stationId} = useParams()
|
||||||
const now = new Date()
|
// eslint-disable-next-line no-unused-vars
|
||||||
let dateNow = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`
|
let [searchParams, setSearchParams] = useSearchParams()
|
||||||
let timeNow = `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`
|
const [datetime, setDatetime] = useState(dayjs())
|
||||||
let [date, setDate] = useState(searchParams.get('date') || dateNow)
|
|
||||||
let [time, setTime] = useState(searchParams.get('time') || timeNow)
|
|
||||||
|
|
||||||
useQueryClient()
|
useQueryClient()
|
||||||
const stationQuery = useQuery({
|
const stationQuery = useQuery({
|
||||||
queryKey: ['station', stationSlug],
|
queryKey: ['station', stationId],
|
||||||
queryFn: () => fetch(`/api/core/station/${stationSlug}/`)
|
queryFn: () => fetch(`${process.env.REACT_APP_MOTIS_SERVER}/api/v1/stoptimes?stopId=${stationId}&n=1`)
|
||||||
.then(response => response.json()),
|
.then(response => response.json()),
|
||||||
enabled: !!stationSlug,
|
enabled: !!stationId,
|
||||||
})
|
})
|
||||||
const station = stationQuery.data ?? {name: "Chargement…"}
|
const station = stationQuery.data?.stopTimes[0].place ?? {name: "Chargement…"}
|
||||||
|
|
||||||
if (time === timeNow) {
|
if (searchParams.get("time") === undefined) {
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
const now = new Date()
|
setDatetime(dayjs())
|
||||||
let dateNow = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`
|
|
||||||
let timeNow = `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`
|
|
||||||
setDate(dateNow)
|
|
||||||
setTime(timeNow)
|
|
||||||
}, 5000)
|
}, 5000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,10 +60,10 @@ function Station() {
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<DateTimeSelector station={station} date={date} time={time} />
|
<DateTimeSelector datetime={datetime} setDatetime={setDatetime} />
|
||||||
<TripsFilter />
|
<TripsFilter />
|
||||||
<TrainsTable station={station} date={date} time={time} tableType="departures" />
|
<TrainsTable station={station} datetime={datetime} tableType="departures" />
|
||||||
<TrainsTable station={station} date={date} time={time} tableType="arrivals" />
|
<TrainsTable station={station} datetime={datetime} tableType="arrivals" />
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,8 +10,9 @@ import {
|
||||||
Typography
|
Typography
|
||||||
} from "@mui/material"
|
} from "@mui/material"
|
||||||
import {CSSTransition, TransitionGroup} from 'react-transition-group'
|
import {CSSTransition, TransitionGroup} from 'react-transition-group'
|
||||||
import {useQueries, useQuery} from "@tanstack/react-query";
|
import {useQuery} from "@tanstack/react-query"
|
||||||
import {useCallback, useEffect, useMemo, useRef, useState} from "react";
|
import {useCallback, useEffect, useMemo, useRef} from "react"
|
||||||
|
import dayjs from "dayjs"
|
||||||
|
|
||||||
const StyledTableRow = styled(TableRow)(({ theme, tabletype }) => ({
|
const StyledTableRow = styled(TableRow)(({ theme, tabletype }) => ({
|
||||||
'tbody &:nth-of-type(odd)': {
|
'tbody &:nth-of-type(odd)': {
|
||||||
|
@ -26,12 +27,12 @@ const StyledTableRow = styled(TableRow)(({ theme, tabletype }) => ({
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
function TrainsTable({station, date, time, tableType}) {
|
function TrainsTable({station, datetime, tableType}) {
|
||||||
return <>
|
return <>
|
||||||
<TableContainer>
|
<TableContainer>
|
||||||
<Table>
|
<Table>
|
||||||
<TrainsTableHeader tableType={tableType} />
|
<TrainsTableHeader tableType={tableType} />
|
||||||
<TrainsTableBody station={station} date={date} time={time} tableType={tableType} />
|
<TrainsTableBody station={station} datetime={datetime} tableType={tableType} />
|
||||||
</Table>
|
</Table>
|
||||||
</TableContainer>
|
</TableContainer>
|
||||||
</>
|
</>
|
||||||
|
@ -49,25 +50,31 @@ function TrainsTableHeader({tableType}) {
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
function TrainsTableBody({station, date, time, tableType}) {
|
function TrainsTableBody({station, datetime, tableType}) {
|
||||||
const filterTime = useCallback((train) => {
|
const filterTime = useCallback((train) => {
|
||||||
if (tableType === "departures")
|
if (tableType === "departures")
|
||||||
return `${train.departure_date}T${train.departure_time_24h}` >= `${date}T${time}`
|
return dayjs(train.place.departure) >= datetime
|
||||||
else
|
else
|
||||||
return `${train.arrival_date}T${train.arrival_time_24h}` >= `${date}T${time}`
|
return dayjs(train.place.arrival) >= datetime
|
||||||
}, [date, time, tableType])
|
}, [datetime, tableType])
|
||||||
|
|
||||||
const updateTrains = useCallback(() => {
|
const updateTrains = useCallback(() => {
|
||||||
return fetch(`/api/station/next_${tableType}/?station_slug=${station.slug}&date=${date}&time=${time}&offset=${0}&limit=${20}`)
|
const query_params = new URLSearchParams({
|
||||||
|
stopId: station.stopId,
|
||||||
|
arriveBy: tableType === "arrivals",
|
||||||
|
time: datetime.format(),
|
||||||
|
n: 20,
|
||||||
|
}).toString()
|
||||||
|
return fetch(`${process.env.REACT_APP_MOTIS_SERVER}/api/v1/stoptimes?${query_params}`)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => data.results)
|
.then(data => data.stopTimes)
|
||||||
.then(data => [...data])
|
.then(data => [...data])
|
||||||
}, [station.id, date, time, tableType])
|
}, [station.stopId, datetime, tableType])
|
||||||
|
|
||||||
const trainsQuery = useQuery({
|
const trainsQuery = useQuery({
|
||||||
queryKey: ['trains', station.id, tableType],
|
queryKey: ['trains', station.stopId, tableType],
|
||||||
queryFn: updateTrains,
|
queryFn: updateTrains,
|
||||||
enabled: !!station.id,
|
enabled: !!station.stopId,
|
||||||
})
|
})
|
||||||
const trains = useMemo(() => trainsQuery.data ?? [], [trainsQuery.data])
|
const trains = useMemo(() => trainsQuery.data ?? [], [trainsQuery.data])
|
||||||
|
|
||||||
|
@ -79,7 +86,7 @@ function TrainsTableBody({station, date, time, tableType}) {
|
||||||
|
|
||||||
const nullRef = useRef(null)
|
const nullRef = useRef(null)
|
||||||
let table_rows = trains.map((train) => <CSSTransition key={train.id} timeout={500} classNames="shrink" nodeRef={nullRef}>
|
let table_rows = trains.map((train) => <CSSTransition key={train.id} timeout={500} classNames="shrink" nodeRef={nullRef}>
|
||||||
<TrainRow train={train} tableType={tableType} date={date} time={time} />
|
<TrainRow train={train} tableType={tableType} />
|
||||||
</CSSTransition>)
|
</CSSTransition>)
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
|
@ -91,90 +98,42 @@ function TrainsTableBody({station, date, time, tableType}) {
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
function TrainRow({train, tableType, date, time}) {
|
function TrainRow({train, tableType}) {
|
||||||
const tripQuery = useQuery({
|
const tripQuery = useQuery({
|
||||||
queryKey: ['trip', train.trip],
|
queryKey: ['tripId', train.tripId],
|
||||||
queryFn: () => fetch(`/api/gtfs/trip/${train.trip}/`)
|
queryFn: () => fetch(`${process.env.REACT_APP_MOTIS_SERVER}/api/v1/trip?${new URLSearchParams({tripId: train.tripId})}`)
|
||||||
.then(response => response.json()),
|
.then(response => response.json()),
|
||||||
enabled: !!train.trip,
|
enabled: !!train.tripId,
|
||||||
})
|
})
|
||||||
const trip = tripQuery.data ?? {}
|
const trip = tripQuery.data ?? {}
|
||||||
|
const leg = trip.legs ? trip.legs[0] : null
|
||||||
|
|
||||||
const routeQuery = useQuery({
|
const trainType = getTrainType(train)
|
||||||
queryKey: ['route', trip.route],
|
const backgroundColor = getBackgroundColor(train)
|
||||||
queryFn: () => fetch(`/api/gtfs/route/${trip.route}/`)
|
const textColor = getTextColor(train)
|
||||||
.then(response => response.json()),
|
|
||||||
enabled: !!trip.route,
|
|
||||||
})
|
|
||||||
const route = routeQuery.data ?? {}
|
|
||||||
const trainType = getTrainType(train, trip, route)
|
|
||||||
const backgroundColor = getBackgroundColor(train, trip, route)
|
|
||||||
const textColor = getTextColor(train, trip, route)
|
|
||||||
const trainTypeDisplay = getTrainTypeDisplay(trainType)
|
const trainTypeDisplay = getTrainTypeDisplay(trainType)
|
||||||
|
|
||||||
const stopTimesQuery = useQuery({
|
const stops = useMemo(() => leg ? [leg.from, ...leg.intermediateStops, leg.to] : [], [leg])
|
||||||
queryKey: ['stop_times', trip.id],
|
const stopIndex = useMemo(() => {
|
||||||
queryFn: () => fetch(`/api/gtfs/stop_time/?${new URLSearchParams({trip: trip.id, order: 'stop_sequence', limit: 1000})}`)
|
if (stops.length === 0 || train.place.stopId === undefined)
|
||||||
.then(response => response.json())
|
return -1
|
||||||
.then(data => data.results),
|
for (let i = 0; i < stops.length; i++) {
|
||||||
enabled: !!trip.id,
|
const index = tableType === "departures" ? i : stops.length - 1 - i
|
||||||
})
|
const stop = stops[index]
|
||||||
const stopTimes = stopTimesQuery.data ?? []
|
let timeCond = tableType === "departures" ? stop.scheduledDeparture === train.place.scheduledDeparture
|
||||||
const stopIds = stopTimes.map(stop_time => stop_time.stop)
|
: stop.scheduledArrival === train.place.scheduledArrival
|
||||||
|
if (stop.stopId === train.place.stopId && timeCond)
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
}, [stops, train, tableType])
|
||||||
|
const nextStops = tableType === "departures" ? stops.slice(stopIndex + 1) : stops.slice(0, stopIndex)
|
||||||
|
|
||||||
const stopQueries = useQueries({
|
let headline = nextStops[tableType === "departures" ? nextStops.length - 1 : 0] ?? {name: "Chargement…"}
|
||||||
queries: stopIds.map(stopId => ({
|
|
||||||
queryKey: ['stop', stopId],
|
|
||||||
queryFn: () => fetch(`/api/gtfs/stop/${stopId}/`)
|
|
||||||
.then(response => response.json()),
|
|
||||||
enabled: !!stopId,
|
|
||||||
})),
|
|
||||||
})
|
|
||||||
const stops = stopTimes.map(((stopTime, i) => ({...stopTime, stop: stopQueries[i]?.data ?? {"name": "…"}}))) ?? []
|
|
||||||
|
|
||||||
let headline = stops[tableType === "departures" ? stops.length - 1 : 0]?.stop ?? {name: "Chargement…"}
|
const canceled = false // TODO Implémenter l'annulation
|
||||||
|
const [delayed, prettyDelay] = getPrettyDelay(train, tableType)
|
||||||
|
|
||||||
const realtimeTripQuery = useQuery({
|
let stopsNames = nextStops.map(stopTime => stopTime?.name ?? "").join(" > ") ?? ""
|
||||||
queryKey: ['realtimeTrip', trip.id, date, time],
|
|
||||||
queryFn: () => fetch(`/api/gtfs-rt/trip_update/${trip.id}/`)
|
|
||||||
.then(response => response.json()),
|
|
||||||
enabled: !!trip.id,
|
|
||||||
})
|
|
||||||
|
|
||||||
const [realtimeTripData, setRealtimeTripData] = useState({})
|
|
||||||
useEffect(() => {
|
|
||||||
if (realtimeTripQuery.data)
|
|
||||||
setRealtimeTripData(realtimeTripQuery.data)
|
|
||||||
}, [realtimeTripQuery.data])
|
|
||||||
const tripScheduleRelationship = realtimeTripData.schedule_relationship ?? 0
|
|
||||||
|
|
||||||
const realtimeQuery = useQuery({
|
|
||||||
queryKey: ['realtime', train.id, date, time],
|
|
||||||
queryFn: () => fetch(`/api/gtfs-rt/stop_time_update/${train.id}/`)
|
|
||||||
.then(response => response.json()),
|
|
||||||
enabled: !!train.id,
|
|
||||||
})
|
|
||||||
const [realtimeData, setRealtimeData] = useState({})
|
|
||||||
useEffect(() => {
|
|
||||||
if (realtimeQuery.data)
|
|
||||||
setRealtimeData(realtimeQuery.data)
|
|
||||||
}, [realtimeQuery.data])
|
|
||||||
const stopScheduleRelationship = realtimeData.schedule_relationship ?? 0
|
|
||||||
|
|
||||||
const canceled = tripScheduleRelationship === 3 || stopScheduleRelationship === 1
|
|
||||||
|
|
||||||
const delay = tableType === "departures" ? realtimeData.departure_delay : realtimeData.arrival_delay
|
|
||||||
const prettyDelay = delay && !canceled ? getPrettyDelay(delay) : ""
|
|
||||||
const [prettyScheduleRelationship, scheduleRelationshipColor] = getPrettyScheduleRelationship(tripScheduleRelationship, stopScheduleRelationship)
|
|
||||||
|
|
||||||
let stopsFilter
|
|
||||||
if (canceled)
|
|
||||||
stopsFilter = (stop_time) => true
|
|
||||||
else if (tableType === "departures")
|
|
||||||
stopsFilter = (stop_time) => stop_time.stop_sequence > train.stop_sequence && stop_time.drop_off_type === 0
|
|
||||||
else
|
|
||||||
stopsFilter = (stop_time) => stop_time.stop_sequence < train.stop_sequence && stop_time.pickup_type === 0
|
|
||||||
let stopsNames = stops.filter(stopsFilter).map(stopTime => stopTime?.stop.name ?? "").join(" > ") ?? ""
|
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<StyledTableRow tabletype={tableType}>
|
<StyledTableRow tabletype={tableType}>
|
||||||
|
@ -197,8 +156,8 @@ function TrainRow({train, tableType, date, time}) {
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Box display="flex" alignItems="center" justifyContent="center" textAlign="center">
|
<Box display="flex" alignItems="center" justifyContent="center" textAlign="center">
|
||||||
<div>
|
<div>
|
||||||
<div>{trip.short_name}</div>
|
<div>{train.routeShortName}</div>
|
||||||
<div>{trip.headsign}</div>
|
<div>{train.headsign}</div>
|
||||||
</div>
|
</div>
|
||||||
</Box>
|
</Box>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
@ -208,19 +167,16 @@ function TrainRow({train, tableType, date, time}) {
|
||||||
<Box fontWeight="bold" color="#FFED02" fontSize={24}>
|
<Box fontWeight="bold" color="#FFED02" fontSize={24}>
|
||||||
{getDisplayTime(train, tableType)}
|
{getDisplayTime(train, tableType)}
|
||||||
</Box>
|
</Box>
|
||||||
<Box color={delay && delay !== "00:00:00" ? "#e86d2b" : "white"}
|
<Box color={delayed ? "#e86d2b" : "white"}
|
||||||
fontWeight={delay && delay !== "00:00:00" ? "bold" : ""}>
|
fontWeight={delayed ? "bold" : ""}>
|
||||||
{prettyDelay}
|
{prettyDelay}
|
||||||
</Box>
|
</Box>
|
||||||
<Box color={scheduleRelationshipColor} fontWeight="bold">
|
|
||||||
{prettyScheduleRelationship}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Box style={{textDecoration: canceled ? 'line-through': ''}}>
|
<Box style={{textDecoration: canceled ? 'line-through': ''}}>
|
||||||
<Typography fontSize={24} fontWeight="bold" data-stop-id={headline.id}>{headline.name}</Typography>
|
<Typography fontSize={24} fontWeight="bold" data-stop-id={headline.stopId}>{headline.name}</Typography>
|
||||||
<span className="stops">{stopsNames}</span>
|
<span className="stops">{stopsNames}</span>
|
||||||
</Box>
|
</Box>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
@ -228,12 +184,14 @@ function TrainRow({train, tableType, date, time}) {
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTrainType(train, trip, route) {
|
function getTrainType(train) {
|
||||||
switch (route.gtfs_feed) {
|
if (train.place.stopId === undefined)
|
||||||
|
return ""
|
||||||
|
switch (train.place.stopId.split('_')[0]) {
|
||||||
case "FR-SNCF-TGV":
|
case "FR-SNCF-TGV":
|
||||||
case "FR-SNCF-IC":
|
case "FR-SNCF-IC":
|
||||||
case "FR-SNCF-TER":
|
case "FR-SNCF-TER":
|
||||||
let trainType = train.stop.split("StopPoint:OCE")[1].split("-")[0]
|
let trainType = train.place.stopId.split("StopPoint:OCE")[1].split("-")[0]
|
||||||
switch (trainType) {
|
switch (trainType) {
|
||||||
case "Train TER":
|
case "Train TER":
|
||||||
return "TER"
|
return "TER"
|
||||||
|
@ -246,7 +204,7 @@ function getTrainType(train, trip, route) {
|
||||||
}
|
}
|
||||||
case "FR-IDF-IDFM":
|
case "FR-IDF-IDFM":
|
||||||
case "FR-GES-CTS":
|
case "FR-GES-CTS":
|
||||||
return route.short_name
|
return "A"
|
||||||
case "FR-EUROSTAR":
|
case "FR-EUROSTAR":
|
||||||
return "Eurostar"
|
return "Eurostar"
|
||||||
case "IT-FRA-TI":
|
case "IT-FRA-TI":
|
||||||
|
@ -254,13 +212,13 @@ function getTrainType(train, trip, route) {
|
||||||
case "ES-RENFE":
|
case "ES-RENFE":
|
||||||
return "RENFE"
|
return "RENFE"
|
||||||
case "AT-OBB":
|
case "AT-OBB":
|
||||||
if (trip.short_name?.startsWith("NJ"))
|
if (train.routeShortName?.startsWith("NJ"))
|
||||||
return "NJ"
|
return "NJ"
|
||||||
return "ÖBB"
|
return "ÖBB"
|
||||||
case "CH-ALL":
|
case "CH-ALL":
|
||||||
return route.desc
|
return "A"
|
||||||
default:
|
default:
|
||||||
return trip.short_name?.split(" ")[0]
|
return train.routeShortName?.split(" ")[0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,8 +252,8 @@ function getTrainTypeDisplay(trainType) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBackgroundColor(train, trip, route) {
|
function getBackgroundColor(train) {
|
||||||
let trainType = getTrainType(train, trip, route)
|
let trainType = getTrainType(train)
|
||||||
switch (trainType) {
|
switch (trainType) {
|
||||||
case "OUIGO":
|
case "OUIGO":
|
||||||
return "#0096CA"
|
return "#0096CA"
|
||||||
|
@ -304,17 +262,17 @@ function getBackgroundColor(train, trip, route) {
|
||||||
case "NJ":
|
case "NJ":
|
||||||
return "#272759"
|
return "#272759"
|
||||||
default:
|
default:
|
||||||
if (route.color)
|
if (train.routeColor)
|
||||||
return `#${route.color}`
|
return `#${train.routeColor}`
|
||||||
return "#FFFFFF"
|
return "#FFFFFF"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTextColor(train, trip, route) {
|
function getTextColor(train) {
|
||||||
if (route.text_color)
|
if (train.routeTextColor)
|
||||||
return `#${route.text_color}`
|
return `#${train.routeTextColor}`
|
||||||
else {
|
else {
|
||||||
let trainType = getTrainType(train, trip, route)
|
let trainType = getTrainType(train)
|
||||||
switch (trainType) {
|
switch (trainType) {
|
||||||
case "OUIGO":
|
case "OUIGO":
|
||||||
return "#FFFFFF"
|
return "#FFFFFF"
|
||||||
|
@ -332,33 +290,21 @@ function getTextColor(train, trip, route) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDisplayTime(train, tableType) {
|
function getDisplayTime(train, tableType) {
|
||||||
let time = tableType === "departures" ? train.departure_time : train.arrival_time
|
dayjs.locale('fr')
|
||||||
let day_split = time.split(' ')
|
let time = tableType === "departures" ? train.place.scheduledDeparture : train.place.scheduledArrival
|
||||||
return day_split[day_split.length - 1].substring(0, 5)
|
return dayjs(time).format('LT')
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPrettyDelay(delay) {
|
function getPrettyDelay(train, tableType) {
|
||||||
let delay_split = delay.split(':')
|
if (train === undefined || !train.realTime) {
|
||||||
let hours = parseInt(delay_split[0])
|
return [false, ""]
|
||||||
let minutes = parseInt(delay_split[1])
|
|
||||||
let full_minutes = hours * 60 + minutes
|
|
||||||
return full_minutes ? `+${full_minutes} min` : "À l'heure"
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPrettyScheduleRelationship(tripScheduledRelationship, stopScheduledRelationship) {
|
|
||||||
switch (tripScheduledRelationship) {
|
|
||||||
case 1:
|
|
||||||
return ["Ajouté", "#3ebb18"]
|
|
||||||
case 3:
|
|
||||||
return ["Supprimé", "#ff8701"]
|
|
||||||
default:
|
|
||||||
switch (stopScheduledRelationship) {
|
|
||||||
case 1:
|
|
||||||
return ["Supprimé", "#ff8701"]
|
|
||||||
default:
|
|
||||||
return ["", ""]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
const [scheduled, projected] = tableType === "departures" ? [train.place.scheduledDeparture, train.place.departure]
|
||||||
|
: [train.place.scheduledArrival, train.place.arrival]
|
||||||
|
const delay_minutes = dayjs(projected).diff(dayjs(scheduled), "minute")
|
||||||
|
if (delay_minutes === 0)
|
||||||
|
return [false, "À l'heure"]
|
||||||
|
return [true, `+${delay_minutes} min`]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TrainsTable;
|
export default TrainsTable;
|
|
@ -1,4 +1,4 @@
|
||||||
import React, {useMemo} from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
import reportWebVitals from './reportWebVitals';
|
import reportWebVitals from './reportWebVitals';
|
||||||
|
|
Loading…
Reference in New Issue