Files
station-manager-2.0/src/components/RoutesModal.vue
T

334 lines
9.2 KiB
Vue

<template>
<div class="modal-bg" @click="closeRoutesModal"></div>
<div
v-if="sceneriesStore.currentStation"
class="modal routes-modal"
@keydown.esc="closeRoutesModal"
tabindex="0"
ref="modal"
>
<div class="modal-content">
<div class="modal-wrapper">
<h1 class="modal-header">
Szlaki na scenerii {{ sceneriesStore.currentStation.name }}
<button class="modal-exit" @click="closeRoutesModal">
<LucideX :size="20" />
</button>
</h1>
<ul class="route-list">
<li class="route" v-for="(route, i) in currentRoutes" :key="i">
<form action="javascript:void(0);">
<div style="display: flex; justify-content: space-between; align-items: center; gap: 1em">
<span> Szlak: <input type="text" v-model="route.routeName" /> </span>
<button class="route-delete-btn" @click="removeRoute(i)">
<LucideTrash />
</button>
</div>
<div>
<label :for="`${route.routeName}-internal`" style="display: inline-block">
<input
type="checkbox"
:name="`${route.routeName}-internal`"
:id="`${route.routeName}-internal`"
v-model="route.isInternal"
/>
WEWNĘTRZNY
</label>
&nbsp;
<label :for="`${route.routeName}-hidden`" style="display: inline-block">
<input
type="checkbox"
:name="`${route.routeName}-hidden`"
:id="`${route.routeName}-hidden`"
v-model="route.hidden"
/>
UKRYTY
</label>
</div>
<div>
<b>Liczba torów:</b>
<label class="radio-choice">
<input
type="radio"
:name="`${route.routeName}-tracks`"
:value="1"
:checked="route.routeTracks == 1"
v-model="route.routeTracks"
/>
<span>1</span>
</label>
<label class="radio-choice">
<input
type="radio"
:name="`${route.routeName}-tracks`"
:value="2"
:checked="route.routeTracks == 2"
v-model="route.routeTracks"
/>
<span>2</span>
</label>
</div>
<div>
<b>Elektryfikacja:</b>
<label class="radio-choice">
<input
type="radio"
:name="`${route.routeName}-electr`"
:value="true"
:checked="route.isElectric"
v-model="route.isElectric"
/>
<span>Tak</span>
</label>
<label class="radio-choice">
<input
type="radio"
:name="`${route.routeName}-electr`"
:value="false"
:checked="!route.isElectric"
v-model="route.isElectric"
/>
<span>Nie</span>
</label>
</div>
<div>
<b>Typ blokady:</b>
<label class="radio-choice">
<input
type="radio"
:name="`${route.routeName}-block`"
:id="`${route.routeName}-PBL`"
:value="false"
:checked="!route.isRouteSBL"
v-model="route.isRouteSBL"
/><span>PBL</span>
</label>
<label class="radio-choice">
<input
type="radio"
:name="`${route.routeName}-block`"
:id="`${route.routeName}-SBL`"
:value="true"
:checked="route.isRouteSBL"
v-model="route.isRouteSBL"
/><span>SBL</span>
</label>
</div>
<div v-if="route.routeTracks == 1">Prędkość: <input type="number" v-model="route.routeSpeed" /> km/h</div>
<div v-if="route.routeTracks == 2">
Prędkość (wjazd na sc.): <input type="number" v-model="route.routeSpeed" /> km/h
</div>
<div v-if="route.routeTracks == 2">
Prędkość (wyjazd ze sc.): <input type="number" v-model="route.routeSpeedExit" /> km/h
</div>
<div>Długość: <input type="number" v-model="route.routeLength" /> m</div>
<div>Linia kolejowa: <input type="number" v-model="route.realLineNo" /></div>
</form>
</li>
</ul>
</div>
<div class="routes-actions">
<button @click="saveRoutes">Zapisz</button>
<button @click="addNewRoute">Dodaj szlak</button>
<button @click="closeRoutesModal">Zamknij</button>
</div>
</div>
</div>
</template>
<script lang="ts">
import { Ref, defineComponent, ref } from 'vue';
import changeMixin from '../mixins/changeMixin';
import { SceneryRoutesInfo } from '../types/sceneries.types';
import { useSceneriesStore } from '../stores/sceneries.store';
import { LucideTrash, LucideX } from 'lucide-vue-next';
export default defineComponent({
components: { LucideX, LucideTrash },
setup() {
const sceneriesStore = useSceneriesStore();
const currentRoutes: Ref<SceneryRoutesInfo[]> = ref([]);
const routeBackup: Ref<SceneryRoutesInfo[]> = ref([]);
return {
sceneriesStore,
routeBackup,
currentRoutes,
};
},
mixins: [changeMixin],
mounted() {
if (this.sceneriesStore.currentStation) {
// unrefed copy of routesInfo object
this.currentRoutes = JSON.parse(JSON.stringify(this.sceneriesStore.currentStation.routesInfo));
this.routeBackup = [...this.sceneriesStore.currentStation.routesInfo];
(this.$refs['modal'] as HTMLElement).focus();
}
},
methods: {
closeRoutesModal() {
this.sceneriesStore.currentStation = null;
},
addNewRoute() {
this.currentRoutes.push({
routeName: '-',
isElectric: true,
isInternal: false,
isRouteSBL: false,
routeLength: 0,
routeSpeed: 0,
routeSpeedExit: 0,
routeTracks: 1,
});
this.saveRoutes();
},
removeRoute(index: number) {
this.currentRoutes = this.currentRoutes.filter((_, i) => i !== index);
this.saveRoutes();
},
parseRoutes() {
const routeString = this.sceneriesStore.currentStation?.routesInfo
.map(
(route) =>
`${route.isInternal ? '!' : ''}${route.routeName.trim()}_${route.routeTracks}${
route.isElectric ? 'E' : 'N'
}${route.isRouteSBL ? 'S' : 'P'}:${route.routeSpeed || 0}:${route.routeLength || 0}`,
)
.join(';');
return routeString;
},
saveRoutes() {
const index = this.sceneriesStore.stationList.findIndex(
(station) => station.name === this.sceneriesStore.currentStation?.name,
);
if (index == -1) return;
this.addChange(this.sceneriesStore.currentStation!, 'routesInfo', this.routeBackup, this.currentRoutes);
this.sceneriesStore.stationList[index]['routesInfo'] = this.currentRoutes;
},
},
});
</script>
<style lang="scss" scoped>
@use '../styles/modal';
.routes-modal input {
display: inline;
margin: 0.25em 0;
color: black;
font-size: 1em;
max-width: 120px;
}
label.radio-choice {
display: inline-block;
position: relative;
background-color: #333;
margin: 0.25em;
cursor: pointer;
input {
position: absolute;
opacity: 0;
cursor: pointer;
}
span {
display: flex;
padding: 0.25em 0.75em;
}
input:checked + span {
color: gold;
font-weight: bold;
}
input:focus-visible + span {
outline: 1px solid white;
}
}
.modal-content {
display: grid;
grid-template-rows: 1fr auto;
height: 100%;
}
ul.route-list {
list-style: none;
padding: 0 1em;
margin: 0;
overflow: auto;
}
ul.route-list li {
padding: 0.65em;
margin: 0.5em 0;
position: relative;
background-color: #222;
}
ul.route-list li > form {
display: flex;
flex-direction: column;
gap: 0.25em;
}
.routes-actions {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 0.5em;
width: 100%;
padding: 0.5em 0;
text-align: center;
}
.routes-actions button {
font-size: 1.2em;
margin: 0;
}
.route-delete-btn {
background-color: #444;
border-radius: 0.5em;
&:hover {
background-color: #555;
}
}
</style>