Zmiana wyglądów filtrów

This commit is contained in:
2020-07-11 01:01:52 +02:00
parent e5235b6907
commit f5db877129
7 changed files with 447 additions and 358 deletions
+4
View File
@@ -75,6 +75,10 @@ export default Vue.extend({
@import "./styles/responsive.scss"; @import "./styles/responsive.scss";
@import "./styles/variables.scss"; @import "./styles/variables.scss";
:root {
font-size: 16px;
}
html { html {
scroll-behavior: smooth; scroll-behavior: smooth;
} }
+3
View File
@@ -0,0 +1,3 @@
<svg width="34" height="34" viewBox="0 0 34 34" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 2L32 32M32 2L2 32" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel"/>
</svg>

After

Width:  |  Height:  |  Size: 215 B

+1 -1
View File
@@ -273,7 +273,7 @@ export default Vue.extend({
font-size: calc(0.6rem + 0.35vw); font-size: calc(0.6rem + 0.35vw);
@include smallScreen() { @include smallScreen() {
font-size: 0.65rem; font-size: 0.75rem;
} }
thead th { thead th {
+1 -1
View File
@@ -37,7 +37,7 @@ export default Vue.extend({
} }
.button { .button {
font-size: 0.8em; font-size: 0.9em;
img { img {
width: 1.3em; width: 1.3em;
+355 -258
View File
@@ -1,168 +1,51 @@
<template> <template>
<transition name="slide"> <transition name="slide">
<div class="list-filter"> <section class="filter-card">
<div class="exit" @click="exitFilters">X</div> <div class="card-exit" @click="exit">
<div class="list-filter-title">FILTRY</div> <img :src="require('@/assets/icon-exit.svg')" alt="exit icon" />
<ul class="grid"> </div>
<li class="grid-row">
<div class="grid-col" v-for="(el, i) in gridElements" :key="i">
<div class="grid-item">
<div class="item-title">{{el.title}}</div>
<div class="item-content"> <div class="card-title flex">FILTRY</div>
<div class="item-input" v-for="(item, i) in el.items" :key="i">
<div class="card-options">
<div class="option" v-for="(option, i) in options" :key="i">
<label class="option-label">
<input <input
:type="el.type" class="option-input"
:id="item.id"
:name="item.name"
v-model="item.value"
checked
@change="handleChange"
/>
<label :for="item.id">{{ item.content }}</label>
</div>
</div>
</div>
</div>
</li>
<li class="grid-row">
<div class="grid-col">
<div class="grid-item">
<div class="item-title">Poziomy dyżurnego</div>
<div class="item-content centered">
<div class="item-input" style="text-align: center;">
<input
v-model="levelFrom"
type="number"
name="level-from"
min="0"
max="25"
@change="handleInput"
/>
<span>&nbsp;do&nbsp;</span>
<input
v-model="levelTo"
type="number"
name="level-to"
min="0"
max="20"
value="20"
@change="handleInput"
/>
</div>
</div>
</div>
</div>
</li>
<li class="grid-row">
<div class="grid-col">
<div class="grid-item">
<div class="item-title">
Szlaki jednotorowe
<div>(minimum)</div>
</div>
<div class="item-content">
<div class="item-input">
<input
v-model="oneWay"
type="checkbox" type="checkbox"
id="no-1track" :name="option.name"
name="no-1track" :id="option.id"
checked v-model="option.value"
@change="handleChange" @change="handleChange"
/> />
<label for="no-1track">Jednotory</label> <span class="option-content" :class="option.section">{{option.content}}</span>
</label>
</div>
</div> </div>
<div class="item-input"> <div class="card-sliders">
<div class="slider" v-for="(slider, i) in sliders" :key="i">
<input <input
v-model="oneWayCatenary" class="slider-input"
type="number" type="range"
name="1track-e" :name="slider.name"
min="0" :id="slider.id"
max="5" :min="slider.minRange"
placeholder="0" :max="slider.maxRange"
v-model="slider.value"
@change="handleInput" @change="handleInput"
/> />
<span>&nbsp;Zelektryfikowane</span>
</div>
<div class="item-input"> <span class="slider-value">{{slider.value}}</span>
<input
v-model="oneWayOther" <div class="slider-content">{{slider.content}}</div>
type="number"
name="1track-ne"
min="0"
max="5"
placeholder="0"
@change="handleInput"
/>
<span>&nbsp;Niezelektryfikowane</span>
</div>
</div>
</div> </div>
</div> </div>
<div class="grid-col"> <div class="card-reset flex">
<div class="grid-item">
<div class="item-title">
Szlaki dwutorowe
<div>(minimum)</div>
</div>
<div class="item-content">
<div class="item-input">
<input
v-model="twoWay"
type="checkbox"
id="no-2track"
name="no-2track"
ref="2track"
checked
@change="handleChange"
/>
<label for="no-2track">Dwutory</label>
</div>
<div class="item-input">
<input
v-model="twoWayCatenary"
type="number"
name="2track-e"
min="0"
max="5"
placeholder="0"
@change="handleInput"
/>
<span>&nbsp;Zelektryfikowane</span>
</div>
<div class="item-input">
<input
v-model="twoWayOther"
type="number"
name="2track-ne"
min="0"
max="5"
placeholder="0"
@change="handleInput"
/>
<span>&nbsp;Niezelektryfikowane</span>
</div>
</div>
</div>
</div>
</li>
<li class="grid-row">
<button class="button" @click="reset">RESET FILTRÓW</button> <button class="button" @click="reset">RESET FILTRÓW</button>
</li>
</ul>
</div> </div>
</section>
</transition> </transition>
</template> </template>
@@ -172,119 +55,170 @@ import { mapActions } from "vuex";
export default Vue.extend({ export default Vue.extend({
name: "list-filter", name: "list-filter",
watch: {
gridElements: {
handler: (v1, v2) => {},
deep: true
}
},
data: () => ({ data: () => ({
oneWay: true, options: [
twoWay: true,
levelFrom: 0,
levelTo: 20,
oneWayCatenary: 0,
oneWayOther: 0,
twoWayCatenary: 0,
twoWayOther: 0,
gridElements: {
access: {
title: "Dostępność",
type: "checkbox",
items: [
{ {
id: "is-default", id: "is-default",
value: true,
name: "default", name: "default",
content: "w paczce z grą" section: "access",
value: true,
defaultValue: true,
content: "W PACZCE"
}, },
{ {
id: "not-default", id: "not-default",
value: true,
name: "notDefault", name: "notDefault",
content: "poza paczką z grą" section: "access",
value: true,
defaultValue: true,
content: "POZA PACZKĄ"
}, },
{ {
id: "non-public", id: "non-public",
value: true,
name: "nonPublic", name: "nonPublic",
content: "niepubliczna" section: "access",
} value: true,
] defaultValue: true,
content: "NIEPUBLICZNA"
}, },
control: {
title: "Sterowanie",
type: "checkbox",
items: [
{ {
id: "SPK", id: "SPK",
value: true,
name: "SPK", name: "SPK",
section: "control",
value: true,
defaultValue: true,
content: "SPK" content: "SPK"
}, },
{ {
id: "SCS", id: "SCS",
value: true,
name: "SCS", name: "SCS",
section: "control",
value: true,
defaultValue: true,
content: "SCS" content: "SCS"
}, },
{ {
id: "by-hand", id: "by-hand",
value: true,
name: "ręczne", name: "ręczne",
content: "ręczne" section: "control",
value: true,
defaultValue: true,
content: "RĘCZNE"
}, },
{ {
id: "levers", id: "levers",
value: true,
name: "mechaniczne", name: "mechaniczne",
content: "mechaniczne" section: "control",
} value: true,
] defaultValue: true,
content: "MECHANICZNE"
}, },
signals: {
title: "Sygnalizacja",
type: "checkbox",
items: [
{ {
id: "modern", id: "modern",
value: true,
name: "współczesna", name: "współczesna",
content: "współczesna" section: "signals",
value: true,
defaultValue: true,
content: "WSPÓŁCZESNA"
}, },
{ {
id: "semaphore", id: "semaphore",
value: true,
name: "kształtowa", name: "kształtowa",
content: "kształtowa" section: "signals",
value: true,
defaultValue: true,
content: "KSZTAŁTOWA"
}, },
{ {
id: "mixed", id: "mixed",
value: true,
name: "mieszana", name: "mieszana",
content: "mieszana" section: "signals",
value: true,
defaultValue: true,
content: "MIESZANA"
}, },
{ {
id: "historic", id: "historic",
value: true,
name: "historyczna", name: "historyczna",
content: "historyczna" section: "signals",
} value: true,
] defaultValue: true,
content: "HISTORYCZNA"
}, },
status: { {
title: "Status", id: "free",
type: "checkbox", name: "free",
section: "status",
value: true,
defaultValue: true,
content: "WOLNA"
},
{
id: "occupied",
name: "occupied",
section: "status",
value: true,
defaultValue: true,
content: "ZAJĘTA"
},
{
id: "ending",
name: "ending",
section: "status",
value: true,
defaultValue: true,
content: "KOŃCZY"
}
],
items: [] sliders: [
} {
id: "min-level",
name: "minLevel",
minRange: 0,
maxRange: 20,
value: 0,
defaultValue: 0,
content: "MINIMALNY WYMAGANY POZIOM DYŻURNEGO"
},
{
id: "min-oneway-e",
name: "minOneWayCatenary",
minRange: 0,
maxRange: 5,
value: 0,
defaultValue: 0,
content: "MINIMALNA LICZBA SZLAKÓW JEDNOTOROWYCH ZELEKTRYFIKOWANYCH"
},
{
id: "min-oneway-ne",
name: "minOneWay",
minRange: 0,
maxRange: 5,
value: 0,
defaultValue: 0,
content: "MINIMALNA LICZBA SZLAKÓW JEDNOTOROWYCH NIEZELEKTRYFIKOWANYCH"
},
{
id: "min-twoway-e",
name: "minTwoWayCatenary",
minRange: 0,
maxRange: 5,
value: 0,
defaultValue: 0,
content: "MINIMALNA LICZBA SZLAKÓW DWUTOROWYCH ZELEKTRYFIKOWANYCH"
},
{
id: "min-twoway-ne",
name: "minTwoWay",
minRange: 0,
maxRange: 5,
value: 0,
defaultValue: 0,
content: "MINIMALNA LICZBA SZLAKÓW DWUTOROWYCH NIEZELEKTRYFIKOWANYCH"
} }
]
}), }),
props: ["exit"], props: ["exit"],
methods: { methods: {
@@ -299,20 +233,8 @@ export default Vue.extend({
}); });
}, },
reset() { reset() {
for (const [key, value] of Object.entries(this.gridElements)) { this.options.forEach(option => (option.value = option.defaultValue));
for (const item of this.gridElements[key].items) { this.sliders.forEach(slider => (slider.value = slider.defaultValue));
item.value = true;
}
}
this.oneWay = true;
this.twoWay = true;
this.levelFrom = 0;
this.levelTo = 20;
this.oneWayCatenary = 0;
this.oneWayOther = 0;
this.twoWayCatenary = 0;
this.twoWayOther = 0;
this.resetFilters(); this.resetFilters();
}, },
@@ -337,74 +259,249 @@ export default Vue.extend({
opacity: 0; opacity: 0;
} }
.list-filter { .filter-card {
position: fixed; position: fixed;
top: 50%; top: 50%;
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
z-index: 0;
overflow: auto; overflow: auto;
max-height: 90%; max-height: 95vh;
padding: 0.5em; padding: 0.5em;
max-width: 600px;
width: 65%;
background: rgba(black, 0.85); background: #262a2e;
white-space: nowrap;
font-size: calc(0.6rem + 0.4vw); font-size: calc(0.75rem + 0.4vw);
@include smallScreen() { @include smallScreen() {
width: 100vw; width: 85vw;
font-size: 1em; font-size: 1em;
} }
box-shadow: 0 0 15px 5px #474747;
} }
.exit { .card {
&-exit {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
padding: 0.4rem; margin: 0.8em;
font-size: calc(1rem + 0.4vw);
img {
width: 1.1em;
}
cursor: pointer; cursor: pointer;
}
&-title {
font-size: 2em;
font-weight: 700;
color: $accentCol;
margin: 0.5em 0;
}
&-options {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(6em, 1fr));
padding: 0 1.5em;
}
&-sliders {
margin-top: 1em;
}
&-reset {
margin-top: 0.7em;
}
} }
.list-filter-title { .option {
text-align: center; margin: 0.3em;
font-size: 1.9em;
font-weight: bold;
}
.grid { &-input {
&-row { display: none;
display: flex;
justify-content: center;
@include smallScreen() { &:not(:checked) + span {
flex-wrap: wrap; background-color: #585858;
&::before {
box-shadow: none;
}
} }
} }
&-col { &-content {
padding: 0.3rem;
}
&-item {
user-select: none; user-select: none;
-moz-user-select: none; -moz-user-select: none;
-webkit-user-select: none; -webkit-user-select: none;
}
}
.item { width: 100%;
&-title {
text-align: center; text-align: center;
margin-bottom: 0.5rem;
font-weight: bold; cursor: pointer;
color: $accentCol;
padding: 0.6em 0.5em;
border-radius: 0.4em;
font-size: 0.65em;
background-color: #333;
display: inline-block;
position: relative;
transition: all 0.2s;
&.access {
background-color: #e03b07;
&::before {
box-shadow: 0 0 6px 1px #e03b07;
}
}
&.control {
background-color: #0085ff;
&::before {
box-shadow: 0 0 6px 1px #0085ff;
}
}
&.signals {
background-color: #b000bf;
&::before {
box-shadow: 0 0 6px 1px #b000bf;
}
}
&.status {
background-color: #05b702;
&::before {
box-shadow: 0 0 6px 1px #05b702;
}
}
&::before {
position: absolute;
content: "";
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: inherit;
}
} }
} }
button.button { .slider {
margin-top: 0.5em; display: flex;
padding: 0.5em;
&-value {
display: flex;
justify-content: center;
align-items: center;
color: $accentCol;
margin-right: 0.3em;
padding: 0.1em 0.2em;
font-size: 1.1em;
font-weight: 500;
border-radius: 0.2em;
}
&-content {
display: flex;
align-items: center;
font-size: 0.6em;
}
&-input {
-webkit-appearance: none;
appearance: none;
background: none;
border: none;
outline: none;
min-width: 25%;
&::-webkit-slider-thumb {
-webkit-appearance: none;
height: 20px;
width: 20px;
margin-top: -7px;
border-radius: 50%;
background: white;
border: 4px solid $accentCol;
@include smallScreen() {
width: 15px;
height: 15px;
margin-top: -5px;
border: 3px solid $accentCol;
}
}
&::-moz-range-thumb {
height: 15px;
width: 15px;
border-radius: 50%;
background: white;
border: 4px solid $accentCol;
cursor: pointer;
@include smallScreen() {
width: 15px;
height: 15px;
border: 3px solid $accentCol;
}
}
&::-webkit-slider-runnable-track {
width: 100%;
height: 5px;
cursor: pointer;
background: #ffffff;
border-radius: 1em;
}
&::-moz-range-track {
width: 100%;
height: 5px;
cursor: pointer;
background: #ffffff;
border-radius: 1em;
}
&::-ms-track {
width: 100%;
height: 5px;
cursor: pointer;
background: #ffffff;
border-radius: 1em;
}
}
} }
</style> </style>
+22 -37
View File
@@ -23,9 +23,10 @@ class Store extends VuexModule {
signalType: string; signalType: string;
controlType: string; controlType: string;
default: boolean; default: boolean;
nonPublic: boolean nonPublic: boolean;
routes: { oneWay: { catenary: number; noCatenary: number; }, twoWay: { catenary: number; noCatenary: number; } }; routes: { oneWay: { catenary: number; noCatenary: number; }, twoWay: { catenary: number; noCatenary: number; } };
online: boolean; online: boolean;
occupiedTo: string;
}[] = []; }[] = [];
private filteredStations: {}[] = []; private filteredStations: {}[] = [];
@@ -42,38 +43,19 @@ class Store extends VuexModule {
"kształtowa": false, "kształtowa": false,
"historyczna": false, "historyczna": false,
"mieszana": false, "mieszana": false,
"levelFrom": 0, "minLevel": 0,
"levelTo": 20, "minOneWayCatenary": 0,
"1track-ne": 0, "minOneWay": 0,
"2track-ne": 0, "minTwoWayCatenary": 0,
"1track-e": 0, "minTwoWay": 0,
"2track-e": 0,
"no-1track": false, "no-1track": false,
"no-2track": false "no-2track": false,
"free": false,
"occupied": false,
"ending": false
} as const; } as const;
private filters = { private filters: any = this.filterInitStates;
"default": false,
"notDefault": false,
"nonPublic": false,
"SPK": false,
"SCS": false,
"ręczne": false,
"mechaniczne": false,
"współczesna": false,
"kształtowa": false,
"historyczna": false,
"mieszana": false,
"levelFrom": 0,
"levelTo": 20,
"1track-ne": 0,
"2track-ne": 0,
"1track-e": 0,
"2track-e": 0,
"no-1track": false,
"no-2track": false
} as any;
get getStationCount(): number { get getStationCount(): number {
return this.stationCount; return this.stationCount;
@@ -210,21 +192,23 @@ class Store extends VuexModule {
if ((station.nonPublic || !station.reqLevel) && this.filters['nonPublic']) return false; if ((station.nonPublic || !station.reqLevel) && this.filters['nonPublic']) return false;
if (!station.reqLevel) return true; if (!station.reqLevel) return true;
if (station.online && this.filters['occupied']) return false;
if (!station.online && this.filters['free']) return false;
if (station.online && station.occupiedTo == "KOŃCZY" && this.filters['ending']) return false;
if (station.default && this.filters['default']) return false; if (station.default && this.filters['default']) return false;
if (!station.default && this.filters['notDefault']) return false; if (!station.default && this.filters['notDefault']) return false;
if (station.reqLevel < this.filters['level-from']) return false; if (station.reqLevel < this.filters['minLevel']) return false;
if (station.reqLevel > this.filters['level-to']) return false;
if (this.filters["no-1track"] && (station.routes.oneWay.catenary != 0 || station.routes.oneWay.noCatenary != 0)) return false; if (this.filters["no-1track"] && (station.routes.oneWay.catenary != 0 || station.routes.oneWay.noCatenary != 0)) return false;
if (this.filters["no-2track"] && (station.routes.twoWay.catenary != 0 || station.routes.twoWay.noCatenary != 0)) return false; if (this.filters["no-2track"] && (station.routes.twoWay.catenary != 0 || station.routes.twoWay.noCatenary != 0)) return false;
if (station.routes.oneWay.catenary < this.filters['1track-e']) return false; if (station.routes.oneWay.catenary < this.filters['minOneWayCatenary']) return false;
if (station.routes.oneWay.noCatenary < this.filters['1track-ne']) return false; if (station.routes.oneWay.noCatenary < this.filters['minOneWay']) return false;
if (station.routes.twoWay.catenary < this.filters['2track-e']) return false;
if (station.routes.twoWay.noCatenary < this.filters['2track-ne']) return false;
if (station.routes.twoWay.catenary < this.filters['minTwoWayCatenary']) return false;
if (station.routes.twoWay.noCatenary < this.filters['minTwoWay']) return false;
if (this.filters[station.controlType]) return false; if (this.filters[station.controlType]) return false;
if (this.filters[station.signalType]) return false; if (this.filters[station.signalType]) return false;
@@ -271,6 +255,7 @@ class Store extends VuexModule {
if (!toUpdate) { if (!toUpdate) {
this.stations[i].online = false; this.stations[i].online = false;
this.stations[i].occupiedTo = "WOLNA";
continue; continue;
} }
+1 -1
View File
@@ -6,5 +6,5 @@ $bgCol: #525252;
$errorCol: #ff1919; $errorCol: #ff1919;
$warningCol: #ff975b; $warningCol: #ff975b;
$accentCol: #ffc62b; $accentCol: #ffc014;
$accent2Col: #ff3d5d; $accent2Col: #ff3d5d;