chore(app): moved options to pragotron view, improved responsiveness

This commit is contained in:
2026-04-12 23:57:08 +02:00
parent 0a88d958da
commit c2ade9f95f
3 changed files with 79 additions and 157 deletions
-129
View File
@@ -1,129 +0,0 @@
<template>
<div class="dropdown" v-click-outside="() => (store.optionsOpen = false)">
<button class="btn--image" @click="store.optionsOpen = !store.optionsOpen">
<img src="/options.svg" alt="options" />
</button>
<transition name="dropdown-anim">
<div class="dropdown-body" v-if="store.optionsOpen">
<h3>{{ $t('options.header') }}</h3>
<hr />
<div class="dropdown-checkboxes">
<label>
<input type="checkbox" v-model="store.filters.nonPassenger" />
{{ $t('options.checkbox-non-passenger') }}
</label>
<label>
<input type="checkbox" v-model="store.filters.terminating" />
{{ $t('options.checkbox-terminating') }}
</label>
<label>
<input type="checkbox" v-model="store.filters.soundsEnabled" />
{{ $t('options.checkbox-sounds') }}
</label>
</div>
<div class="dropdown-checkpoints" v-if="isPragotronOpen">
<label for="checkpoint">
{{ $t('options.checkpoint-name') }}
<select id="checkpoint" v-model="store.selectedCheckpointName">
<option v-for="cp in store.selectedStation?.stationCheckpoints" :value="cp" :key="cp">
{{ cp }}
</option>
</select>
</label>
</div>
<div tabindex="0" @focus="() => (store.optionsOpen = false)"></div>
</div>
</transition>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { useMainStore } from '../stores/mainStore';
export default defineComponent({
data: () => ({
store: useMainStore()
}),
computed: {
isPragotronOpen() {
return this.$route.path == '/board';
}
},
watch: {
'store.filters': {
deep: true,
handler(filters: typeof this.store.filters) {
window.localStorage.setItem('settings', JSON.stringify(filters));
}
}
}
});
</script>
<style lang="scss" scoped>
img {
max-width: 2em;
}
h3 {
font-size: 1.2em;
margin: 0;
}
.dropdown-bg {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 100;
}
.dropdown-body {
position: absolute;
top: 100%;
right: 0;
padding: 0.25em;
transform: translateY(0.5em);
width: 500px;
max-width: calc(100% - 0.5em);
z-index: 105;
background-color: #000000e1;
}
.dropdown-checkboxes {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 0.5em;
margin: 0.5em 0;
}
.dropdown-checkpoints {
margin: 0.5em 0;
}
.dropdown-anim {
&-enter-active,
&-leave-active {
transition: all 90ms ease-out;
}
&-enter-from,
&-leave-to {
transform: translateY(20px);
opacity: 0;
}
}
</style>
+1 -7
View File
@@ -4,10 +4,6 @@
<router-link class="brand" to="/"> <router-link class="brand" to="/">
Pragotron TD2 <span class="text--accent">v{{ version }}</span> <sup>by Spythere</sup> Pragotron TD2 <span class="text--accent">v{{ version }}</span> <sup>by Spythere</sup>
</router-link> </router-link>
<div class="options">
<Dropdown />
</div>
</div> </div>
</nav> </nav>
</template> </template>
@@ -15,10 +11,8 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { useMainStore } from '../stores/mainStore'; import { useMainStore } from '../stores/mainStore';
import Dropdown from './Dropdown.vue';
export default defineComponent({ export default defineComponent({
components: { Dropdown },
props: { props: {
version: String version: String
}, },
@@ -53,7 +47,7 @@ nav.navbar {
position: relative; position: relative;
margin: 0 auto; margin: 0 auto;
max-width: 1400px; max-width: 1500px;
font-weight: bold; font-weight: bold;
} }
+78 -21
View File
@@ -1,6 +1,40 @@
<template> <template>
<div class="pragotron"> <div class="pragotron">
<div class="pragotron_content"> <div class="pragotron_content">
<div class="pragotron_options">
<div class="options-checkboxes">
<label>
<input type="checkbox" v-model="mainStore.filters.nonPassenger" />
{{ $t('options.checkbox-non-passenger') }}
</label>
<label>
<input type="checkbox" v-model="mainStore.filters.terminating" />
{{ $t('options.checkbox-terminating') }}
</label>
<label>
<input type="checkbox" v-model="mainStore.filters.soundsEnabled" />
{{ $t('options.checkbox-sounds') }}
</label>
</div>
<div class="options-checkpoints">
<label for="checkpoint">
{{ $t('options.checkpoint-name') }}
<select id="checkpoint" v-model="mainStore.selectedCheckpointName">
<option
v-for="cp in mainStore.selectedStation?.stationCheckpoints"
:value="cp"
:key="cp"
>
{{ cp }}
</option>
</select>
</label>
</div>
</div>
<div class="wrapper" ref="pragotron"> <div class="wrapper" ref="pragotron">
<div class="top-pane"> <div class="top-pane">
<span class="title"> <span class="title">
@@ -327,16 +361,15 @@ export default defineComponent({
methods: { methods: {
resizeTable() { resizeTable() {
const elRef = this.$refs['pragotron'] as HTMLElement; // const elRef = this.$refs['pragotron'] as HTMLElement;
if (!elRef) return; // if (!elRef) return;
// const scale = Math.min(
const scale = Math.min( // window.innerWidth / elRef.clientWidth,
window.innerWidth / elRef.clientWidth, // window.innerHeight / elRef.clientHeight,
window.innerHeight / elRef.clientHeight, // 1
1 // );
); // console.log(elRef.clientWidth);
// elRef.style.transform = `scale(${scale})`;
elRef.style.transform = `scale(${scale})`;
}, },
selectDefaultCheckpoint() { selectDefaultCheckpoint() {
@@ -450,34 +483,58 @@ export default defineComponent({
/* ************** */ /* ************** */
.pragotron_content { .pragotron {
display: flex; display: flex;
justify-content: center; justify-content: center;
padding: 1em; padding: 1em;
} }
@media only screen and (max-width: 1500px) {
.pragotron {
font-size: calc(0.3em + 0.65vw);
}
}
.pragotron_options {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
width: 100%;
margin-bottom: 0.5em;
}
.pragotron_content {
display: flex;
justify-content: center;
align-items: flex-start;
flex-direction: column;
width: 100%;
max-width: 1500px;
}
.wrapper { .wrapper {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
min-width: 1400px;
min-height: 700px;
padding: 2em;
transform-origin: top; width: 100%;
min-height: 50em;
overflow: auto;
} }
.top-pane > .headers, .top-pane > .headers,
.row-content { .row-content {
display: grid; display: grid;
grid-template-columns: 1fr 1fr 2fr 2fr 1fr; grid-template-columns: 1fr 1fr 2fr 2fr 1fr;
gap: 0 10px; gap: 0 1em;
padding: 0 10px; padding: 0 1em;
} }
.top-pane { .top-pane {
background-color: white; background-color: white;
color: black; color: black;
height: 180px; height: 12em;
min-width: 700px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -485,24 +542,24 @@ export default defineComponent({
.title { .title {
padding: 0; padding: 0;
font-size: 3.5em; font-size: 3.5em;
} }
.headers { .headers {
text-align: center; text-align: center;
font-size: 1.35em; font-size: 1.35em;
} }
} }
.table { .table {
background: white;
flex-grow: 1; flex-grow: 1;
display: grid; display: grid;
grid-template-rows: repeat(7, 1fr); grid-template-rows: repeat(7, 1fr);
gap: 5px 0; gap: 5px 0;
background: white;
min-width: 700px;
} }
.row { .row {