This commit is contained in:
2022-07-26 00:31:00 +02:00
parent bea95f9cf3
commit 451a184ccb
9 changed files with 149 additions and 159 deletions
+69 -35
View File
@@ -1,43 +1,54 @@
<template>
<header>
<img :src="logoImage" alt="logo pojazdownik" />
</header>
<div class="image-preview" v-if="store.vehiclePreviewSrc != ''" @click="() => (store.vehiclePreviewSrc = '')">
<img :src="store.vehiclePreviewSrc" alt="preview" />
</div>
<main>
<div class="image-preview" v-if="store.vehiclePreviewSrc != ''" @click="() => (store.vehiclePreviewSrc = '')">
<img :src="store.vehiclePreviewSrc" alt="preview" />
</div>
<div class="app_container">
<header>
<img :src="logoImage" alt="logo pojazdownik" />
</header>
<main>
<div id="inputs-area">
<InputsSection />
</div>
<InputsSection />
<ListSection />
</main>
<footer>
<div class="text--grayed" style="margin-bottom: 0.25em">
Ta strona ma charakter informacyjny. Autor nie ponosi odpowiedzialności za tworzenie pociągów niezgodnych z
regulaminem symulatora Train Driver 2!
</div>
&copy;
<a href="https://td2.info.pl/profile/?u=20777" target="_blank">Spythere</a>
{{ new Date().getUTCFullYear() }} | v{{ VERSION }}
</footer>
<div id="list-area">
<ListSection />
</div>
<div id="image-area">
<TrainImage />
</div>
</main>
<footer>
<div class="text--grayed" style="margin-bottom: 0.25em">
Ta strona ma charakter informacyjny. Autor nie ponosi odpowiedzialności za tworzenie pociągów niezgodnych z
regulaminem symulatora Train Driver 2!
</div>
&copy;
<a href="https://td2.info.pl/profile/?u=20777" target="_blank">Spythere</a>
{{ new Date().getUTCFullYear() }} | v{{ VERSION }}
</footer>
</div>
</template>
<script lang="ts">
import packageInfo from '.././package.json';
import { defineComponent, inject } from 'vue';
import { defineComponent } from 'vue';
import { IStore } from './types';
import InputsSection from './components/InputsSection.vue';
import ListSection from './components/ListSection.vue';
import logoImage from './assets/logo.svg';
import { useStore } from './store';
import TrainImage from './components/TrainImageSection.vue';
export default defineComponent({
components: {
ListSection,
InputsSection,
TrainImage,
},
data: () => ({
@@ -69,23 +80,22 @@ export default defineComponent({
<style lang="scss">
@import './styles/global';
.app_container {
min-height: 100vh;
display: flex;
flex-direction: column;
padding: 1em;
}
/* APP */
#app {
margin: 0 auto;
color: $textColor;
min-height: 100vh;
padding: 0.5em 1em;
overflow: hidden;
display: grid;
display: flex;
justify-content: center;
grid-template-columns: minmax(200px, 1200px);
grid-template-rows: 5.5em 1fr auto;
}
/* HEADER SECTION */
@@ -93,12 +103,11 @@ export default defineComponent({
header {
text-align: center;
margin-top: 1em;
img {
width: 35em;
}
}
h2 {
margin: 0;
margin-bottom: 0.5em;
@@ -139,14 +148,39 @@ h2 {
/* MAIN SECTION */
main {
margin-top: 8em;
margin-top: 2em;
display: grid;
gap: 1em 3em;
width: 100%;
max-width: 1200px;
grid-template-columns: 1fr 2fr;
grid-template-areas: 'inputs list' 'image list';
#inputs-area {
grid-area: inputs;
}
#list-area {
grid-area: list;
}
#image-area {
grid-area: image;
}
}
/* FOOTER SECTION */
footer {
margin-top: 1.5em;
margin-top: auto;
text-align: center;
}
/* MOBILE VIEWS */
@media screen and (max-width: 800px) {
#app {
font-size: calc(0.75vw + 0.6rem);
+22 -62
View File
@@ -5,7 +5,12 @@
<h2 class="input_header">WYBIERZ POJAZDY / WAGONY</h2>
<div class="input_list type">
<select id="locomotives-list" v-model="store.chosenLoco">
<select
id="locomotives-list"
v-model="store.chosenLoco"
@focus="onVehicleSelect('loco')"
@input="onVehicleSelect('loco')"
>
<option :value="null" disabled>Wybierz pojazd trakcyjny</option>
<option v-for="loco in locoOptions" :value="loco" :key="loco.type">
{{ loco.type }}
@@ -16,7 +21,12 @@
</div>
<div class="input_list type">
<select id="carwagons-list" v-model="store.chosenCar">
<select
id="carwagons-list"
v-model="store.chosenCar"
@focus="onVehicleSelect('car')"
@input="onVehicleSelect('car')"
>
<option :value="null" disabled>Wybierz wagon</option>
<option v-for="car in carOptions" :value="car" :key="car.type">
@@ -108,8 +118,16 @@ export default defineComponent({
this.isReadyStockListOpen = bool;
},
onVehicleSelect(type: 'loco' | 'car') {
this.$nextTick(() => {
if (!this.store.chosenLoco && !this.store.chosenCar) return;
this.store.chosenVehicle = type == 'loco' ? this.store.chosenLoco : this.store.chosenCar;
});
},
addVehicle() {
const vehicle = this.store.chosenCar || this.store.chosenLoco;
const vehicle = this.store.chosenVehicle;
if (!vehicle) return;
@@ -201,64 +219,6 @@ export default defineComponent({
margin-bottom: 1em;
}
&_radio {
button {
padding: 0.25em 0.55em;
margin-right: 0.5em;
border: 2px solid white;
color: white;
font-size: 1em;
}
button:focus {
color: $accentColor;
}
button.checked {
border-color: $accentColor;
color: $accentColor;
font-weight: bold;
}
}
&_checkbox {
margin: 1em 0;
padding: 0 1.5em;
button {
position: relative;
color: #999;
&::before {
content: '';
width: 1.5ch;
height: 1.5ch;
display: block;
position: absolute;
bottom: 0.2ch;
left: -1.5em;
background-color: #999;
}
&.checked {
color: white;
font-weight: bold;
&::before {
background-color: $accentColor;
}
}
&:focus {
outline: 1px solid $accentColor;
}
}
}
&_list {
margin: 0.5em 0;
@@ -271,7 +231,7 @@ export default defineComponent({
&_list button {
margin-left: 0.5em;
font-size: 0.8em;
font-weight: bold;
&:hover img {
border-color: $accentColor;
+10 -23
View File
@@ -1,11 +1,5 @@
<template>
<div class="bottom">
<div class="bg-dimmer" v-if="store.isRandomizerCardOpen"></div>
<train-image />
<section class="spacer"></section>
<section class="stock-list">
<div class="stock-list_buttons">
<button class="btn" @click="downloadStock">POBIERZ POCIĄG</button>
@@ -121,10 +115,9 @@
</template>
<script lang="ts">
import { computed, ComputedRef, defineComponent, inject, provide, reactive, ref } from 'vue';
import { IStore, ILocomotive, ICarWagon } from '../types';
import { defineComponent } from 'vue';
import RandomizerCard from './RandomizerCard.vue';
import TrainImage from './TrainImage.vue';
import TrainImage from './TrainImageSection.vue';
import addIcon from '../assets/add-icon.svg';
import subIcon from '../assets/sub-icon.svg';
@@ -154,12 +147,7 @@ export default defineComponent({
const attr = targetNode.attributes.getNamedItem('data-ignore-outside');
if (
!attr &&
!(this.$refs['list'] as Node).contains(targetNode) &&
targetNode.tagName.toLowerCase() != 'select' &&
targetNode.tagName.toLowerCase() != 'option'
)
if (!attr && targetNode.tagName.toLowerCase() != 'select' && targetNode.tagName.toLowerCase() != 'option')
this.store.chosenStockListIndex = -1;
});
},
@@ -212,24 +200,23 @@ export default defineComponent({
this.store.chosenStockListIndex = vehicleID;
if ((this.store.chosenCar || this.store.chosenLoco)?.imageSrc != vehicle.imgSrc) this.store.imageLoading = true;
if (this.store.chosenVehicle?.imageSrc != vehicle.imgSrc) this.store.imageLoading = true;
if (this.store.showSupporter && !vehicle.supportersOnly) {
this.store.showSupporter = false;
}
if (vehicle.isLoco) {
this.store.chosenLocoPower = vehicle.useType;
const chosenLoco = this.store.locoDataList.find((v) => v.type == vehicle.type) || null;
this.store.chosenVehicle = chosenLoco;
this.store.chosenLoco = chosenLoco;
this.store.chosenLoco = this.store.locoDataList.find((v) => v.type == vehicle.type) || null;
this.store.chosenCar = null;
this.store.chosenCargo = null;
} else {
this.store.chosenCarUseType = vehicle.useType;
const chosenCar = this.store.carDataList.find((v) => v.type == vehicle.type) || null;
this.store.chosenVehicle = chosenCar;
this.store.chosenCar = chosenCar;
this.store.chosenLoco = null;
this.store.chosenCar = this.store.carDataList.find((v) => v.type == vehicle.type) || null;
this.store.chosenCargo = vehicle.cargo || null;
}
+2 -4
View File
@@ -114,8 +114,6 @@ export default defineComponent({
return list;
}, [] as string[]),
includeSupporterVehicles: inject('includeSupporterVehicles') as boolean,
};
},
@@ -204,7 +202,7 @@ export default defineComponent({
let locoSet = this.store.locoDataList
.filter((loco) => loco.power == 'loco-e' || loco.power == 'loco-s')
.filter((loco) => (!this.includeSupporterVehicles && loco.supportersOnly ? false : true));
.filter((loco) => (loco.supportersOnly ? false : true));
if (this.chosenCarTypes.some((car) => this.cargoTypes.includes(car)))
locoSet = locoSet.filter((loco) => !loco.type.startsWith('EP'));
@@ -218,7 +216,7 @@ export default defineComponent({
totalStockMass += this.store.stockList[0].mass;
let availableCarsSet = this.store.carDataList.filter((cargoCar) => {
if (!this.includeSupporterVehicles && cargoCar.supportersOnly) return false;
if (cargoCar.supportersOnly) return false;
if (this.chosenCarTypes.find((carType) => cargoCar.type.includes(carType))) return true;
+5 -5
View File
@@ -39,7 +39,7 @@
<script lang="ts">
import { defineComponent, inject } from 'vue';
import { IStore, ILocomotive, ICarWagon } from '../types';
import { IStore, ILocomotive, ICarWagon, Vehicle } from '../types';
import iconEIC from '../assets/EIC.png';
import iconIC from '../assets/IC.svg';
@@ -127,9 +127,9 @@ export default defineComponent({
this.store.chosenRealStockName = `${type} ${number} ${name}`;
stockArray.forEach((type, i) => {
let vehicle;
if (i == 0) vehicle = this.store.locoDataList.find((loco) => loco.type == stockArray[0]);
else vehicle = this.store.carDataList.find((car) => car.type == type);
let vehicle: Vehicle | null = null;
if (i == 0) vehicle = this.store.locoDataList.find((loco) => loco.type == stockArray[0]) || null;
else vehicle = this.store.carDataList.find((car) => car.type == type) || null;
this.addVehicle(vehicle);
});
@@ -137,7 +137,7 @@ export default defineComponent({
this.exit();
},
addVehicle(vehicle: ILocomotive | ICarWagon | undefined) {
addVehicle(vehicle: Vehicle | null) {
if (!vehicle) return;
const stockObj = {
@@ -1,55 +1,55 @@
<template>
<div class="image">
<div class="image__wrapper">
<div
class="image__content"
:class="{
supporter: (store.chosenLoco || store.chosenCar)?.supportersOnly,
}"
>
<div class="no-img" v-if="!store.chosenCar && !store.chosenLoco">PODGLĄD WYBRANEGO POJAZDU</div>
<section class="train-image">
<div class="train-image__wrapper">
<div class="train-image__content">
<div class="no-img" v-if="!store.chosenVehicle">PODGLĄD WYBRANEGO POJAZDU</div>
<div class="empty-message" v-if="store.imageLoading">ŁADOWANIE OBRAZU...</div>
<img
v-if="store.chosenLoco || store.chosenCar"
:src="store.chosenLoco?.imageSrc || store.chosenCar?.imageSrc"
:alt="store.chosenLoco?.type || store.chosenCar?.type"
v-if="store.chosenVehicle"
:src="store.chosenVehicle.imageSrc"
:alt="store.chosenVehicle.type"
@load="onImageLoad"
@click="onImageClick"
/>
</div>
</div>
<div class="image__info" v-if="store.chosenLoco || store.chosenCar">
<b class="text--accent">{{ (store.chosenLoco || store.chosenCar)?.type }} </b>
<div class="image__info" v-if="store.chosenVehicle">
<b class="text--accent">{{ store.chosenVehicle.type }} </b>
<div style="color: #ccc">
<b>{{ vehicleTypes[store.chosenLoco?.power || store.chosenCar?.useType || 'loco-e'] }}</b>
<b>{{
vehicleTypes[
isLocomotive(store.chosenVehicle) ? store.chosenVehicle.power : store.chosenVehicle.useType || 'loco-e'
]
}}</b>
<div>
{{ (store.chosenCar || store.chosenLoco)?.length }}m | {{ (store.chosenCar || store.chosenLoco)?.mass }}t |
{{ (store.chosenCar || store.chosenLoco)?.maxSpeed }} km/h
{{ store.chosenVehicle.length }}m | {{ store.chosenVehicle.mass }}t | {{ store.chosenVehicle.maxSpeed }} km/h
</div>
<div v-if="store.chosenLoco">Typ kabiny: {{ store.chosenLoco.cabinType }}</div>
<div v-if="isLocomotive(store.chosenVehicle)">Typ kabiny: {{ store.chosenVehicle.cabinType }}</div>
<div v-if="store.chosenCar">
<div v-else>
{{
store.chosenCar.useType == 'car-cargo'
? carUsage[store.chosenCar.constructionType]
: 'Typ konstrukcji: ' + store.chosenCar.constructionType
store.chosenVehicle.useType == 'car-cargo'
? carUsage[store.chosenVehicle.constructionType]
: 'Typ konstrukcji: ' + store.chosenVehicle.constructionType
}}
</div>
</div>
</div>
<div class="image__info" v-else>Wybierz pojazd lub wagon, aby zobaczyć jego podgląd powyżej</div>
</div>
</section>
</template>
<script lang="ts">
import carUsage from '../data/carUsage.json';
import { defineComponent } from 'vue';
import { useStore } from '../store';
import { isLocomotive } from '../utils/vehicleUtils';
import { ILocomotive, Vehicle } from '../types';
export default defineComponent({
setup() {
@@ -80,8 +80,12 @@ export default defineComponent({
this.store.imageLoading = false;
},
isLocomotive(vehicle: Vehicle): vehicle is ILocomotive {
return isLocomotive(vehicle);
},
onImageClick() {
const chosenVehicle = this.store.chosenCar || this.store.chosenLoco;
const chosenVehicle = this.store.chosenVehicle;
if (!chosenVehicle) return;
@@ -92,15 +96,16 @@ export default defineComponent({
</script>
<style lang="scss" scoped>
.image {
flex-grow: 2;
.train-image {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
margin-top: 2.5em;
}
.image {
.train-image {
&__wrapper {
max-width: 380px;
width: 22em;
+3 -1
View File
@@ -1,7 +1,8 @@
import { IStore } from './types';
import { ICarWagon, ILocomotive, IStore } from './types';
import { defineStore } from 'pinia';
import { carDataList, isTrainPassenger, locoDataList, maxStockSpeed, totalLength, totalMass } from './utils/vehicleUtils';
export const useStore = defineStore({
id: 'store',
state: () =>
@@ -9,6 +10,7 @@ export const useStore = defineStore({
chosenCar: null,
chosenLoco: null,
chosenCargo: null,
chosenVehicle: null,
showSupporter: false,
imageLoading: false,
-1
View File
@@ -24,7 +24,6 @@ html {
margin: 0;
padding: 0;
min-height: 100vh;
font-family: "Lato", sans-serif;
background-color: $bgColor;
+5
View File
@@ -1,8 +1,12 @@
export type Vehicle = ILocomotive | ICarWagon;
export interface IStore {
chosenCar: ICarWagon | null;
chosenLoco: ILocomotive | null;
chosenCargo: ICargo | null;
chosenVehicle: Vehicle | null;
showSupporter: boolean;
imageLoading: boolean;
@@ -70,3 +74,4 @@ export interface IStock {
count: number;
imgSrc: string;
}