115 lines
3.9 KiB
HTML
115 lines
3.9 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Odjezdová tabule</title>
|
|
<style>
|
|
|
|
:root {
|
|
--site-bg: #1C1C1C;
|
|
--site-alt-bg: #272727;
|
|
}
|
|
body {background-color: var(--site-bg); color: #fffd; margin: 0; margin-top: 35px; font-family: sans-serif; box-sizing: border-box;}
|
|
|
|
.container {max-width: 700px; padding: 25px; margin: auto;}
|
|
.departure-grid {display: grid; grid-template-columns: 30px 1fr max-content max-content; gap: 10px 20px; line-height: 31px;}
|
|
|
|
.header {line-height: 100%; opacity: .5; margin-bottom: 10px; font-size: 90%;}
|
|
|
|
.line {background-color: var(--site-alt-bg); border-radius: 3px; box-shadow: 0 0 5px 0 #0004; text-align: center; font-weight: 700; width: 30px; height: 30px; color: #fff; text-shadow: 0 0 15px #000;}
|
|
.last-stop {font-weight: 700;}
|
|
.departure {text-align: right;}
|
|
.delay {text-align: right; color: #ff6e6e; font-size: 80%;}
|
|
|
|
.line.type1 {background-color: #F0BE32;}
|
|
.line.type2 {background-color: #1E9641;}
|
|
.line.type3 {background-color: #CD2837;}
|
|
|
|
h3 {color: #fff;}
|
|
|
|
.nav {position: fixed; top: 0; left: 0; width: 100%; z-index: 10;}
|
|
.nav .inner {background: linear-gradient(to bottom, var(--site-bg) 70%, transparent 100%); padding: 5px 25px; margin: auto; max-width: 700px; padding-bottom: 25px; transition: padding .1s;}
|
|
.nav.top .inner {padding-bottom: 0px;}
|
|
.nav .inner::after {content: ""; position: fixed; bottom: 0; left: 0; height: 20px; width: 100%; background: linear-gradient(to top, var(--site-bg) 0%, transparent 100%)}
|
|
|
|
</style>
|
|
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
|
|
</head>
|
|
<body>
|
|
<div class="container" id="app">
|
|
<div class="nav" :class="{'top': top == 0}">
|
|
<div class="inner" v-if="stop">
|
|
<h3>{{ stop.name }}</h3>
|
|
</div>
|
|
</div>
|
|
<div class="departure-grid">
|
|
<div class="header">spoj</div>
|
|
<div class="header">poslední zastávka</div>
|
|
<div class="header">zpoždění</div>
|
|
<div class="header">odjezd</div>
|
|
<template v-for="d in departures">
|
|
<template v-if="d.departure > -0.7">
|
|
<div class="line" :class="'type'+d.type">{{ d.line }}</div>
|
|
<div class="last-stop">{{ d.last_stop }}</div>
|
|
<div class="delay">{{ d.delay == 0 ? '' : '+'+d.delay }}</div>
|
|
<div class="departure">{{ d.departure < 1 ? '<1' : Math.floor(d.departure) }}</div>
|
|
</template>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
const { createApp } = Vue;
|
|
let app = createApp({
|
|
data() {
|
|
return {
|
|
top: 0,
|
|
interval: null,
|
|
stop: null,
|
|
stops: [],
|
|
departures: []
|
|
}
|
|
},
|
|
methods: {
|
|
async update() {
|
|
if(app.$data.stop) app.$data.departures = (await api("/departures/"+app.$data.stop.id)).departures;
|
|
},
|
|
async setup() {
|
|
app.$data.stops = (await api("/stops")).stops;
|
|
if(app.$data.stops.length < 1) {
|
|
alert("Žádné zastávky nejsou k dispozici!");
|
|
if(app.$data.interval) clearTimeout(app.$data.interval);
|
|
return;
|
|
}
|
|
if(localStorage.getItem("favstop")) {
|
|
app.$data.stops.forEach(stop => {
|
|
if(stop.id == localStorage.getItem("favstop")) app.$data.stop = stop;
|
|
});
|
|
}
|
|
if(!app.$data.stop) app.$data.stop = app.$data.stops[0];
|
|
window.addEventListener("scroll", () => {
|
|
app.$data.top = document.querySelector('html').scrollTop;
|
|
});
|
|
app.$data.interval = setInterval(app.update, 5000);
|
|
app.update();
|
|
}
|
|
}
|
|
}).mount('#app');
|
|
async function api(url) {
|
|
return new Promise(function(resolve, reject) {
|
|
var xhr = new XMLHttpRequest();
|
|
xhr.onreadystatechange = function() {
|
|
if(this.readyState !== 4) return;
|
|
if(!this.responseText) reject(this);
|
|
try {
|
|
resolve(JSON.parse(this.responseText));
|
|
} catch(e) {
|
|
resolve(null);
|
|
}
|
|
};
|
|
xhr.open("GET", url, true);
|
|
xhr.send();
|
|
});
|
|
}
|
|
app.setup();
|
|
</script>
|
|
</body>
|
|
</html> |