chore: journal timetable stop labels

This commit is contained in:
2024-09-02 22:39:41 +02:00
parent 631bb20c61
commit df86364c51
6 changed files with 192 additions and 75 deletions
@@ -1,25 +1,77 @@
<template> <template>
<div class="timetable-stops"> <div class="timetable-stops">
<div class="stop-list"> <ul class="stop-list">
<span <li
v-for="(stop, i) in timetableStops.filter((_, i) => v-for="(stop, i) in timetableStops.filter((_, i) =>
!showExtraInfo ? i == 0 || i == timetableStops.length - 1 : true !showExtraInfo ? i == 0 || i == timetableStops.length - 1 : true
)" )"
class="stop-list-item" class=""
:key="stop.stopName" :key="stop.stopName"
:data-confirmed="stop.confirmed"
> >
<span v-if="i > 0"> <span class="stop-label" :data-confirmed="stop.isConfirmed">
&gt; <span class="stop-name">{{ stop.stopName }}</span>
<span v-if="!showExtraInfo && i == 1 && timetableStops.length > 2">
... (+{{ timetableStops.length - 2 }}) &gt; <span
class="stop-date"
v-if="stop.scheduledArrivalTimestamp != 0"
:data-delayed="
stop.isConfirmed && stop.arrivalTimestamp - stop.scheduledArrivalTimestamp > 0
"
:data-preponed="
stop.isConfirmed &&
stop.arrivalTimestamp != 0 &&
stop.arrivalTimestamp - stop.scheduledArrivalTimestamp < 0
"
>
<span
v-if="stop.isConfirmed && stop.arrivalTimestamp - stop.scheduledArrivalTimestamp != 0"
>
p. <s>{{ timestampToString(stop.scheduledArrivalTimestamp) }}</s>
{{ timestampToString(stop.arrivalTimestamp) }}
</span>
<span v-else>p. {{ timestampToString(stop.scheduledArrivalTimestamp) }}</span>
</span>
<span
class="stop-time"
v-if="stop.stopTime > 0"
:data-stop-ph="stop.stopType.includes('ph')"
:data-stop-pt="stop.stopType.includes('pt')"
:data-stop-pm="stop.stopType.includes('pm')"
>
{{ stop.stopTime }} {{ stop.stopType }}
</span>
<span
class="stop-date"
v-if="
stop.scheduledDepartureTimestamp != 0 &&
stop.scheduledArrivalTimestamp != stop.scheduledDepartureTimestamp
"
:data-delayed="
stop.isConfirmed && stop.departureTimestamp - stop.scheduledDepartureTimestamp > 0
"
:data-preponed="
stop.isConfirmed &&
stop.departureTimestamp != 0 &&
stop.departureTimestamp - stop.scheduledDepartureTimestamp < 0
"
>
<span
v-if="
stop.isConfirmed && stop.departureTimestamp - stop.scheduledDepartureTimestamp != 0
"
>
o. <s>{{ timestampToString(stop.scheduledDepartureTimestamp) }}</s>
{{ timestampToString(stop.departureTimestamp) }}
</span>
<span v-else>o. {{ timestampToString(stop.scheduledDepartureTimestamp) }}</span>
</span> </span>
</span> </span>
</li>
<span class="stop-name">{{ stop.stopName }}</span> </ul>
<span v-html="stop.html"></span>
</span>
</div>
<div class="path-details" v-if="showExtraInfo && timetablePathDetails"> <div class="path-details" v-if="showExtraInfo && timetablePathDetails">
<span <span
@@ -29,7 +81,9 @@
i < timetablePathDetails.length - 1 && timetablePathDetails[i + 1].isVisited i < timetablePathDetails.length - 1 && timetablePathDetails[i + 1].isVisited
" "
> >
<span class="path-arrival" v-if="pathData.arrival">/ {{ pathData.arrival }} &RightArrow; </span> <span class="path-arrival" v-if="pathData.arrival">
/ {{ pathData.arrival }} &RightArrow;
</span>
<b class="path-scenery">{{ pathData.sceneryName }}</b> <b class="path-scenery">{{ pathData.sceneryName }}</b>
<span class="path-departure" v-if="pathData.departure"> <span class="path-departure" v-if="pathData.departure">
&RightArrow; {{ pathData.departure }}&nbsp; &RightArrow; {{ pathData.departure }}&nbsp;
@@ -44,6 +98,17 @@ import { PropType, defineComponent } from 'vue';
import dateMixin from '../../../mixins/dateMixin'; import dateMixin from '../../../mixins/dateMixin';
import { API } from '../../../typings/api'; import { API } from '../../../typings/api';
interface ITimetableStopDetails {
stopName: string;
arrivalTimestamp: number;
scheduledArrivalTimestamp: number;
departureTimestamp: number;
scheduledDepartureTimestamp: number;
stopTime: number;
stopType: string;
isConfirmed: boolean;
}
export default defineComponent({ export default defineComponent({
mixins: [dateMixin], mixins: [dateMixin],
@@ -78,58 +143,56 @@ export default defineComponent({
}); });
}, },
timetableStops() { timetableStops(): ITimetableStopDetails[] {
const timetable = this.timetable; const timetable = this.timetable;
const stopNames = timetable.sceneriesString.split('%'); const stopNames = timetable.sceneriesString.split('%');
const beginDateHTML = ` (o. ${ return stopNames.reduce<ITimetableStopDetails[]>((acc, stopName, i, arr) => {
timetable.beginDate != timetable.scheduledBeginDate const arrivalDate =
? `<s class="text--grayed">${this.localeTime(timetable.beginDate, this.$i18n.locale)}</s>` i == arr.length - 1
: '' ? (timetable.checkpointArrivals.at(i) ?? timetable.endDate)
} <span>${this.localeTime(timetable.scheduledBeginDate, this.$i18n.locale)}</span>)`; : timetable.checkpointArrivals.at(i);
const endDateHTML = ` (p. ${ const scheduledArrivalDate =
timetable.endDate != timetable.scheduledEndDate && timetable.fulfilled i == arr.length - 1
? `<s class="text--grayed">${this.localeTime(timetable.endDate, this.$i18n.locale)}</s>` ? (timetable.checkpointArrivalsScheduled.at(i) ?? timetable.scheduledEndDate)
: '' : timetable.checkpointArrivalsScheduled.at(i);
} <span>${this.localeTime(timetable.scheduledEndDate, this.$i18n.locale)}</span>)`;
return stopNames.map((stopName, i) => { const departureDate =
const confirmed = i < timetable.confirmedStopsCount; i == 0
if (i == 0) return { stopName, html: beginDateHTML, confirmed }; ? (timetable.checkpointDepartures.at(i) ?? timetable.beginDate)
if (i == stopNames.length - 1) return { stopName, html: endDateHTML, confirmed }; : timetable.checkpointDepartures.at(i);
const departureDateScheduled = this.stringToDate( const scheduledDepartureDate =
timetable.checkpointDeparturesScheduled?.at(i) i == 0
); ? (timetable.checkpointDeparturesScheduled.at(i) ?? timetable.scheduledBeginDate)
const departureDateReal = this.stringToDate(timetable.checkpointDepartures?.at(i)); : timetable.checkpointDeparturesScheduled.at(i);
const arrivalDateScheduled = this.stringToDate(
timetable.checkpointArrivalsScheduled?.at(i) const stopTime = Number(timetable.checkpointStopTypes.at(i)?.split(',')[0]) || 0;
); const stopType = timetable.checkpointStopTypes.at(i)?.split(',')[1] || '';
const arrivalDateReal = this.stringToDate(timetable.checkpointArrivals?.at(i));
const arrivalHTML = acc.push({
(arrivalDateReal && stopName,
arrivalDateScheduled && arrivalTimestamp: this.dateStringToTimestamp(arrivalDate),
arrivalDateReal?.getTime() != arrivalDateScheduled?.getTime() scheduledArrivalTimestamp: this.dateStringToTimestamp(scheduledArrivalDate),
? `<s class="text--grayed">${this.parseDateToTimeString(arrivalDateScheduled)}</s> ` departureTimestamp: this.dateStringToTimestamp(departureDate),
: '') + this.parseDateToTimeString(arrivalDateReal || arrivalDateScheduled); scheduledDepartureTimestamp: this.dateStringToTimestamp(scheduledDepartureDate),
const departureHTML = stopTime,
(departureDateReal && stopType,
departureDateScheduled && isConfirmed: i < timetable.confirmedStopsCount
departureDateReal?.getTime() != departureDateScheduled?.getTime() });
? `<s class="text--grayed">${this.parseDateToTimeString(departureDateScheduled)}</s> `
: '') + this.parseDateToTimeString(departureDateReal || departureDateScheduled); return acc;
let html = `${arrivalHTML}${departureHTML ? ` / ${departureHTML}` : ''}`; }, []);
if (html) html = ` (${html})`;
return { stopName, html, confirmed };
});
} }
} }
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '../../../styles/badge.scss';
.timetable-stops { .timetable-stops {
word-wrap: break-word; word-wrap: break-word;
gap: 0.25em; gap: 0.25em;
@@ -138,12 +201,63 @@ export default defineComponent({
} }
.stop-list { .stop-list {
&-item[data-confirmed='true'] { display: flex;
color: lightgreen; flex-wrap: wrap;
gap: 0.5em;
padding: 0.5em 0;
}
.stop-name { .stop-label {
font-weight: bold; display: flex;
} flex-wrap: wrap;
align-items: center;
color: white;
&[data-confirmed='true'] > .stop-name {
color: lightgreen;
}
}
.stop-label > span {
display: flex;
align-items: center;
padding: 0.3em 0.5em;
}
.stop-name {
background-color: #2b2b2b;
border-radius: 0.5em 0 0 0.5em;
font-weight: bold;
color: #ccc;
}
.stop-date {
background-color: #444;
padding: 0.3em 0.5em;
&:last-child {
border-radius: 0 0.5em 0.5em 0;
}
s {
color: #aaa;
}
&[data-delayed='true'] {
color: salmon;
}
&[data-preponed='true'] {
color: lightgreen;
}
}
.stop-time {
background-color: #252525;
&[data-stop-ph='true'],
&[data-stop-pm='true'] {
background-color: #db8e29;
} }
} }
@@ -21,7 +21,7 @@
:key="spawn.spawnName + onlineScenery?.dispatcherName + i" :key="spawn.spawnName + onlineScenery?.dispatcherName + i"
:data-electrified="spawn.isElectrified" :data-electrified="spawn.isElectrified"
> >
<span class="name">{{ spawn.spawnName }}</span> <span class="stop-name">{{ spawn.spawnName }}</span>
<span class="length">{{ spawn.spawnLength }}m</span> <span class="length">{{ spawn.spawnLength }}m</span>
</li> </li>
</transition-group> </transition-group>
+4 -4
View File
@@ -4,10 +4,10 @@
:data-minor="stop.isSBL || (stop.nameRaw.endsWith(', po') && !stop.duration)" :data-minor="stop.isSBL || (stop.nameRaw.endsWith(', po') && !stop.duration)"
> >
<router-link v-if="/(, podg$|<strong>)/.test(stop.nameHtml)" :to="sceneryHref"> <router-link v-if="/(, podg$|<strong>)/.test(stop.nameHtml)" :to="sceneryHref">
<span class="name" v-html="stop.nameHtml"></span> <span class="stop-name" v-html="stop.nameHtml"></span>
</router-link> </router-link>
<span v-else class="name" v-html="stop.nameHtml"></span> <span v-else class="stop-name" v-html="stop.nameHtml"></span>
<span <span
v-if="stop.position != 'begin'" v-if="stop.position != 'begin'"
@@ -107,7 +107,7 @@ s {
flex-wrap: wrap; flex-wrap: wrap;
align-items: center; align-items: center;
.name { .stop-name {
background: $stopNameClr; background: $stopNameClr;
border-radius: 0.5em 0 0 0.5em; border-radius: 0.5em 0 0 0.5em;
padding: 0.3em 0.5em; padding: 0.3em 0.5em;
@@ -134,7 +134,7 @@ s {
display: none; display: none;
} }
.name { .stop-name {
background: none; background: none;
color: #aaa; color: #aaa;
padding: 0; padding: 0;
+6 -2
View File
@@ -57,6 +57,10 @@ export default defineComponent({
: ''; : '';
}, },
dateStringToTimestamp(dateString?: string) {
return dateString ? new Date(dateString).getTime() : 0;
},
calculateDuration(timestampMs: number, showSeconds = false) { calculateDuration(timestampMs: number, showSeconds = false) {
const secondsTotal = Math.floor(timestampMs / 1000); const secondsTotal = Math.floor(timestampMs / 1000);
const minsTotal = Math.round(timestampMs / 60000); const minsTotal = Math.round(timestampMs / 60000);
@@ -70,8 +74,8 @@ export default defineComponent({
minsInHour minsInHour
)}` )}`
: showSeconds && secondsTotal <= 60 : showSeconds && secondsTotal <= 60
? this.$t('journal.seconds', { value: secondsTotal }, secondsTotal) ? this.$t('journal.seconds', { value: secondsTotal }, secondsTotal)
: this.$t('journal.minutes', { value: minsTotal }, minsTotal); : this.$t('journal.minutes', { value: minsTotal }, minsTotal);
} }
} }
}); });
+1
View File
@@ -1,4 +1,5 @@
@import 'variables.scss'; @import 'variables.scss';
@import 'responsive.scss';
.badge { .badge {
font-weight: 600; font-weight: 600;
+8 -10
View File
@@ -246,8 +246,6 @@ export namespace API {
authorName?: string; authorName?: string;
authorId?: number; authorId?: number;
stopsString?: string;
stockString?: string; stockString?: string;
stockHistory: string[]; stockHistory: string[];
@@ -255,16 +253,16 @@ export namespace API {
stockLength?: number; stockLength?: number;
maxSpeed?: number; maxSpeed?: number;
hashesString?: string;
currentSceneryName?: string; currentSceneryName?: string;
currentSceneryHash?: string; currentSceneryHash?: string;
routeSceneries?: string; routeSceneries: string;
checkpointArrivals?: string[]; checkpointArrivals: string[];
checkpointDepartures?: string[]; checkpointDepartures: string[];
checkpointArrivalsScheduled?: string[]; checkpointArrivalsScheduled: string[];
checkpointDeparturesScheduled?: string[]; checkpointDeparturesScheduled: string[];
checkpointStopTypes?: string[]; checkpointStopTypes: string[];
visitedSceneries?: string[]; visitedSceneries: string[];
sceneryNames: string[];
path: string; path: string;
} }