mirror of
https://github.com/Spythere/stacjownik.git
synced 2026-05-03 05:18:11 +00:00
Schedule indicatory
This commit is contained in:
@@ -1,329 +1,386 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="train-schedule" @click="toggleShowState">
|
<div class="train-schedule" @click="toggleShowState">
|
||||||
<div class="schedule-wrapper">
|
<div class="schedule-wrapper">
|
||||||
<ul class="stop_list">
|
<ul class="stop_list">
|
||||||
<li
|
<li
|
||||||
v-for="(stop, i) in followingStops"
|
v-for="(stop, i) in followingStops"
|
||||||
:key="i"
|
:key="i"
|
||||||
:class="addClasses(stop, i)"
|
:class="addClasses(stop, i)"
|
||||||
>
|
>
|
||||||
<span class="stop_info">
|
<span class="stop_info">
|
||||||
<div class="indicator"></div>
|
<div class="indicator"></div>
|
||||||
|
|
||||||
<div class="progress-bar"></div>
|
<div class="progress-bar"></div>
|
||||||
|
|
||||||
<div class="stop-bar"></div>
|
<div class="stop-bar"></div>
|
||||||
|
|
||||||
<span class="distance" v-if="stop.stopDistance">
|
<span class="distance" v-if="stop.stopDistance">
|
||||||
{{ Math.floor(stop.stopDistance) }}
|
{{ Math.floor(stop.stopDistance) }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span class="stop-name" v-html="stop.stopName"></span>
|
<span class="stop-name" v-html="stop.stopName"></span>
|
||||||
<span class="stop-date">
|
<span class="stop-date">
|
||||||
<span
|
<span
|
||||||
class="date arrival"
|
class="date arrival"
|
||||||
v-if="!stop.beginsHere"
|
v-if="!stop.beginsHere"
|
||||||
:class="{
|
:class="{
|
||||||
delayed: stop.arrivalDelay > 0 && stop.confirmed,
|
delayed: stop.arrivalDelay > 0 && stop.confirmed,
|
||||||
preponed: stop.arrivalDelay < 0 && stop.confirmed,
|
preponed: stop.arrivalDelay < 0 && stop.confirmed,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
p.
|
p.
|
||||||
{{
|
{{
|
||||||
stylizeTime(
|
stylizeTime(
|
||||||
stop.confirmed
|
stop.confirmed
|
||||||
? stop.arrivalRealTimeString || ""
|
? stop.arrivalRealTimeString || ""
|
||||||
: stop.arrivalTimeString || "",
|
: stop.arrivalTimeString || "",
|
||||||
stop.arrivalDelay,
|
stop.arrivalDelay,
|
||||||
stop.confirmed
|
stop.confirmed
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span
|
<span
|
||||||
class="date stop"
|
class="date stop"
|
||||||
v-if="stop.stopTime"
|
v-if="stop.stopTime"
|
||||||
:class="stop.stopType.replace(', ', '-')"
|
:class="stop.stopType.replace(', ', '-')"
|
||||||
>
|
>
|
||||||
{{ stop.stopTime }} {{ stop.stopType }}
|
{{ stop.stopTime }} {{ stop.stopType }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span
|
<span
|
||||||
class="date departure"
|
class="date departure"
|
||||||
v-if="!stop.terminatesHere && stop.stopTime != 0"
|
v-if="!stop.terminatesHere && stop.stopTime != 0"
|
||||||
:class="{
|
:class="{
|
||||||
delayed: stop.departureDelay > 0 && stop.confirmed,
|
delayed: stop.departureDelay > 0 && stop.confirmed,
|
||||||
preponed: stop.departureDelay < 0 && stop.confirmed,
|
preponed: stop.departureDelay < 0 && stop.confirmed,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
o.
|
o.
|
||||||
{{
|
{{
|
||||||
stylizeTime(
|
stylizeTime(
|
||||||
stop.confirmed
|
stop.confirmed
|
||||||
? stop.departureRealTimeString || ""
|
? stop.departureRealTimeString || ""
|
||||||
: stop.departureTimeString || "",
|
: stop.departureTimeString || "",
|
||||||
stop.departureDelay,
|
stop.departureDelay,
|
||||||
stop.confirmed
|
stop.confirmed
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div class="stop_line">
|
<div class="stop_line">
|
||||||
<div class="progress-bar"></div>
|
<div class="progress-bar"></div>
|
||||||
|
|
||||||
<span v-if="i < followingStops.length - 1">
|
<span v-if="i < followingStops.length - 1">
|
||||||
<span
|
<span
|
||||||
v-if="stop.departureLine == followingStops[i + 1].arrivalLine"
|
v-if="stop.departureLine == followingStops[i + 1].arrivalLine"
|
||||||
>
|
>
|
||||||
{{ stop.departureLine }}
|
{{ stop.departureLine }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span v-else>
|
<span v-else>
|
||||||
{{ stop.departureLine }} /
|
{{ stop.departureLine }} /
|
||||||
{{ followingStops[i + 1].arrivalLine }}
|
{{ followingStops[i + 1].arrivalLine }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import TrainStop from "@/scripts/interfaces/TrainStop";
|
import TrainStop from "@/scripts/interfaces/TrainStop";
|
||||||
import { defineComponent } from "@vue/runtime-core";
|
import { computed, defineComponent } from "@vue/runtime-core";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
followingStops: {
|
followingStops: {
|
||||||
type: Array as () => TrainStop[],
|
type: Array as () => TrainStop[],
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
emits: ["click"],
|
emits: ["click"],
|
||||||
|
|
||||||
methods: {
|
setup(props) {
|
||||||
stylizeTime(timeString: string, delay: number, confirmed: boolean) {
|
return {
|
||||||
return (
|
lastConfirmed: computed(() => {
|
||||||
timeString +
|
return props.followingStops.findIndex(
|
||||||
(delay != 0 && confirmed
|
(stop, i, stops) =>
|
||||||
? " (" + (delay > 0 ? "+" : "") + delay.toString() + ")"
|
stop.confirmed && !stops[i + 1]?.confirmed && !stops[i + 1]?.stopped
|
||||||
: "")
|
);
|
||||||
);
|
}),
|
||||||
},
|
activeMinorStops: computed(() => {
|
||||||
|
const lastMajorConfirmed = props.followingStops.findIndex(
|
||||||
toggleShowState() {
|
(stop, i, stops) => stop.confirmed && !stops[i + 1]?.confirmed
|
||||||
this.$emit("click");
|
);
|
||||||
},
|
|
||||||
|
const activeMinorStopList: number[] = [];
|
||||||
addClasses(stop: TrainStop, index: number) {
|
if (lastMajorConfirmed + 1 >= props.followingStops.length)
|
||||||
return {
|
return activeMinorStopList;
|
||||||
confirmed: stop.confirmed,
|
|
||||||
stopped: stop.stopped,
|
for (
|
||||||
beginning: stop.beginsHere,
|
let i = lastMajorConfirmed + 1;
|
||||||
delayed: stop.departureDelay > 0,
|
i < props.followingStops.length;
|
||||||
"minor-stop":
|
i++
|
||||||
this.followingStops[index - 1]?.confirmed &&
|
) {
|
||||||
stop.stopNameRAW.includes("po"),
|
if (props.followingStops[i].stopNameRAW.includes("po."))
|
||||||
"last-confirmed":
|
activeMinorStopList.push(i);
|
||||||
stop.confirmed && !this.followingStops[index + 1]?.confirmed,
|
else break;
|
||||||
};
|
}
|
||||||
},
|
|
||||||
},
|
return activeMinorStopList;
|
||||||
});
|
}),
|
||||||
</script>
|
};
|
||||||
|
},
|
||||||
<style lang="scss" scoped>
|
|
||||||
@keyframes blink {
|
methods: {
|
||||||
from {
|
stylizeTime(timeString: string, delay: number, confirmed: boolean) {
|
||||||
background-color: white;
|
return (
|
||||||
}
|
timeString +
|
||||||
to {
|
(delay != 0 && confirmed
|
||||||
background-color: lime;
|
? " (" + (delay > 0 ? "+" : "") + delay.toString() + ")"
|
||||||
}
|
: "")
|
||||||
}
|
);
|
||||||
|
},
|
||||||
.train-schedule {
|
|
||||||
max-height: 600px;
|
toggleShowState() {
|
||||||
margin-top: 2em;
|
this.$emit("click");
|
||||||
|
},
|
||||||
overflow-y: auto;
|
|
||||||
}
|
addClasses(stop: TrainStop, index: number) {
|
||||||
|
return {
|
||||||
.schedule-wrapper {
|
confirmed: stop.confirmed,
|
||||||
margin-left: 2.5rem;
|
stopped: stop.stopped,
|
||||||
}
|
beginning: stop.beginsHere,
|
||||||
|
delayed: stop.departureDelay > 0,
|
||||||
.progress-bar {
|
[stop.stopType.replaceAll(", ", "-")]:
|
||||||
position: absolute;
|
stop.stopType.match(new RegExp("ph|pm|pt")) && !stop.confirmed,
|
||||||
|
"minor-stop-active": this.activeMinorStops.includes(index),
|
||||||
top: 0;
|
"last-confirmed": index == this.lastConfirmed,
|
||||||
left: -1rem;
|
};
|
||||||
|
},
|
||||||
transform: translateX(-1px);
|
},
|
||||||
|
});
|
||||||
height: 100%;
|
</script>
|
||||||
width: 2px;
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
background-color: white;
|
$barClr: #d4d4d4;
|
||||||
}
|
$confirmedClr: #18d818;
|
||||||
|
$stoppedClr: #ff4500;
|
||||||
ul.stop_list > li {
|
$haltClr: #48c5eb;
|
||||||
position: relative;
|
|
||||||
|
$preponedClr: #008b00;
|
||||||
display: flex;
|
$delayedClr: #e93f3f;
|
||||||
flex-direction: column;
|
$dateClr: #525151;
|
||||||
|
$stopExchangeClr: #db8e29;
|
||||||
padding: 0 0.5em;
|
$stopDefaultClr: #252525;
|
||||||
|
$stopNameClr: #22a8d1;
|
||||||
&.minor-stop {
|
|
||||||
.stop_info > .progress-bar {
|
@keyframes blink {
|
||||||
animation: 0.5s ease-in-out alternate infinite blink;
|
from {
|
||||||
}
|
background-color: $barClr;
|
||||||
|
}
|
||||||
.stop_line > .progress-bar {
|
to {
|
||||||
animation: 0.5s ease-in-out alternate infinite blink;
|
background-color: $confirmedClr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.last-confirmed {
|
.train-schedule {
|
||||||
& > .stop_line > .progress-bar {
|
max-height: 600px;
|
||||||
animation: 0.5s ease-in-out alternate infinite blink;
|
margin-top: 2em;
|
||||||
}
|
|
||||||
}
|
overflow-y: auto;
|
||||||
|
}
|
||||||
&.confirmed {
|
|
||||||
& > .stop_line > .progress-bar {
|
.schedule-wrapper {
|
||||||
background-color: lime;
|
margin-left: 2.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
& > .stop_info > .progress-bar {
|
.progress-bar {
|
||||||
background-color: lime;
|
position: absolute;
|
||||||
}
|
z-index: 10;
|
||||||
|
|
||||||
& > .stop_info > .indicator {
|
top: -1px;
|
||||||
border-color: lime;
|
/* left: -1rem; */
|
||||||
}
|
left: -17px;
|
||||||
}
|
|
||||||
|
/* transform: translate(-1px, -1px); */
|
||||||
&.stopped {
|
/* transform: translateX(-4spx, -1px); */
|
||||||
& > .stop_info {
|
|
||||||
& > .indicator {
|
height: 100%;
|
||||||
border-color: orangered;
|
width: 3px;
|
||||||
}
|
|
||||||
|
background-color: $barClr;
|
||||||
& > .stop-bar {
|
}
|
||||||
background: orangered;
|
|
||||||
}
|
ul.stop_list > li {
|
||||||
}
|
position: relative;
|
||||||
}
|
|
||||||
|
display: flex;
|
||||||
.stop_line {
|
flex-direction: column;
|
||||||
font-size: 0.8em;
|
|
||||||
color: #ccc;
|
padding: 0 0.5em;
|
||||||
|
|
||||||
padding: 0.35em 0;
|
&[class*="ph"] > .stop_info > .indicator {
|
||||||
|
border-color: $stopExchangeClr;
|
||||||
position: relative;
|
}
|
||||||
|
|
||||||
.line-segment {
|
&[class*="pt"] > .stop_info > .indicator {
|
||||||
color: white;
|
border-color: #818181;
|
||||||
font-weight: 500;
|
}
|
||||||
}
|
|
||||||
}
|
&.minor-stop-active {
|
||||||
|
.stop_info > .progress-bar {
|
||||||
.stop_info {
|
animation: 0.5s ease-in-out alternate infinite blink;
|
||||||
display: flex;
|
}
|
||||||
|
|
||||||
position: relative;
|
.stop_line > .progress-bar {
|
||||||
text-align: center;
|
animation: 0.5s ease-in-out alternate infinite blink;
|
||||||
|
}
|
||||||
padding: 0.15em 0;
|
}
|
||||||
}
|
|
||||||
|
&.last-confirmed {
|
||||||
.stop-bar {
|
.stop_line > .progress-bar {
|
||||||
position: absolute;
|
animation: 0.5s ease-in-out alternate infinite blink;
|
||||||
top: 0;
|
}
|
||||||
left: -1rem;
|
}
|
||||||
|
|
||||||
transform: translateX(-1px);
|
&.confirmed {
|
||||||
|
.stop_info {
|
||||||
z-index: 2;
|
> .progress-bar {
|
||||||
|
background-color: $confirmedClr;
|
||||||
width: 2px;
|
}
|
||||||
height: 100%;
|
|
||||||
}
|
> .indicator {
|
||||||
|
border-color: $confirmedClr;
|
||||||
.distance {
|
}
|
||||||
position: absolute;
|
}
|
||||||
|
|
||||||
top: 50%;
|
.stop_line > .progress-bar {
|
||||||
transform: translate(-100%, -50%);
|
background-color: $confirmedClr;
|
||||||
|
}
|
||||||
margin-left: -1.75rem;
|
}
|
||||||
|
|
||||||
font-size: 0.85em;
|
&.stopped {
|
||||||
color: #d6d6d6;
|
.stop_info {
|
||||||
}
|
> .indicator {
|
||||||
|
border-color: $stoppedClr;
|
||||||
.indicator {
|
}
|
||||||
position: absolute;
|
|
||||||
z-index: 3;
|
> .stop-bar {
|
||||||
|
background: $stoppedClr;
|
||||||
top: 50%;
|
}
|
||||||
left: -1rem;
|
}
|
||||||
|
}
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
|
.stop_line {
|
||||||
text-align: right;
|
font-size: 0.8em;
|
||||||
|
color: #ccc;
|
||||||
width: 15px;
|
|
||||||
height: 15px;
|
padding: 0.35em 0;
|
||||||
|
|
||||||
background: var(--clr-secondary);
|
position: relative;
|
||||||
border: 2px solid white;
|
|
||||||
border-radius: 100%;
|
.line-segment {
|
||||||
}
|
color: $barClr;
|
||||||
|
font-weight: 500;
|
||||||
.stop-name {
|
}
|
||||||
background: var(--clr-accent);
|
}
|
||||||
padding: 0.3em 0.5em;
|
|
||||||
|
.stop_info {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
|
||||||
}
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
.stop-date {
|
|
||||||
display: flex;
|
padding: 0.15em 0;
|
||||||
align-items: center;
|
}
|
||||||
|
|
||||||
.date {
|
.stop-bar {
|
||||||
background: #494949;
|
position: absolute;
|
||||||
padding: 0.3em 0.5em;
|
top: 0;
|
||||||
}
|
left: -1rem;
|
||||||
|
|
||||||
.stop {
|
transform: translate(-1px, -1px);
|
||||||
&.ph,
|
|
||||||
&.ph-pm {
|
z-index: 10;
|
||||||
background: #db8e29;
|
|
||||||
}
|
width: 3px;
|
||||||
|
height: 100%;
|
||||||
background: #252525;
|
}
|
||||||
}
|
|
||||||
|
.distance {
|
||||||
.arrival,
|
position: absolute;
|
||||||
.departure {
|
|
||||||
&.delayed {
|
top: 50%;
|
||||||
background: #f80334;
|
transform: translate(-100%, -50%);
|
||||||
}
|
|
||||||
|
margin-left: -1.75rem;
|
||||||
&.preponed {
|
|
||||||
background: rgb(0, 139, 0);
|
font-size: 0.85em;
|
||||||
}
|
color: #d6d6d6;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
.indicator {
|
||||||
</style>
|
position: absolute;
|
||||||
|
z-index: 11;
|
||||||
|
|
||||||
|
top: 50%;
|
||||||
|
left: -1rem;
|
||||||
|
|
||||||
|
transform: translate(-47%, -50%);
|
||||||
|
|
||||||
|
text-align: right;
|
||||||
|
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
|
||||||
|
background: var(--clr-secondary);
|
||||||
|
border: 3px solid $barClr;
|
||||||
|
border-radius: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stop-name {
|
||||||
|
background: $stopNameClr;
|
||||||
|
padding: 0.3em 0.5em;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stop-date {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.date {
|
||||||
|
background: $dateClr;
|
||||||
|
padding: 0.3em 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stop {
|
||||||
|
&.ph,
|
||||||
|
&.ph-pm,
|
||||||
|
&.pm {
|
||||||
|
background: $stopExchangeClr;
|
||||||
|
}
|
||||||
|
|
||||||
|
background: $stopDefaultClr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrival,
|
||||||
|
.departure {
|
||||||
|
&.delayed {
|
||||||
|
background: $delayedClr;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.preponed {
|
||||||
|
background: $preponedClr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -163,8 +163,10 @@
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
class="train_extended-info"
|
class="train_extended-info"
|
||||||
v-if="train.timetableData"
|
v-if="
|
||||||
v-show="showedSchedule == train.timetableData.timetableId"
|
train.timetableData &&
|
||||||
|
showedSchedule == train.timetableData.timetableId
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<TrainSchedule
|
<TrainSchedule
|
||||||
:followingStops="train.timetableData.followingStops"
|
:followingStops="train.timetableData.followingStops"
|
||||||
@@ -439,7 +441,7 @@ img.train-image {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
background-color: var(--clr-accent);
|
background-color: #22a8d1;
|
||||||
border-radius: 0.5em;
|
border-radius: 0.5em;
|
||||||
padding: 0.1em 0.35em;
|
padding: 0.1em 0.35em;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user