added search bar + platform select + refresh btn

This commit is contained in:
Louis Heredero 2024-04-10 18:53:16 +02:00
parent acb585b47a
commit 8cc2c7b019
Signed by: HEL
GPG Key ID: 8D83DE470F8544E7
3 changed files with 256 additions and 9 deletions

151
index.css
View File

@ -10,8 +10,11 @@
:root {
--blue: #2D327D;
--granite: #686868;
--graphite: #B7B7B7;
--cloud: #E5E5E5;
--white: #FFFFFF;
--black: #000000;
--red: #EB0000;
--red125: #C60018;
--red150: #A20013;
@ -35,7 +38,48 @@ body {
}
#station {
color: black;
display: flex;
gap: 1em;
align-items: flex-end;
color: var(--black);
margin: 1em 0;
}
#refresh {
width: 3.4em;
height: 3.4em;
cursor: pointer;
position: relative;
background-color: var(--white);
border: none;
transition: background-color 0.2s;
}
#refresh::after {
content: "";
position: absolute;
inset: 0;
width: 100%;
height: 100%;
background-color: var(--granite);
mask-image: url(icons/arrows-circle-medium.svg);
-webkit-mask-image: url(icons/arrows-circle-medium.svg);
mask-size: contain;
-webkit-mask-size: contain;
mask-position: center;
-webkit-mask-position: center;
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
transition: transform 0.2s;
will-change: transform;
}
#refresh:hover {
background-color: var(--cloud);
}
#refresh:hover::after {
transform: rotate(90deg);
}
#grid {
@ -211,3 +255,108 @@ body {
mask-position: center;
-webkit-mask-position: center;
}
#search {
display: flex;
gap: 0.5em;
}
#search-input {
font-family: inherit;
font-size: 80%;
padding: 6px 8px 6px 8px;
border: solid var(--graphite) 1px;
}
#search-input:focus-visible {
outline: none;
border-color: var(--granite);
}
#search-btn {
font-family: inherit;
font-size: 80%;
padding: 11px 40px 11px 40px;
background-color: var(--red);
color: var(--white);
border: none;
cursor: pointer;
}
#search-btn:hover {
background-color: var(--red125);
}
#stations {
display: flex;
flex-direction: column;
}
#stations .station {
padding: 0.5em 2em;
border-bottom: solid var(--graphite) 1px;
cursor: pointer;
color: var(--black);
}
#stations .station:last-child {
border-bottom: none;
}
#stations .station:hover {
background-color: var(--cloud);
}
.select-wrapper {
position: relative;
width: 10em;
}
.select-wrapper select {
font-family: inherit;
font-size: inherit;
background-color: var(--white);
border: solid var(--graphite) 1px;
border-radius: 0;
padding: 11px 40px 11px 40px;
color: var(--granite);
text-align: left;
appearance: none;
-webkit-appearance: none;
width: 100%;
cursor: pointer;
}
.select-wrapper .select-arrow {
width: 2em;
height: 100%;
position: absolute;
right: 0;
background-color: var(--granite);
mask-image: url(icons/chevron-small-down-medium.svg);
-webkit-mask-image: url(icons/chevron-small-down-medium.svg);
mask-size: contain;
-webkit-mask-size: contain;
mask-position: center;
-webkit-mask-position: center;
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
pointer-events: none;
}
.select-wrapper select:focus-visible {
outline: none;
border-color: var(--granite);
}
.field {
display: flex;
flex-direction: column;
gap: 0.2em;
}
.field label {
font-family: inherit;
font-size: 80%;
color: var(--granite);
padding-left: 0.5em;
}

View File

@ -15,7 +15,22 @@
<div class="services"></div>
</div>
</div>
<h1 id="station">St-Maurice</h1>
<form id="search">
<input type="text" id="search-input" placeholder="Station...">
<button id="search-btn">Search</button>
</form>
<div id="stations"></div>
<div id="station">
<h1 class="name">St-Maurice</h1>
<div class="field">
<label for="platforms">Platform</label>
<div class="select-wrapper">
<select id="platforms"></select>
<span class="select-arrow"></span>
</div>
</div>
<button id="refresh"></button>
</div>
<div id="grid">
<div id="type-time">
<img id="train-type" src="icons/ic-61.svg" alt="InterCity 61">

View File

@ -1,12 +1,93 @@
const MAX_DISPLAYED_VIAS = 4
let currentBpuic = null
let currentPlatform = null
let currentInfo = null
function initSearch() {
const sInput = document.getElementById("search-input")
const form = document.getElementById("search")
const refresh = document.getElementById("refresh")
const platforms = document.getElementById("platforms")
form.addEventListener("submit", e => {
e.preventDefault()
searchStation(sInput.value)
.then(stations => updateStationsList(stations))
})
refresh.addEventListener("click", () => {
if (currentBpuic !== null) {
setStation(currentBpuic)
}
})
platforms.addEventListener("change", () => {
setPlatform(platforms.value)
})
}
function updateStationsList(stations) {
const stationsList = document.getElementById("stations")
stationsList.innerHTML = ""
stations.forEach(station => {
const div = document.createElement("div")
div.classList.add("station")
div.innerText = station.bezeichnungOffiziell
div.addEventListener("click", () => setStation(station.bpuic))
stationsList.appendChild(div)
})
}
function setStation(bpuic) {
if (bpuic !== currentBpuic) {
currentPlatform = null
}
currentBpuic = bpuic
fetchInfo(bpuic).then(res => {
currentInfo = res
document.getElementById("search-input").value = ""
document.getElementById("stations").innerHTML = ""
const platformsList = document.getElementById("platforms")
platformsList.innerHTML = ""
let platforms = res.contents[0].verkehrsmittels.map(train => train.gleisAbIst)
platforms = [... new Set(platforms)]
platforms = platforms.sort()
platforms.forEach(platform => {
const opt = document.createElement("option")
opt.value = platform
opt.innerText = platform
if (currentPlatform === platform) {
opt.selected = true
}
platformsList.appendChild(opt)
})
const station = document.getElementById("station")
station.querySelector(".name").innerText = res.contents[0].betriebspunkt.bezeichnungOffiziell
updateDisplay(res, 0, currentPlatform)
})
}
function setPlatform(platform) {
const platforms = document.getElementById("platforms")
currentPlatform = platforms.value
if (currentInfo === null) return
updateDisplay(currentInfo, 0, platform)
}
function searchStation(query) {
return fetch(`https://displays.api.sbb.ch/internal/api/v1/betriebspunkt?query=${query}`, {
headers: {
"X-API-Key": API_KEY
}
}).then(res => {
return res.json()
}).then(async (res) => {
let stations = []
if (res.status === 200) {
stations = await res.json()
}
return stations
})
}
@ -47,8 +128,8 @@ const example = {
},
zeitAbKb: "2024-04-08T18:32:00", // heure de départ prévue
zeitAbErw: "2024-04-08T18:33:00", // heure de départ réelle
gleisAbKb: 1, // voie prévue
gleisAbIst: 1, // voie réelle
gleisAbKb: "1", // voie prévue
gleisAbIst: "1", // voie réelle
verspaetungsminutenAb: 0, // au moins n minutes de retard
verspaetungsminutenAn: 0, // au plus n minutes de retard
ziele: [
@ -204,8 +285,6 @@ function buildComposition(formation) {
}
function updateDisplay(result, idx=0, platform=null) {
document.getElementById("station").innerText = result.config.stationName
let trains = result.contents[0].verkehrsmittels
if (platform !== null) {
trains = trains.filter(t => t.gleisAbIst === platform)
@ -236,3 +315,7 @@ function updateDisplay(result, idx=0, platform=null) {
buildComposition(train.formation)
}
window.addEventListener("load", () => {
initSearch()
})