Files
stacjownik/src/App.vue
T

215 lines
4.1 KiB
Vue

<template>
<div class="app">
<div class="container">
<header class="header">
<div class="header-body">
<span class="header-brand">
<span>Stacj</span>
<img src="@/assets/trainlogo.png" alt="trainlogo" />
<span>wnik</span>
</span>
<span class="header-info">
<Clock />
<div class="counter">
<img src="@/assets/icon-dispatcher.svg" alt="icon dispatcher" />
<span>{{stationCount}}</span>
<span>{{trainCount}}</span>
<img src="@/assets/icon-train.svg" alt="icon train" />
</div>
</span>
<span class="header-links">
<router-link class="route" active-class="route-active" to="/" exact>SCENERIE</router-link>/
<router-link class="route" active-class="route-active" to="/trains">POCIĄGI</router-link>
</span>
</div>
</header>
<main class="app-main">
<Loading v-if="connectionState == 0" />
<Error v-else-if="connectionState == 1" :error="errorMessage" />
<transition name="view-anim" mode="out-in" v-else>
<keep-alive>
<router-view />
</keep-alive>
</transition>
</main>
<footer class="app-footer flex">
<span>&copy; Spythere 2020</span>
<span>Sprawdź, co nowego w Stacjowniku!</span>
</footer>
</div>
</div>
</template>
<script lang="ts">
import { Vue, Component, Prop } from "vue-property-decorator";
import { Action, Getter } from "vuex-class";
import { mapGetters, mapActions } from "vuex";
import Error from "@/components/states/Error.vue";
import Loading from "@/components/states/Loading.vue";
import Clock from "@/components/ui/Clock.vue";
import Options from "@/components/ui/Options.vue";
enum ConnState {
Loading = 0,
Error = 1,
Connected = 2,
}
@Component({
components: { Error, Loading, Clock, Options },
})
export default class App extends Vue {
@Getter("getStations") stations;
@Getter("getTrainCount") trainCount;
@Getter("getStationCount") stationCount;
@Action("initStations") initStations;
errorMessage: string = "";
connectionState: ConnState = ConnState.Loading;
mounted() {
this.initStations();
this.$store.watch(
(state, getters) => getters.getConnectionState,
(state: ConnState) => (this.connectionState = state)
);
}
}
</script>
<style lang="scss">
@import "./styles/responsive.scss";
@import "./styles/variables.scss";
@import "./styles/global.scss";
.view-anim {
&-enter {
transform: translateX(-10%);
opacity: 0;
}
&-leave-to {
transform: translateX(10%);
opacity: 0;
}
&-enter-active,
&-leave-active {
transition: all $animDuration $animType;
}
}
.route {
margin: 0 0.2em;
&-active {
color: $accentCol;
font-weight: bold;
}
}
.app {
background: $bgCol;
color: white;
font-size: calc(1rem + 2.1vw);
@include smallScreen() {
font-size: 2rem;
}
}
.container {
display: grid;
grid-template-rows: auto 1fr auto;
grid-template-columns: minmax(0, 1fr);
min-width: 0;
min-height: 100vh;
}
.header {
background: #333;
padding: 0.15em;
border-radius: 0 0 0.7em 0.7em;
display: flex;
justify-content: center;
&-brand {
width: 100%;
font-size: 1.1em;
text-align: center;
img {
width: 0.8em;
}
}
&-info {
display: flex;
justify-content: space-between;
margin: 0 0.3em;
padding: 0.2em;
font-size: 0.35em;
}
&-links {
display: flex;
justify-content: center;
border-radius: 0.7em;
padding: 0.2em;
font-size: 0.35em;
}
}
.counter {
display: flex;
align-items: center;
color: $accentCol;
font-size: 1em;
span {
margin: 0 0.15em;
}
img {
width: 1.35em;
}
}
footer {
background: #111;
padding: 0.3rem;
color: white;
max-width: 100%;
font-size: calc(0.5rem + 0.5vw);
flex-direction: column;
span {
margin: 0.2rem;
&:nth-child(2) {
color: #888;
font-size: 0.95em;
}
}
}
</style>