Visual prototype to filter routes
This commit is contained in:
26
trainvel-front/package-lock.json
generated
26
trainvel-front/package-lock.json
generated
@ -10,6 +10,7 @@
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.11.3",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@mui/icons-material": "^5.15.17",
|
||||
"@mui/material": "^5.15.6",
|
||||
"@mui/x-date-pickers": "^6.19.2",
|
||||
"@tanstack/query-sync-storage-persister": "^5.18.0",
|
||||
@ -3476,6 +3477,31 @@
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/icons-material": {
|
||||
"version": "5.15.17",
|
||||
"resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.17.tgz",
|
||||
"integrity": "sha512-xVzl2De7IY36s/keHX45YMiCpsIx3mNv2xwDgtBkRSnZQtVk+Gqufwj1ktUxEyjzEhBl0+PiNJqYC31C+n1n6A==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@mui/material": "^5.0.0",
|
||||
"@types/react": "^17.0.0 || ^18.0.0",
|
||||
"react": "^17.0.0 || ^18.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/material": {
|
||||
"version": "5.15.6",
|
||||
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.6.tgz",
|
||||
|
@ -5,6 +5,7 @@
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.11.3",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@mui/icons-material": "^5.15.17",
|
||||
"@mui/material": "^5.15.6",
|
||||
"@mui/x-date-pickers": "^6.19.2",
|
||||
"@tanstack/query-sync-storage-persister": "^5.18.0",
|
||||
|
@ -1,5 +1,6 @@
|
||||
import {useNavigate, useParams, useSearchParams} from "react-router-dom"
|
||||
import TrainsTable from "./TrainsTable"
|
||||
import TripsFilter from "./TripsFilter"
|
||||
import {useState} from "react";
|
||||
import {Box, Button, FormLabel} from "@mui/material";
|
||||
import {DatePicker, TimePicker} from "@mui/x-date-pickers";
|
||||
@ -67,6 +68,7 @@ function Station() {
|
||||
|
||||
<main>
|
||||
<DateTimeSelector station={station} date={date} time={time} />
|
||||
<TripsFilter />
|
||||
<TrainsTable station={station} date={date} time={time} tableType="departures" />
|
||||
<TrainsTable station={station} date={date} time={time} tableType="arrivals" />
|
||||
</main>
|
||||
|
@ -257,6 +257,8 @@ function getTrainType(train, trip, route) {
|
||||
if (trip.short_name?.startsWith("NJ"))
|
||||
return "NJ"
|
||||
return "ÖBB"
|
||||
case "CH-ALL":
|
||||
return route.desc
|
||||
default:
|
||||
return trip.short_name?.split(" ")[0]
|
||||
}
|
||||
|
165
trainvel-front/src/TripsFilter.js
Normal file
165
trainvel-front/src/TripsFilter.js
Normal file
@ -0,0 +1,165 @@
|
||||
import {useState} from "react"
|
||||
import {
|
||||
Box, Button,
|
||||
Checkbox, Chip, FormControl,
|
||||
FormControlLabel,
|
||||
InputLabel, MenuItem, OutlinedInput, Select
|
||||
} from "@mui/material"
|
||||
import DirectionsBusTwoToneIcon from '@mui/icons-material/DirectionsBusTwoTone'
|
||||
import SubwayTwoToneIcon from '@mui/icons-material/SubwayTwoTone'
|
||||
import TrainTwoToneIcon from '@mui/icons-material/TrainTwoTone'
|
||||
import TramTwoToneIcon from '@mui/icons-material/TramTwoTone'
|
||||
|
||||
function TripsFilter() {
|
||||
const [transportModeFilter, setTransportModeFilter] = useState(
|
||||
{longDistanceTrain: true, regionalTrain: true, metro: true, tram: true, bus: true})
|
||||
const transportModeNames = {
|
||||
train: "Trains",
|
||||
longDistanceTrain: "Trains longue distance",
|
||||
regionalTrain: "Trains régionaux",
|
||||
metro: "Métro",
|
||||
tram: "Tram",
|
||||
bus: "Bus",
|
||||
}
|
||||
|
||||
const trainCheckbox = <>
|
||||
<TrainTwoToneIcon />
|
||||
<Checkbox
|
||||
checked={transportModeFilter.longDistanceTrain && transportModeFilter.regionalTrain}
|
||||
indeterminate={transportModeFilter.longDistanceTrain !== transportModeFilter.regionalTrain}
|
||||
onChange={(event) =>
|
||||
setTransportModeFilter(
|
||||
{...transportModeFilter, longDistanceTrain: event.target.checked, regionalTrain: event.target.checked})}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
/>
|
||||
</>
|
||||
|
||||
const longDistanceTrainCheckbox = <>
|
||||
<TrainTwoToneIcon />
|
||||
<Checkbox
|
||||
checked={transportModeFilter.longDistanceTrain}
|
||||
onChange={(event) =>
|
||||
setTransportModeFilter({...transportModeFilter, longDistanceTrain: event.target.checked})} />
|
||||
</>
|
||||
|
||||
const regionalTrainCheckbox = <>
|
||||
<TrainTwoToneIcon />
|
||||
<Checkbox
|
||||
checked={transportModeFilter.regionalTrain}
|
||||
onChange={(event) =>
|
||||
setTransportModeFilter({...transportModeFilter, regionalTrain: event.target.checked})} />
|
||||
</>
|
||||
|
||||
const metroCheckbox = <>
|
||||
<SubwayTwoToneIcon />
|
||||
<Checkbox
|
||||
checked={transportModeFilter.metro}
|
||||
onChange={(event) =>
|
||||
setTransportModeFilter({...transportModeFilter, metro: event.target.checked})} />
|
||||
</>
|
||||
|
||||
const tramCheckbox = <>
|
||||
<TramTwoToneIcon />
|
||||
<Checkbox
|
||||
checked={transportModeFilter.tram}
|
||||
onChange={(event) =>
|
||||
setTransportModeFilter({...transportModeFilter, tram: event.target.checked})} />
|
||||
</>
|
||||
|
||||
const busCheckbox = <>
|
||||
<DirectionsBusTwoToneIcon />
|
||||
<Checkbox
|
||||
checked={transportModeFilter.bus}
|
||||
onChange={(event) =>
|
||||
setTransportModeFilter({...transportModeFilter, bus: event.target.checked})} />
|
||||
</>
|
||||
|
||||
// TODO Fetch routes that are accessible from one stop
|
||||
// For now, we have the tram and bus routes accessible in Strasbourg main station
|
||||
const routesList = [
|
||||
{name: "Tous"},
|
||||
{name: "A", bgColor: "#E10D19", color: "#FFFFFF"},
|
||||
{name: "C", bgColor: "#F29400", color: "#FFFFFF"},
|
||||
{name: "D", bgColor: "#009933", color: "#FFFFFF"},
|
||||
{name: "G", bgColor: "#F6C900", color: "#000000"},
|
||||
{name: "H", bgColor: "#A62341", color: "#FFFFFF"},
|
||||
{name: "2", bgColor: "#FF0000", color: "#FFFFFF"},
|
||||
{name: "10", bgColor: "#FFAA00", color: "#000000"},
|
||||
]
|
||||
const routesDict = {}
|
||||
for (const route of routesList) {
|
||||
routesDict[route.name] = route
|
||||
}
|
||||
|
||||
const [selectedRoutes, setSelectedRoutes] = useState(["Tous"])
|
||||
|
||||
return <>
|
||||
<h2>Filtres</h2>
|
||||
<Box display="flex" alignItems="center" sx={{mb: 3}}>
|
||||
<FormControl>
|
||||
<InputLabel>Mode de transport</InputLabel>
|
||||
<Select
|
||||
multiple
|
||||
value={selectedRoutes}
|
||||
input={<OutlinedInput id="select-multiple-chip" label="Lignes" />}
|
||||
renderValue={(selected) => (
|
||||
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>
|
||||
{Object.keys(transportModeFilter).filter(key => transportModeFilter[key]).map((filterType) => (
|
||||
<Chip key={filterType} label={transportModeNames[filterType]} sx={{fontWeight: "bold"}} />
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
>
|
||||
<MenuItem key="train" value="train">
|
||||
<FormControlLabel label={transportModeNames["train"]} control={trainCheckbox} />
|
||||
</MenuItem>
|
||||
<MenuItem key="longDistanceTrain" value="longDistanceTrain">
|
||||
<FormControlLabel label={transportModeNames["longDistanceTrain"]} sx={{pl: 4}} control={longDistanceTrainCheckbox} />
|
||||
</MenuItem>
|
||||
<MenuItem key="regionalTrain" value="regionalTrain">
|
||||
<FormControlLabel label={transportModeNames["regionalTrain"]} sx={{pl: 4}} control={regionalTrainCheckbox} />
|
||||
</MenuItem>
|
||||
<MenuItem key="metro" value="metro">
|
||||
<FormControlLabel label={transportModeNames["metro"]} control={metroCheckbox} />
|
||||
</MenuItem>
|
||||
<MenuItem key="tram" value="tram">
|
||||
<FormControlLabel label={transportModeNames["tram"]} control={tramCheckbox} />
|
||||
</MenuItem>
|
||||
<MenuItem key="bus" value="bus">
|
||||
<FormControlLabel label={transportModeNames["bus"]} control={busCheckbox} />
|
||||
</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormControl>
|
||||
<InputLabel>Ligne</InputLabel>
|
||||
<Select
|
||||
multiple
|
||||
value={selectedRoutes}
|
||||
onChange={(event) => setSelectedRoutes(event.target.value)}
|
||||
input={<OutlinedInput id="select-multiple-chip" label="Lignes" />}
|
||||
renderValue={(selected) => (
|
||||
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>
|
||||
{selected.map(routeName => routesDict[routeName]).map((route) => (
|
||||
<Chip key={route.name} label={route.name} sx={{backgroundColor: route.bgColor, color: route.color, fontWeight: "bold"}} />
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
>
|
||||
{routesList.map((route) =>
|
||||
<MenuItem key={route.name} value={route.name}>
|
||||
<Checkbox checked={selectedRoutes.includes(route.name)} />
|
||||
<Chip label={route.name} sx={{backgroundColor: route.bgColor, color: route.color, fontWeight: "bold"}} />
|
||||
</MenuItem>
|
||||
)}
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<Button>
|
||||
Filtrer
|
||||
</Button>
|
||||
</Box>
|
||||
</>
|
||||
}
|
||||
|
||||
export default TripsFilter
|
Reference in New Issue
Block a user