Files
2026-06-13 23:42:04 +02:00

161 lines
5.6 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { getNextPassage } from "../tcl.js";
const LAST_PASSAGE_WARNING_THREASHOLD_MS = 30*60*1000;
const TEMPLATE = document.createElement("template");
TEMPLATE.innerHTML = `
<img class="line-picto" src="" />
<h1>
<span>vers <span class="line-name"></span></span>
<small class="stop-name"></small>
</h1>
<p class="next-passage">
Prochain passage <span class="stop-passage-time-relative"></span>
(<time class="stop-passage-time"></time>)
</p>
<p class="last-passage">
<span class="next-and-last" >Prochain et </span>Dernier passage <span class="last-passage-time-relative"></span>
(<time class="last-passage-time"></time>)
</p>
`
class NextBusElement extends HTMLElement {
#stop
#autoupdateTimeout
get stopId(){
return this.#stop
}
set stopId(value){
this.#stop = value
}
handleAutoUpdate(){
clearTimeout(this.#autoupdateTimeout)
this.updateContent()
this.#autoupdateTimeout = setTimeout(this.handleAutoUpdate.bind(this), 60000 + ((Math.random() * 10000) - 5000))
}
connectedCallback(){
this.replaceChildren(TEMPLATE.content.cloneNode(true))
this.handleAutoUpdate()
}
async updateContent(){
try {
let nextPassage = await getNextPassage(this.stopId)
let time = nextPassage.time
if(!time){
time = nextPassage.line.timetable.find(it => it.time.getTime() > Date.now())?.time
}
if(!time){
return
}
this.querySelector(".line-picto").src = nextPassage.line.picto
this.querySelector(".line-name").textContent = nextPassage.line.displayName
this.querySelector(".stop-name").textContent = nextPassage.displayName
let timeFormatter = new Intl.DateTimeFormat("fr-FR", {
timeStyle: "short"
});
let timeEl = this.querySelector(".stop-passage-time")
timeEl.textContent = timeFormatter.format(time)
let relativeTimeFOrmatter = new Intl.RelativeTimeFormat("fr-FR", {
style: "short",
numeric: "auto"
});
let time_minutes = Math.floor((time.getTime() - Date.now()) / 60000)
let relative_time_str;
if(time_minutes > 60) {
let time_hours = Math.floor(time_minutes / 60)
time_minutes -= time_hours * 60
relative_time_str = relativeTimeFOrmatter.format(
time_hours,
"hours"
)
if(time_minutes > 0){
relative_time_str += ` et ${Math.abs(time_minutes)} min`
}
} else {
relative_time_str = relativeTimeFOrmatter.format(
time_minutes,
"minutes"
)
}
this.querySelector(".stop-passage-time-relative").textContent = relative_time_str
{
let last_passage = nextPassage.getLastPassageTime()
let next_passage_time = time;
if(last_passage){
let time = last_passage.time
if(next_passage_time.getTime() > time.getTime()){
time = next_passage_time
}
let timeEl = this.querySelector(".last-passage-time")
timeEl.textContent = timeFormatter.format(time)
let time_minutes = Math.floor((time.getTime() - Date.now()) / 60000)
let relative_time_str;
if(time_minutes > 60) {
let time_hours = Math.floor(time_minutes / 60)
time_minutes -= time_hours * 60
relative_time_str = relativeTimeFOrmatter.format(
time_hours,
"hours"
)
if(time_minutes > 0){
relative_time_str += ` et ${Math.abs(time_minutes)} min`
}
} else {
relative_time_str = relativeTimeFOrmatter.format(
time_minutes,
"minutes"
)
}
this.querySelector(".last-passage-time-relative").textContent = relative_time_str
this.querySelector(".last-passage").style.display = ""
this.querySelector(".last-passage").classList.toggle("warning", (time.getTime() - Date.now()) <= LAST_PASSAGE_WARNING_THREASHOLD_MS)
} else {
this.querySelector(".last-passage").style.display = "none"
}
if(last_passage && last_passage.time.getTime() <= time.getTime()){
this.querySelector(".next-and-last").style.display = ""
this.querySelector(".next-passage").style.display = "none"
} else {
this.querySelector(".next-and-last").style.display = "none"
this.querySelector(".next-passage").style.display = ""
}
}
this.style.display = ""
} catch(e){
this.style.display = "none"
throw e
}
}
static observedAttributes = ["stop-id"]
attributeChangedCallback(name, oldVal, newVal){
switch(name){
case "stop-id":
this.stopId = newVal
break;
}
}
}
customElements.define("gavle-next-bus", NextBusElement);