Globalny TrainModal; animacja przejścia

This commit is contained in:
2022-07-16 00:27:37 +02:00
parent 5ee8f72652
commit 1cc799706c
10 changed files with 73 additions and 128 deletions
+13
View File
@@ -17,6 +17,19 @@
} }
} }
.modal-anim {
&-enter-active,
&-leave-active {
transition: all $animDuration $animType;
}
&-enter-from,
&-leave-to {
transform: translateY(-25%);
opacity: 0;
}
}
.route { .route {
margin: 0 0.2em; margin: 0 0.2em;
+11 -4
View File
@@ -1,7 +1,13 @@
<template> <template>
<div class="app_container"> <div class="app_container">
<UpdateModal /> <UpdateModal />
<transition name="modal-anim">
<keep-alive>
<TrainModal v-if="store.chosenModalTrain" />
</keep-alive>
</transition>
<header class="app_header"> <header class="app_header">
<div class="header_container"> <div class="header_container">
<div class="header_icons"> <div class="header_icons">
@@ -59,7 +65,6 @@
<main class="app_main"> <main class="app_main">
<router-view v-slot="{ Component }"> <router-view v-slot="{ Component }">
<!-- <transition name="view-anim" mode="out-in"> -->
<keep-alive> <keep-alive>
<component :is="Component" :key="$route.path" /> <component :is="Component" :key="$route.path" />
</keep-alive> </keep-alive>
@@ -89,14 +94,16 @@ import StatusIndicator from '@/components/App/StatusIndicator.vue';
import SelectBox from '@/components/Global/SelectBox.vue'; import SelectBox from '@/components/Global/SelectBox.vue';
import { useStore } from './store/store'; import { useStore } from './store/store';
import UpdateModal from './components/App/UpdateModal.vue'; import UpdateModal from './components/App/UpdateModal.vue';
import TrainModal from './components/Global/TrainModal.vue';
export default defineComponent({ export default defineComponent({
components: { components: {
Clock, Clock,
StatusIndicator, StatusIndicator,
SelectBox, SelectBox,
UpdateModal UpdateModal,
}, TrainModal,
},
setup() { setup() {
const store = useStore(); const store = useStore();
+19 -70
View File
@@ -1,38 +1,21 @@
<template> <template>
<div class="train-modal" @keydown.esc="closeModal"> <div class="train-modal" v-if="store.chosenModalTrain" @keydown.esc="closeModal">
<div class="modal_background" @click="closeModal"></div> <div class="modal_background" @click="closeModal"></div>
<div class="modal_content" ref="content" tabindex="0"> <div class="modal_content" ref="content" tabindex="0">
<!-- <transition name="top-info-bar-anim">
<div class="top-info-bar" v-if="isTopBarVisible">
<span v-if="chosenTrain.timetableData">
<b class="text--primary">{{ chosenTrain.timetableData.category }} {{ chosenTrain.trainNo }}</b>
{{ chosenTrain.driverName }} &bull;
<b>{{ chosenTrain.timetableData.route.replace('|', ' > ') }}</b>
&bull;
{{ currentDistance(chosenTrain.timetableData.followingStops) }} km /
<span class="text--primary">{{ chosenTrain.timetableData.routeDistance }} km</span>
&bull;
<span class="text--grayed">{{ displayTrainPosition(chosenTrain) }}</span>
&bull;
{{ chosenTrain.speed }}km/h
</span>
</div>
</transition> -->
<button class="btn exit" @click="closeModal"> <button class="btn exit" @click="closeModal">
<img :src="icons.exit" alt="close card" /> <img :src="icons.exit" alt="close card" />
</button> </button>
<TrainInfo :train="chosenTrain" :extended="false" ref="trainInfo" /> <TrainInfo :train="store.chosenModalTrain" :extended="false" ref="trainInfo" />
<TrainSchedule :train="chosenTrain" tabindex="0" /> <TrainSchedule :train="store.chosenModalTrain" tabindex="0" />
</div> </div>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import trainInfoMixin from '@/mixins/trainInfoMixin'; import trainInfoMixin from '@/mixins/trainInfoMixin';
import Train from '@/scripts/interfaces/Train'; import { useStore } from '@/store/store';
import { defineComponent, PropType } from 'vue'; import { defineComponent } from 'vue';
import TrainInfo from '../TrainsView/TrainInfo.vue'; import TrainInfo from '../TrainsView/TrainInfo.vue';
import TrainSchedule from '../TrainsView/TrainSchedule.vue'; import TrainSchedule from '../TrainsView/TrainSchedule.vue';
@@ -40,8 +23,6 @@ export default defineComponent({
components: { TrainInfo, TrainSchedule }, components: { TrainInfo, TrainSchedule },
mixins: [trainInfoMixin], mixins: [trainInfoMixin],
emits: ['closeModal'],
data() { data() {
return { return {
isTopBarVisible: false, isTopBarVisible: false,
@@ -52,11 +33,12 @@ export default defineComponent({
}; };
}, },
props: { setup() {
chosenTrain: { const store = useStore();
type: Object as PropType<Train>,
required: true, return {
}, store,
};
}, },
activated() { activated() {
@@ -65,23 +47,11 @@ export default defineComponent({
this.$nextTick(() => { this.$nextTick(() => {
contentEl.focus(); contentEl.focus();
}); });
document.body.style.overflowY = 'hidden';
// document.body.blur();
// contentEl.addEventListener('scroll', this.handleContentScroll);
},
deactivated() {
document.body.style.overflowY = 'scroll';
// (this.$refs['content'] as HTMLElement).removeEventListener('scroll', this.handleContentScroll);
// this.isTopBarVisible = false;
}, },
methods: { methods: {
closeModal() { closeModal() {
this.$emit('closeModal'); this.store.chosenModalTrain = undefined;
}, },
handleContentScroll(e: Event) { handleContentScroll(e: Event) {
@@ -120,7 +90,7 @@ export default defineComponent({
padding: 0.25em; padding: 0.25em;
z-index: 101; z-index: 201;
img { img {
width: 1.5rem; width: 1.5rem;
@@ -134,10 +104,9 @@ export default defineComponent({
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%;
color: white; color: white;
z-index: 100; z-index: 200;
display: flex; display: flex;
justify-content: center; justify-content: center;
@@ -149,8 +118,8 @@ export default defineComponent({
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100vw;
height: 100%; height: 100vh;
cursor: pointer; cursor: pointer;
@@ -164,26 +133,10 @@ export default defineComponent({
margin-top: 1em; margin-top: 1em;
width: 95vw; width: 95vw;
height: 95vh; max-height: 96vh;
background-color: #1a1a1a; background-color: #1a1a1a;
} box-shadow: 0 0 15px 10px #0e0e0e;
.top-info-bar {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
width: 100%;
padding: 0.5em 1em;
padding-right: 4em;
text-align: center;
overflow: hidden;
z-index: 101;
background-color: #000000dd;
} }
@include midScreen { @include midScreen {
@@ -194,10 +147,6 @@ export default defineComponent({
width: 1.75rem; width: 1.75rem;
} }
} }
.top-info-bar {
padding: 0.5em 1em;
}
} }
@include smallScreen { @include smallScreen {
@@ -206,7 +155,7 @@ export default defineComponent({
} }
.modal_content { .modal_content {
max-height: 75vh; max-height: 85vh;
} }
} }
</style> </style>
@@ -11,10 +11,10 @@
v-for="(train, i) in computedStationTrains" v-for="(train, i) in computedStationTrains"
class="badge user" class="badge user"
:class="train.stopStatus" :class="train.stopStatus"
:key="train.trainNo + i" :key="train.trainId"
tabindex="0" tabindex="0"
@click="navigateTo('/trains', { trainNo: train.trainNo, driverName: train.driverName })" @click="selectTrain(train.trainId)"
@keydown.enter="navigateTo('/trains', { trainNo: train.trainNo, driverName: train.driverName })" @keydown.enter="selectTrain(train.trainId)"
> >
<span class="user_train">{{ train.trainNo }}</span> <span class="user_train">{{ train.trainNo }}</span>
<span class="user_name">{{ train.driverName }}</span> <span class="user_name">{{ train.driverName }}</span>
@@ -29,6 +29,7 @@
<script lang="ts"> <script lang="ts">
import routerMixin from '@/mixins/routerMixin'; import routerMixin from '@/mixins/routerMixin';
import Station from '@/scripts/interfaces/Station'; import Station from '@/scripts/interfaces/Station';
import { useStore } from '@/store/store';
import { computed, defineComponent } from 'vue'; import { computed, defineComponent } from 'vue';
export default defineComponent({ export default defineComponent({
@@ -42,6 +43,8 @@ export default defineComponent({
}, },
setup(props) { setup(props) {
const store = useStore();
const computedStationTrains = computed(() => { const computedStationTrains = computed(() => {
if (!props.station) return []; if (!props.station) return [];
@@ -59,7 +62,7 @@ export default defineComponent({
}); });
}); });
return { computedStationTrains }; return { computedStationTrains, store };
}, },
data: () => ({ data: () => ({
@@ -67,6 +70,12 @@ export default defineComponent({
user: require('@/assets/icon-user.svg'), user: require('@/assets/icon-user.svg'),
}, },
}), }),
methods: {
selectTrain(trainId: string) {
this.store.chosenModalTrain = this.store.trainList.find((train) => train.trainId == trainId);
},
},
}); });
</script> </script>
@@ -130,3 +139,4 @@ $disconnected: slategray;
} }
} }
</style> </style>
@@ -25,10 +25,6 @@
</div> </div>
</div> </div>
<keep-alive>
<TrainModal v-if="chosenTrain" :chosen-train="chosenTrain" @close-modal="closeTrainModal" />
</keep-alive>
<div class="timetable-list"> <div class="timetable-list">
<!-- <transition name="scenery-timetable-list-anim" mode="out-in"> --> <!-- <transition name="scenery-timetable-list-anim" mode="out-in"> -->
<!-- <div :key="store.dataStatuses.trains + selectedCheckpoint" class="scenery-timetable-list"> --> <!-- <div :key="store.dataStatuses.trains + selectedCheckpoint" class="scenery-timetable-list"> -->
@@ -188,8 +184,6 @@ export default defineComponent({
warning: require('@/assets/icon-warning.svg'), warning: require('@/assets/icon-warning.svg'),
timetable: require('@/assets/icon-timetable.svg'), timetable: require('@/assets/icon-timetable.svg'),
}, },
chosenTrainId: null as string | null,
}), }),
setup(props) { setup(props) {
@@ -238,12 +232,6 @@ export default defineComponent({
}; };
}, },
computed: {
chosenTrain() {
return this.store.trainList.find((train) => train.trainId == this.chosenTrainId);
},
},
methods: { methods: {
loadSelectedOption() { loadSelectedOption() {
if (!this.station) return; if (!this.station) return;
@@ -261,11 +249,7 @@ export default defineComponent({
}, },
selectTrain(trainId: string) { selectTrain(trainId: string) {
this.chosenTrainId = trainId; this.store.chosenModalTrain = this.store.trainList.find((train) => train.trainId == trainId);
},
closeTrainModal() {
this.chosenTrainId = null;
}, },
}, },
+2 -1
View File
@@ -191,10 +191,11 @@ $stopNameClr: #22a8d1;
display: flex; display: flex;
justify-content: center; justify-content: center;
} }
ul.stock-list { ul.stock-list {
display: flex; display: flex;
align-items: flex-end; align-items: flex-end;
overflow-x: auto; overflow: auto;
padding-bottom: 1em; padding-bottom: 1em;
li > div { li > div {
+7 -31
View File
@@ -1,9 +1,5 @@
<template> <template>
<keep-alive> <div class="train-table">
<TrainModal v-if="chosenTrain" :chosen-train="chosenTrain" @close-modal="closeTimetable" />
</keep-alive>
<div class="train-table" @keydown.esc="closeTimetable">
<button class="return-btn" @click="scrollToTop" v-if="showReturnButton"> <button class="return-btn" @click="scrollToTop" v-if="showReturnButton">
<img :src="icons.arrowAsc" alt="return arrow" /> <img :src="icons.arrowAsc" alt="return arrow" />
</button> </button>
@@ -20,9 +16,9 @@
<li <li
class="train-row" class="train-row"
v-for="train in currentTrains" v-for="train in currentTrains"
:key="train.trainNo + train.driverId" :key="train.trainId"
@click.stop="toggleTimetable(train)" @click.stop="selectTrain(train.trainId)"
@keydown.enter="toggleTimetable(train)" @keydown.enter="selectTrain(train.trainId)"
> >
<TrainInfo :train="train" /> <TrainInfo :train="train" />
</li> </li>
@@ -73,7 +69,6 @@ export default defineComponent({
}, },
defaultVehicleIcons: defaultVehicleIconsJSON, defaultVehicleIcons: defaultVehicleIconsJSON,
chosenTrainId: null as string | null,
}), }),
setup(props) { setup(props) {
@@ -99,12 +94,6 @@ export default defineComponent({
}; };
}, },
computed: {
chosenTrain() {
return this.trains.find((train) => train.trainId == this.chosenTrainId);
},
},
activated() { activated() {
const query = this.$route.query; const query = this.$route.query;
@@ -113,15 +102,11 @@ export default defineComponent({
this.searchedTrain = query.trainNo.toString(); this.searchedTrain = query.trainNo.toString();
setTimeout(() => { setTimeout(() => {
this.chosenTrainId = query.driverName + <string>query.trainNo; this.selectTrain(query.driverName + <string>query.trainNo);
}, 20); }, 20);
} }
}, },
deactivated() {
this.chosenTrainId = null;
},
methods: { methods: {
enter(el: HTMLElement) { enter(el: HTMLElement) {
const maxHeight = getComputedStyle(el).height; const maxHeight = getComputedStyle(el).height;
@@ -147,17 +132,8 @@ export default defineComponent({
}, 10); }, 10);
}, },
toggleTimetable(train: Train, state?: boolean) { selectTrain(trainId: string) {
if (state !== undefined) { this.store.chosenModalTrain = this.store.trainList.find((train) => train.trainId == trainId);
this.chosenTrainId = train.trainId;
return;
}
this.chosenTrainId = this.chosenTrainId && this.chosenTrainId == train.trainId ? null : train.trainId;
},
closeTimetable() {
this.chosenTrainId = null;
}, },
}, },
}); });
+1
View File
@@ -53,6 +53,7 @@ export default interface Station {
driverName: string; driverName: string;
driverId: number; driverId: number;
trainNo: number; trainNo: number;
trainId: string;
stopStatus?: string; stopStatus?: string;
}[]; }[];
+3 -1
View File
@@ -41,6 +41,8 @@ export const useStore = defineStore('store', {
driverStatsName: '', driverStatsName: '',
driverStatsData: undefined, driverStatsData: undefined,
chosenModalTrain: undefined as Train | undefined,
dataStatuses: { dataStatuses: {
connection: DataStatus.Loading, connection: DataStatus.Loading,
sceneries: DataStatus.Loading, sceneries: DataStatus.Loading,
@@ -202,7 +204,7 @@ export const useStore = defineStore('store', {
(train) => (train) =>
train?.region === this.region.id && train.online && train.currentStationName === stationAPIData.stationName train?.region === this.region.id && train.online && train.currentStationName === stationAPIData.stationName
) )
.map((train) => ({ driverName: train.driverName, driverId: train.driverId, trainNo: train.trainNo })); .map((train) => ({ driverName: train.driverName, driverId: train.driverId, trainNo: train.trainNo, trainId: train.trainId }));
}, },
setStationsOnlineInfo() { setStationsOnlineInfo() {
+2
View File
@@ -30,6 +30,8 @@ export interface StoreState {
driverStatsName: string; driverStatsName: string;
driverStatsData?: DriverStatsAPIData; driverStatsData?: DriverStatsAPIData;
chosenModalTrain?: Train;
dataStatuses: { dataStatuses: {
connection: DataStatus; connection: DataStatus;
sceneries: DataStatus; sceneries: DataStatus;