mirror of
https://github.com/Spythere/pojazdownik.git
synced 2026-05-03 05:18:10 +00:00
Layout
This commit is contained in:
+69
-35
@@ -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>
|
||||
©
|
||||
<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>
|
||||
©
|
||||
<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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -24,7 +24,6 @@ html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
min-height: 100vh;
|
||||
font-family: "Lato", sans-serif;
|
||||
|
||||
background-color: $bgColor;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user