161 lines
5.6 KiB
JavaScript
161 lines
5.6 KiB
JavaScript
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); |