mirror of
https://github.com/Spythere/stacjownik.git
synced 2026-05-03 13:28:11 +00:00
refactor: restructured station filters
This commit is contained in:
@@ -15,7 +15,6 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { useStationFiltersStore } from '../../store/stationFiltersStore';
|
||||
|
||||
interface FilterOption {
|
||||
id: string;
|
||||
@@ -40,15 +39,9 @@ export default defineComponent({
|
||||
|
||||
emits: ['update:optionValue'],
|
||||
|
||||
setup() {
|
||||
return {
|
||||
filterStore: useStationFiltersStore()
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
'option.value'() {
|
||||
this.filterStore.changeFilterValue(this.option.name, !this.option.value);
|
||||
// this.filterStore.changeFilterValue(this.option.name, !this.option.value);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -56,17 +49,17 @@ export default defineComponent({
|
||||
handleDbClick(e: Event) {
|
||||
e.preventDefault();
|
||||
|
||||
this.filterStore.lastClickedFilterId = this.option.id;
|
||||
// this.filterStore.lastClickedFilterId = this.option.id;
|
||||
// this.option.value = true;
|
||||
this.$emit('update:optionValue', true);
|
||||
|
||||
this.filterStore.inputs.options
|
||||
.filter((option) => {
|
||||
return option.section == this.option.section && option.id != this.option.id;
|
||||
})
|
||||
.forEach((option) => {
|
||||
option.value = !this.option.value;
|
||||
});
|
||||
// this.filterStore.inputs.options
|
||||
// .filter((option) => {
|
||||
// return option.section == this.option.section && option.id != this.option.id;
|
||||
// })
|
||||
// .forEach((option) => {
|
||||
// option.value = !this.option.value;
|
||||
// });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<button class="card-button btn--filled btn--image" @click="toggleCard">
|
||||
<img class="button_icon" src="/images/icon-filter2.svg" alt="filter icon" />
|
||||
<p>[F] {{ $t('options.filters') }}</p>
|
||||
<span class="active-indicator" v-if="!filterStore.areFiltersAtDefault"></span>
|
||||
<span class="active-indicator" v-if="!areFiltersAtDefaultComp"></span>
|
||||
</button>
|
||||
|
||||
<label for="scenery-search">
|
||||
@@ -36,26 +36,37 @@
|
||||
<section class="card_options">
|
||||
<div
|
||||
class="option-section"
|
||||
v-for="section in filterStore.inputs.optionSections"
|
||||
:key="section"
|
||||
v-for="(sectionFilters, sectionKey) in filtersSections"
|
||||
:key="sectionKey"
|
||||
>
|
||||
<h3 class="text--primary">
|
||||
{{ $t(`filters.sections.${section}`) }}
|
||||
{{ $t(`filters.sections.${sectionKey}`) }}
|
||||
|
||||
<button @click="filterStore.resetSectionOptions(section)">RESET</button>
|
||||
<button @click="resetSectionOptions(sectionKey)">RESET</button>
|
||||
</h3>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="section-inputs">
|
||||
<FilterOption
|
||||
v-for="(option, i) in filterStore.inputs.options.filter(
|
||||
(o) => o.section == section
|
||||
)"
|
||||
v-model:optionValue="option.value"
|
||||
:option="option"
|
||||
:key="i"
|
||||
/>
|
||||
<!--
|
||||
@dblclick="handleDbClick"
|
||||
|
||||
-->
|
||||
<div class="section-filters">
|
||||
<div
|
||||
v-for="filter in sectionFilters"
|
||||
@click="() => (filters[filter] = !filters[filter])"
|
||||
>
|
||||
<input
|
||||
:checked="filters[filter]"
|
||||
v-model="filters[filter]"
|
||||
type="checkbox"
|
||||
:class="sectionKey"
|
||||
:name="filter"
|
||||
/>
|
||||
<span>
|
||||
{{ $t(`filters.${filter}`) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -68,7 +79,7 @@
|
||||
<span>{{
|
||||
minimumHours == 0
|
||||
? $t('filters.now')
|
||||
: minimumHours < 8
|
||||
: minimumHours < 7
|
||||
? minimumHours + $t('filters.hour')
|
||||
: $t('filters.no-limit')
|
||||
}}</span>
|
||||
@@ -76,21 +87,21 @@
|
||||
</span>
|
||||
</section>
|
||||
|
||||
<datalist id="authors">
|
||||
<option v-for="(author, i) in authors" :key="i" :value="author"></option>
|
||||
</datalist>
|
||||
|
||||
<section class="card_authors-search">
|
||||
<h3 class="section-header">{{ $t('filters.authors-search') }}</h3>
|
||||
|
||||
<datalist id="authors" name="authors">
|
||||
<option v-for="(author, i) in authorsHint" :key="i" :value="author"></option>
|
||||
</datalist>
|
||||
|
||||
<form action="javascript:void(0);" @submit="handleAuthorsInput">
|
||||
<input
|
||||
type="text"
|
||||
id="author"
|
||||
list="authors"
|
||||
name="authors"
|
||||
v-model="authors"
|
||||
:placeholder="$t('filters.authors-placeholder')"
|
||||
v-model="authorsInputValue"
|
||||
@focus="preventKeyDown = true"
|
||||
@blur="preventKeyDown = false"
|
||||
/>
|
||||
@@ -100,19 +111,18 @@
|
||||
</section>
|
||||
|
||||
<section class="card_sliders">
|
||||
<div class="slider" v-for="(slider, i) in filterStore.inputs.sliders" :key="i">
|
||||
<div class="slider" v-for="(slider, i) in initSliders" :key="i">
|
||||
<input
|
||||
class="slider-input"
|
||||
type="range"
|
||||
:name="slider.name"
|
||||
:name="slider.id"
|
||||
:id="slider.id"
|
||||
:min="slider.minRange"
|
||||
:max="slider.maxRange"
|
||||
:step="slider.step"
|
||||
v-model="slider.value"
|
||||
@change="handleInput"
|
||||
v-model="filters[slider.id]"
|
||||
/>
|
||||
<span class="slider-value">{{ slider.value }}</span>
|
||||
<span class="slider-value">{{ filters[slider.id] }}</span>
|
||||
<div class="slider-content">
|
||||
{{ $t(`filters.sliders.${slider.id}`) }}
|
||||
</div>
|
||||
@@ -133,9 +143,9 @@
|
||||
|
||||
<button
|
||||
class="btn--action"
|
||||
:disabled="areFiltersAtDefaultComp"
|
||||
:data-disabled="areFiltersAtDefaultComp"
|
||||
@click="resetFilters"
|
||||
:disabled="filterStore.areFiltersAtDefault"
|
||||
:data-disabled="filterStore.areFiltersAtDefault"
|
||||
>
|
||||
[R] {{ $t('filters.reset') }}
|
||||
</button>
|
||||
@@ -151,12 +161,21 @@
|
||||
import { defineComponent, inject } from 'vue';
|
||||
import keyMixin from '../../mixins/keyMixin';
|
||||
import routerMixin from '../../mixins/routerMixin';
|
||||
import { useStationFiltersStore } from '../../store/stationFiltersStore';
|
||||
import { useMainStore } from '../../store/mainStore';
|
||||
|
||||
import FilterOption from './FilterOption.vue';
|
||||
import StorageManager from '../../managers/storageManager';
|
||||
|
||||
import {
|
||||
filtersSections,
|
||||
initSliders,
|
||||
initFilters,
|
||||
areFiltersAtDefault
|
||||
} from '../../managers/stationFilterManager';
|
||||
|
||||
import { StationFilterSection } from '../../managers/stationFilterManager';
|
||||
import { computed } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: { FilterOption },
|
||||
mixins: [keyMixin, routerMixin],
|
||||
@@ -165,8 +184,11 @@ export default defineComponent({
|
||||
saveOptions: false,
|
||||
STORAGE_KEY: 'options_saved',
|
||||
|
||||
authorsInputValue: '',
|
||||
filtersSections,
|
||||
initSliders,
|
||||
|
||||
minimumHours: 0,
|
||||
authors: '',
|
||||
|
||||
currentRegion: { id: '', value: '' },
|
||||
|
||||
@@ -180,12 +202,16 @@ export default defineComponent({
|
||||
setup() {
|
||||
const isVisible = inject('isFilterCardVisible');
|
||||
const store = useMainStore();
|
||||
const filterStore = useStationFiltersStore();
|
||||
|
||||
const filters = inject('StationsView_filters') as Record<string, any>;
|
||||
|
||||
const areFiltersAtDefaultComp = computed(() => areFiltersAtDefault(filters));
|
||||
|
||||
return {
|
||||
isVisible,
|
||||
store,
|
||||
filterStore
|
||||
filters,
|
||||
areFiltersAtDefaultComp
|
||||
};
|
||||
},
|
||||
|
||||
@@ -194,8 +220,6 @@ export default defineComponent({
|
||||
|
||||
if (StorageManager.isRegistered('onlineFromHours') && this.saveOptions) {
|
||||
this.minimumHours = StorageManager.getNumericValue('onlineFromHours');
|
||||
|
||||
this.changeNumericFilterValue('onlineFromHours', this.minimumHours);
|
||||
}
|
||||
|
||||
this.currentRegion = this.store.region;
|
||||
@@ -214,7 +238,7 @@ export default defineComponent({
|
||||
return true;
|
||||
},
|
||||
|
||||
authors() {
|
||||
authorsHint() {
|
||||
return this.store.stationList
|
||||
.reduce((acc, station) => {
|
||||
station.generalInfo?.authors?.forEach((author) => {
|
||||
@@ -258,35 +282,19 @@ export default defineComponent({
|
||||
this.scrollTop = (e.target as HTMLElement).scrollTop;
|
||||
},
|
||||
|
||||
handleInput(e: Event) {
|
||||
const target = e.target as HTMLInputElement;
|
||||
|
||||
this.filterStore.changeFilterValue(target.name, target.value);
|
||||
|
||||
if (this.saveOptions) StorageManager.setStringValue(target.name, target.value);
|
||||
},
|
||||
|
||||
handleAuthorsInput() {
|
||||
this.filterStore.changeFilterValue('authors', this.authorsInputValue);
|
||||
|
||||
if (this.saveOptions) StorageManager.setStringValue('authors', this.authorsInputValue);
|
||||
},
|
||||
|
||||
changeNumericFilterValue(name: string, value: number, saveToStorage = false) {
|
||||
this.filterStore.changeFilterValue(name, value);
|
||||
if (this.saveOptions && saveToStorage) StorageManager.setNumericValue(name, value);
|
||||
this.filters['authors'] = this.authors;
|
||||
// if (this.saveOptions) StorageManager.setStringValue('authors', target.value);
|
||||
},
|
||||
|
||||
subHour() {
|
||||
this.minimumHours = this.minimumHours < 1 ? 8 : this.minimumHours - 1;
|
||||
|
||||
this.changeNumericFilterValue('onlineFromHours', this.minimumHours, true);
|
||||
this.minimumHours = this.minimumHours < 1 ? 7 : this.minimumHours - 1;
|
||||
this.filters['onlineFromHours'] = this.minimumHours;
|
||||
},
|
||||
|
||||
addHour() {
|
||||
this.minimumHours = this.minimumHours > 7 ? 0 : this.minimumHours + 1;
|
||||
|
||||
this.changeNumericFilterValue('onlineFromHours', this.minimumHours, true);
|
||||
this.minimumHours = this.minimumHours > 6 ? 0 : this.minimumHours + 1;
|
||||
this.filters['onlineFromHours'] = this.minimumHours;
|
||||
},
|
||||
|
||||
saveFilters() {
|
||||
@@ -299,20 +307,26 @@ export default defineComponent({
|
||||
|
||||
StorageManager.registerStorage(this.STORAGE_KEY);
|
||||
|
||||
this.filterStore.inputs.options.forEach((option) =>
|
||||
StorageManager.setBooleanValue(option.name, !option.value)
|
||||
);
|
||||
this.filterStore.inputs.sliders.forEach((slider) =>
|
||||
StorageManager.setNumericValue(slider.name, slider.value)
|
||||
);
|
||||
Object.keys(this.filters).forEach((filterKey) => {
|
||||
StorageManager.setValue(filterKey, this.filters[filterKey]);
|
||||
});
|
||||
},
|
||||
|
||||
resetFilters() {
|
||||
this.authorsInputValue = '';
|
||||
|
||||
// Reset local model values
|
||||
this.minimumHours = 0;
|
||||
this.changeNumericFilterValue('onlineFromHours', this.minimumHours, true);
|
||||
this.filterStore.resetFilters();
|
||||
this.authors = '';
|
||||
|
||||
// Reset global filters
|
||||
Object.keys(this.filters).forEach((filterKey) => {
|
||||
this.filters[filterKey] = (initFilters as any)[filterKey];
|
||||
});
|
||||
},
|
||||
|
||||
resetSectionOptions(key: string) {
|
||||
filtersSections[key as StationFilterSection].forEach((filter) => {
|
||||
this.filters[filter] = (initFilters as any)[filter];
|
||||
});
|
||||
},
|
||||
|
||||
closeCard() {
|
||||
@@ -374,28 +388,6 @@ h3.section-header {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.card_regions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
label > input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
label > span {
|
||||
padding: 0.25em 0.5em;
|
||||
margin: 0 0.25em;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
background-color: gray;
|
||||
|
||||
&.checked {
|
||||
background-color: seagreen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card_timestamp {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -441,6 +433,52 @@ h3.section-header {
|
||||
}
|
||||
}
|
||||
|
||||
.section-filters {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 0.5em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.section-filters > div {
|
||||
position: relative;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
|
||||
span {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 0.25em;
|
||||
font-weight: bold;
|
||||
background-color: forestgreen;
|
||||
}
|
||||
|
||||
span:hover {
|
||||
background-color: #22aa22;
|
||||
}
|
||||
|
||||
input[type='checkbox'] {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
|
||||
&:checked + span {
|
||||
background-color: #444;
|
||||
|
||||
&:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
}
|
||||
|
||||
&:focus-visible + span {
|
||||
outline: 1px solid $accentCol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card_actions {
|
||||
padding: 0.5em;
|
||||
|
||||
@@ -475,19 +513,6 @@ h3.section-header {
|
||||
}
|
||||
}
|
||||
|
||||
.section-inputs {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 0.5em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.quick-actions div {
|
||||
display: flex;
|
||||
margin: 1em 0;
|
||||
gap: 1em;
|
||||
}
|
||||
|
||||
.slider {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<section class="station_table">
|
||||
<Loading
|
||||
v-if="apiStore.dataStatuses.connection == Status.Loading && displayedStations.length == 0"
|
||||
v-if="apiStore.dataStatuses.connection == Status.Loading && filteredStationList.length == 0"
|
||||
/>
|
||||
|
||||
<div class="table_wrapper" v-else-if="displayedStations.length > 0">
|
||||
<div class="table_wrapper" v-else-if="filteredStationList.length > 0">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -20,8 +20,8 @@
|
||||
|
||||
<img
|
||||
class="sort-icon"
|
||||
v-if="sorterActive.headerName == headerName"
|
||||
:src="`/images/icon-arrow-${sorterActive.dir == 1 ? 'asc' : 'desc'}.svg`"
|
||||
v-if="activeSorter.headerName == headerName"
|
||||
:src="`/images/icon-arrow-${activeSorter.dir == 1 ? 'asc' : 'desc'}.svg`"
|
||||
alt="sort icon"
|
||||
/>
|
||||
</span>
|
||||
@@ -43,8 +43,8 @@
|
||||
|
||||
<img
|
||||
class="sort-icon"
|
||||
v-if="sorterActive.headerName == headerName"
|
||||
:src="`/images/icon-arrow-${sorterActive.dir == 1 ? 'asc' : 'desc'}.svg`"
|
||||
v-if="activeSorter.headerName == headerName"
|
||||
:src="`/images/icon-arrow-${activeSorter.dir == 1 ? 'asc' : 'desc'}.svg`"
|
||||
alt="sort icon"
|
||||
/>
|
||||
</span>
|
||||
@@ -54,7 +54,7 @@
|
||||
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="station in displayedStations"
|
||||
v-for="station in filteredStationList"
|
||||
:class="{ 'last-selected': lastSelectedStationName == station.name }"
|
||||
:key="station.name"
|
||||
@click.left="setScenery(station.name)"
|
||||
@@ -309,20 +309,21 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { defineComponent, inject, computed } from 'vue';
|
||||
import StationStatusBadge from '../Global/StationStatusBadge.vue';
|
||||
import dateMixin from '../../mixins/dateMixin';
|
||||
import styleMixin from '../../mixins/styleMixin';
|
||||
import { useStationFiltersStore } from '../../store/stationFiltersStore';
|
||||
import { useMainStore } from '../../store/mainStore';
|
||||
import Loading from '../Global/Loading.vue';
|
||||
import { HeadIdsTypes, headIconsIds, headIds } from '../../scripts/data/stationHeaderNames';
|
||||
import StationStatusBadge from '../Global/StationStatusBadge.vue';
|
||||
import { Station, Status } from '../../typings/common';
|
||||
import { Status } from '../../typings/common';
|
||||
import { useApiStore } from '../../store/apiStore';
|
||||
import { useTooltipStore } from '../../store/tooltipStore';
|
||||
import { filterStations, sortStations } from '../../scripts/utils/stationFilterUtils';
|
||||
import { ActiveSorter, HeadIdsType, headIconsIds, headIds } from './typings';
|
||||
|
||||
export default defineComponent({
|
||||
emits: ['toggleDonationModal'],
|
||||
|
||||
components: { Loading, StationStatusBadge },
|
||||
mixins: [styleMixin, dateMixin],
|
||||
|
||||
@@ -332,35 +333,36 @@ export default defineComponent({
|
||||
lastSelectedStationName: ''
|
||||
}),
|
||||
|
||||
computed: {
|
||||
sorterActive() {
|
||||
return this.stationFiltersStore.sorterActive;
|
||||
},
|
||||
|
||||
displayedStations() {
|
||||
return this.stationFiltersStore.filteredStationList;
|
||||
}
|
||||
},
|
||||
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
const apiStore = useApiStore();
|
||||
const tooltipStore = useTooltipStore();
|
||||
|
||||
const stationFiltersStore = useStationFiltersStore();
|
||||
const filters = inject('StationsView_filters') as Record<string, any>;
|
||||
const activeSorter = inject('StationsView_activeSorter') as ActiveSorter;
|
||||
|
||||
const filteredStationList = computed(() =>
|
||||
mainStore.allStationInfo
|
||||
.filter((station) => filterStations(station, filters))
|
||||
.sort((a, b) => sortStations(a, b, activeSorter))
|
||||
);
|
||||
// const areFiltersAtDefault = computed(() => {
|
||||
|
||||
// })
|
||||
|
||||
return {
|
||||
Status: Status.Data,
|
||||
stationFiltersStore,
|
||||
mainStore,
|
||||
apiStore,
|
||||
tooltipStore
|
||||
tooltipStore,
|
||||
filteredStationList,
|
||||
activeSorter
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
setScenery(name: string) {
|
||||
const station = this.displayedStations.find((station) => station.name === name);
|
||||
const station = this.filteredStationList.find((station) => station.name === name);
|
||||
|
||||
if (!station) return;
|
||||
|
||||
@@ -388,10 +390,14 @@ export default defineComponent({
|
||||
window.open(url, '_blank');
|
||||
},
|
||||
|
||||
changeSorter(headerName: HeadIdsTypes) {
|
||||
changeSorter(headerName: HeadIdsType) {
|
||||
if (headerName == 'general') return;
|
||||
|
||||
this.stationFiltersStore.changeSorter(headerName);
|
||||
if (headerName == this.activeSorter.headerName)
|
||||
this.activeSorter.dir = -1 * this.activeSorter.dir;
|
||||
else this.activeSorter.dir = 1;
|
||||
|
||||
this.activeSorter.headerName = headerName;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5,56 +5,29 @@ export interface FilterOption {
|
||||
defaultValue: boolean;
|
||||
}
|
||||
|
||||
export interface Filter {
|
||||
[key: string]: boolean | number | string;
|
||||
default: boolean;
|
||||
notDefault: boolean;
|
||||
real: boolean;
|
||||
fictional: boolean;
|
||||
SPK: boolean;
|
||||
SCS: boolean;
|
||||
SPE: boolean;
|
||||
SUP: boolean;
|
||||
noSUP: boolean;
|
||||
ASDEK: boolean;
|
||||
noASDEK: boolean;
|
||||
ręczne: boolean;
|
||||
'ręczne+SPK': boolean;
|
||||
'ręczne+SCS': boolean;
|
||||
mechaniczne: boolean;
|
||||
'mechaniczne+SPK': boolean;
|
||||
'mechaniczne+SCS': boolean;
|
||||
SBL: boolean;
|
||||
PBL: boolean;
|
||||
współczesna: boolean;
|
||||
kształtowa: boolean;
|
||||
historyczna: boolean;
|
||||
mieszana: boolean;
|
||||
minLevel: number;
|
||||
maxLevel: number;
|
||||
minOneWayCatenary: number;
|
||||
minOneWay: number;
|
||||
minTwoWayCatenary: number;
|
||||
minTwoWay: number;
|
||||
minVmax: number;
|
||||
maxVmax: number;
|
||||
'no-1track': boolean;
|
||||
'no-2track': boolean;
|
||||
'include-selected': boolean;
|
||||
free: boolean;
|
||||
occupied: boolean;
|
||||
nonPublic: boolean;
|
||||
unavailable: boolean;
|
||||
abandoned: boolean;
|
||||
endingStatus: boolean;
|
||||
afkStatus: boolean;
|
||||
noSpaceStatus: boolean;
|
||||
unavailableStatus: boolean;
|
||||
unsignedStatus: boolean;
|
||||
authors: string;
|
||||
onlineFromHours: number;
|
||||
withActiveTimetables: boolean;
|
||||
withoutActiveTimetables: boolean;
|
||||
junction: boolean;
|
||||
nonJunction: boolean;
|
||||
export const headIds = [
|
||||
'station',
|
||||
'min-lvl',
|
||||
'status',
|
||||
'dispatcher',
|
||||
'dispatcher-lvl',
|
||||
'routes-single',
|
||||
'routes-double',
|
||||
'general'
|
||||
] as const;
|
||||
|
||||
export const headIconsIds = [
|
||||
'user',
|
||||
'like',
|
||||
'spawn',
|
||||
'timetableAll',
|
||||
'timetableUnconfirmed',
|
||||
'timetableConfirmed'
|
||||
] as const;
|
||||
|
||||
export type HeadIdsType = (typeof headIds)[number] | (typeof headIconsIds)[number];
|
||||
|
||||
export interface ActiveSorter {
|
||||
headerName: HeadIdsType;
|
||||
dir: number;
|
||||
}
|
||||
|
||||
+12
-13
@@ -174,9 +174,9 @@
|
||||
|
||||
"sections": {
|
||||
"quick": "QUICK FILTERS",
|
||||
"station-type": "STATION TYPE",
|
||||
"stationType": "STATION TYPE",
|
||||
"reality": "SCENERY REALITY",
|
||||
"package-access": "IN-GAME AVAILABILITY",
|
||||
"packageAccess": "IN-GAME AVAILABILITY",
|
||||
"access": "GENERAL AVAILABILITY",
|
||||
"control": "CONTROLS",
|
||||
"signals": "SIGNALLING",
|
||||
@@ -197,11 +197,11 @@
|
||||
|
||||
"title": "STATION FILTERS",
|
||||
"default": "IN-GAME",
|
||||
"not-default": "ADDITIONAL",
|
||||
"notDefault": "ADDITIONAL",
|
||||
"real": "REAL",
|
||||
"fictional": "FICTIONAL",
|
||||
"unavailable": "UNSUPPORTED",
|
||||
"non-public": "NON-PUBLIC",
|
||||
"nonPublic": "NON-PUBLIC",
|
||||
"abandoned": "ABANDONED",
|
||||
|
||||
"SPK": "SPK",
|
||||
@@ -211,7 +211,6 @@
|
||||
"SCS-R": "SCS + MANUAL",
|
||||
"SCS-M": "SCS + MECH.",
|
||||
"SPE": "SPE",
|
||||
|
||||
"manual": "MANUAL",
|
||||
"mechanical": "MECHANICAL",
|
||||
|
||||
@@ -238,14 +237,14 @@
|
||||
"nonJunction": "OTHER",
|
||||
|
||||
"sliders": {
|
||||
"min-lvl": "MIN. REQUIRED DISPATCHER LEVEL",
|
||||
"max-lvl": "MAX. REQUIRED DISPATCHER LEVEL",
|
||||
"min-vmax": "MIN. SCENERY ROUTE SPEED",
|
||||
"max-vmax": "MAX. SCENERY ROUTE SPEED",
|
||||
"routes-1t-cat": "MIN. CATENARY SINGLE TRACK ROUTES",
|
||||
"routes-1t-other": "MIN. OTHER SINGLE TRACK ROUTES",
|
||||
"routes-2t-cat": "MIN. CATENARY DOUBLE TRACK ROUTES",
|
||||
"routes-2t-other": "MIN. OTHER DOUBLE TRACK ROUTES"
|
||||
"minLevel": "MIN. REQUIRED DISPATCHER LEVEL",
|
||||
"maxLevel": "MAX. REQUIRED DISPATCHER LEVEL",
|
||||
"minVmax": "MIN. SCENERY ROUTE SPEED",
|
||||
"maxVmax": "MAX. SCENERY ROUTE SPEED",
|
||||
"minOneWayCatenary": "MIN. CATENARY SINGLE TRACK ROUTES",
|
||||
"minOneWay": "MIN. OTHER SINGLE TRACK ROUTES",
|
||||
"minTwoWayCatenary": "MIN. CATENARY DOUBLE TRACK ROUTES",
|
||||
"minTwoWay": "MIN. OTHER DOUBLE TRACK ROUTES"
|
||||
},
|
||||
|
||||
"authors-search": "SEARCH BY AUTHOR NAME (other filters apply):",
|
||||
|
||||
+12
-12
@@ -171,9 +171,9 @@
|
||||
|
||||
"sections": {
|
||||
"quick": "SZYBKIE FILTRY",
|
||||
"station-type": "RODZAJ STACJI",
|
||||
"stationType": "RODZAJ STACJI",
|
||||
"reality": "FIKCYJNOŚĆ SCENERII",
|
||||
"package-access": "DOSTĘPNOŚĆ W PACZCE",
|
||||
"packageAccess": "DOSTĘPNOŚĆ W PACZCE",
|
||||
"access": "DOSTĘPNOŚĆ OGÓLNA",
|
||||
"control": "TYP STEROWANIA",
|
||||
"signals": "TYP SYGNALIZACJI",
|
||||
@@ -194,11 +194,11 @@
|
||||
|
||||
"title": "FILTRUJ STACJE",
|
||||
"default": "DOMYŚLNA",
|
||||
"not-default": "POZA PACZKĄ",
|
||||
"notDefault": "POZA PACZKĄ",
|
||||
"real": "REALNA",
|
||||
"fictional": "FIKCYJNA",
|
||||
"unavailable": "NIEDOSTĘPNA",
|
||||
"non-public": "NIEPUBLICZNA",
|
||||
"nonPublic": "NIEPUBLICZNA",
|
||||
"abandoned": "WYCOFANA",
|
||||
|
||||
"SPK": "SPK",
|
||||
@@ -234,14 +234,14 @@
|
||||
"nonJunction": "INNE",
|
||||
|
||||
"sliders": {
|
||||
"min-lvl": "MIN. WYMAGANY POZIOM DYŻURNEGO",
|
||||
"max-lvl": "MAKS. WYMAGANY POZIOM DYŻURNEGO",
|
||||
"min-vmax": "MIN. PRĘDKOŚĆ SZLAKOWA",
|
||||
"max-vmax": "MAKS. PRĘDKOŚĆ SZLAKOWA",
|
||||
"routes-1t-cat": "SZLAKI JEDNOTOROWE ZELEKTR. (MINIMUM)",
|
||||
"routes-1t-other": "SZLAKI JEDNOTOROWE NIEZELEKTR. (MINIMUM)",
|
||||
"routes-2t-cat": "SZLAKI DWUTOROWE ZELEKTR. (MINIMUM)",
|
||||
"routes-2t-other": "SZLAKI DWUTOROWE NIEZELEKTR. (MINIMUM)"
|
||||
"minLevel": "MIN. WYMAGANY POZIOM DYŻURNEGO",
|
||||
"maxLevel": "MAKS. WYMAGANY POZIOM DYŻURNEGO",
|
||||
"minVmax": "MIN. PRĘDKOŚĆ SZLAKOWA",
|
||||
"maxVmax": "MAKS. PRĘDKOŚĆ SZLAKOWA",
|
||||
"minOneWayCatenary": "SZLAKI JEDNOTOROWE ZELEKTR. (MINIMUM)",
|
||||
"minOneWay": "SZLAKI JEDNOTOROWE NIEZELEKTR. (MINIMUM)",
|
||||
"minTwoWayCatenary": "SZLAKI DWUTOROWE ZELEKTR. (MINIMUM)",
|
||||
"minTwoWay": "SZLAKI DWUTOROWE NIEZELEKTR. (MINIMUM)"
|
||||
},
|
||||
|
||||
"authors-search": "SZUKAJ AUTORA (uwzględnia inne filtry):",
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
import StorageManager from './storageManager';
|
||||
|
||||
export const sections = [
|
||||
'status',
|
||||
'timetables',
|
||||
'reality',
|
||||
'packageAccess',
|
||||
'stationType',
|
||||
'access',
|
||||
'control',
|
||||
'blockades',
|
||||
'signals',
|
||||
'addons'
|
||||
] as const;
|
||||
|
||||
export const initFilters = {
|
||||
default: false,
|
||||
notDefault: false,
|
||||
real: false,
|
||||
fictional: false,
|
||||
SPK: false,
|
||||
SCS: false,
|
||||
SPE: false,
|
||||
SUP: false,
|
||||
noSUP: false,
|
||||
ASDEK: false,
|
||||
noASDEK: false,
|
||||
manual: false,
|
||||
'SPK-R': false,
|
||||
'SCS-R': false,
|
||||
mechanical: false,
|
||||
'SPK-M': false,
|
||||
'SCS-M': false,
|
||||
modern: false,
|
||||
semaphores: false,
|
||||
historical: false,
|
||||
mixed: false,
|
||||
SBL: false,
|
||||
PBL: false,
|
||||
'include-selected': false,
|
||||
'no-1track': false,
|
||||
'no-2track': false,
|
||||
free: true,
|
||||
occupied: false,
|
||||
nonPublic: false,
|
||||
unavailable: true,
|
||||
abandoned: true,
|
||||
afkStatus: false,
|
||||
endingStatus: false,
|
||||
noSpaceStatus: false,
|
||||
unavailableStatus: false,
|
||||
unsignedStatus: false,
|
||||
withActiveTimetables: false,
|
||||
withoutActiveTimetables: false,
|
||||
junction: false,
|
||||
nonJunction: false,
|
||||
maxVmax: 200,
|
||||
minVmax: 0,
|
||||
onlineFromHours: 0,
|
||||
minLevel: 0,
|
||||
maxLevel: 20,
|
||||
minOneWayCatenary: 0,
|
||||
minOneWay: 0,
|
||||
minTwoWayCatenary: 0,
|
||||
minTwoWay: 0,
|
||||
authors: ''
|
||||
};
|
||||
|
||||
export const initSliders = [
|
||||
{ id: 'maxVmax', minRange: 0, maxRange: 200, step: 10 },
|
||||
{ id: 'minVmax', minRange: 0, maxRange: 200, step: 10 },
|
||||
{ id: 'minLevel', minRange: 0, maxRange: 20, step: 1 },
|
||||
{ id: 'maxLevel', minRange: 0, maxRange: 20, step: 1 },
|
||||
{ id: 'minOneWayCatenary', minRange: 0, maxRange: 5, step: 1 },
|
||||
{ id: 'minOneWay', minRange: 0, maxRange: 5, step: 1 },
|
||||
{ id: 'minTwoWayCatenary', minRange: 0, maxRange: 5, step: 1 },
|
||||
{ id: 'minTwoWay', minRange: 0, maxRange: 5, step: 1 }
|
||||
];
|
||||
|
||||
export type StationFilter = keyof typeof initFilters;
|
||||
export type StationFilterSection = (typeof sections)[number];
|
||||
|
||||
export const filtersSections: Record<StationFilterSection, StationFilter[]> = {
|
||||
status: ['free', 'occupied', 'endingStatus', 'afkStatus', 'noSpaceStatus', 'unavailableStatus'],
|
||||
timetables: ['withActiveTimetables', 'withoutActiveTimetables'],
|
||||
reality: ['real', 'fictional'],
|
||||
packageAccess: ['default', 'notDefault'],
|
||||
stationType: ['junction', 'nonJunction'],
|
||||
access: ['nonPublic', 'unavailable', 'abandoned'],
|
||||
addons: ['SUP', 'ASDEK', 'noSUP', 'noASDEK'],
|
||||
control: ['SPK', 'SCS', 'SPE', 'SPK-M', 'SCS-M', 'mechanical', 'SPK-R', 'SCS-R', 'manual'],
|
||||
blockades: ['SBL', 'PBL'],
|
||||
signals: ['modern', 'semaphores', 'mixed', 'historical']
|
||||
};
|
||||
|
||||
export function setupFilters(currentFilters: Record<string, any>) {
|
||||
if (!StorageManager.isRegistered('options_saved')) return;
|
||||
|
||||
Object.keys(currentFilters).forEach((filterKey) => {
|
||||
const savedValue = StorageManager.getValue(filterKey);
|
||||
|
||||
if (savedValue != null) {
|
||||
if (typeof currentFilters[filterKey] == 'boolean')
|
||||
currentFilters[filterKey] = savedValue === 'true';
|
||||
else if (typeof currentFilters[filterKey] == 'number')
|
||||
currentFilters[filterKey] = Number(savedValue);
|
||||
else currentFilters[filterKey] = savedValue.toString();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function areFiltersAtDefault(currentFilters: Record<string, any>) {
|
||||
return Object.keys(currentFilters).every(
|
||||
(filterKey) => currentFilters[filterKey] === initFilters[filterKey as keyof typeof initFilters]
|
||||
);
|
||||
}
|
||||
@@ -34,6 +34,10 @@ export default class StorageManager {
|
||||
window.localStorage.removeItem(key);
|
||||
}
|
||||
|
||||
static getValue(key: string) {
|
||||
return window.localStorage.getItem(key);
|
||||
}
|
||||
|
||||
static getBooleanValue(key: string): boolean {
|
||||
return window.localStorage.getItem(key) === 'true' ? true : false;
|
||||
}
|
||||
|
||||
@@ -1,21 +1 @@
|
||||
export const headIds = [
|
||||
'station',
|
||||
'min-lvl',
|
||||
'status',
|
||||
'dispatcher',
|
||||
'dispatcher-lvl',
|
||||
'routes-single',
|
||||
'routes-double',
|
||||
'general'
|
||||
] as const;
|
||||
|
||||
export const headIconsIds = [
|
||||
'user',
|
||||
'like',
|
||||
'spawn',
|
||||
'timetableAll',
|
||||
'timetableUnconfirmed',
|
||||
'timetableConfirmed'
|
||||
] as const;
|
||||
|
||||
export type HeadIdsTypes = (typeof headIds)[number] | (typeof headIconsIds)[number];
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Filter } from '../../components/StationsView/typings';
|
||||
import { Status } from '../../typings/common';
|
||||
import { HeadIdsTypes } from '../data/stationHeaderNames';
|
||||
import { ActiveSorter } from '../../components/StationsView/typings';
|
||||
import { ActiveScenery, StationGeneralInfo, Status } from '../../typings/common';
|
||||
import { Station } from '../../typings/common';
|
||||
|
||||
const dispatcherStatusPriority = [
|
||||
@@ -14,11 +13,137 @@ const dispatcherStatusPriority = [
|
||||
undefined
|
||||
];
|
||||
|
||||
export const sortStations = (
|
||||
a: Station,
|
||||
b: Station,
|
||||
sorter: { headerName: HeadIdsTypes; dir: number }
|
||||
) => {
|
||||
const filtersAssociations: Record<string, string> = {
|
||||
mechaniczne: 'mechanical',
|
||||
ręczne: 'manual',
|
||||
'mechaniczne+SPK': 'SPK-M',
|
||||
'ręczne+SPK': 'SPK-R',
|
||||
'mechaniczne+SCS': 'SCS-M',
|
||||
'ręczne+SCS': 'SCS-R',
|
||||
współczesna: 'modern',
|
||||
historyczna: 'historical',
|
||||
kształtowa: 'semaphores',
|
||||
mieszana: 'mixed'
|
||||
};
|
||||
|
||||
function filterStatusSection(
|
||||
filters: Record<string, any>,
|
||||
{ dispatcherStatus, dispatcherTimestamp }: ActiveScenery
|
||||
) {
|
||||
return (
|
||||
(filters['endingStatus'] && dispatcherStatus == Status.ActiveDispatcher.ENDING) ||
|
||||
(filters['unavailableStatus'] &&
|
||||
(dispatcherStatus == Status.ActiveDispatcher.UNAVAILABLE ||
|
||||
dispatcherStatus == Status.ActiveDispatcher.NOT_LOGGED_IN)) ||
|
||||
(filters['afkStatus'] && dispatcherStatus == Status.ActiveDispatcher.AFK) ||
|
||||
(filters['noSpaceStatus'] && dispatcherStatus == Status.ActiveDispatcher.NO_SPACE) ||
|
||||
(filters['occupied'] && dispatcherStatus != Status.ActiveDispatcher.FREE) ||
|
||||
(filters['onlineFromHours'] > 0 &&
|
||||
(dispatcherTimestamp ?? 0) <= Date.now() + filters['onlineFromHours'] * 3600000)
|
||||
);
|
||||
}
|
||||
|
||||
function filterTimetablesSection(filters: Record<string, any>, station: Station) {
|
||||
return (
|
||||
(filters['withoutActiveTimetables'] &&
|
||||
(!station.onlineInfo || station.onlineInfo.scheduledTrainCount.all == 0)) ||
|
||||
(filters['withActiveTimetables'] &&
|
||||
station.onlineInfo &&
|
||||
(station.onlineInfo.scheduledTrainCount.all != 0 ||
|
||||
station.onlineInfo.dispatcherStatus == Status.ActiveDispatcher.FREE))
|
||||
);
|
||||
}
|
||||
|
||||
function filterAccessibilitySection(filters: Record<string, any>, station: Station) {
|
||||
if (
|
||||
filters['nonPublic'] &&
|
||||
(!station.generalInfo || station.generalInfo.availability == 'nonPublic')
|
||||
)
|
||||
return true;
|
||||
|
||||
if (!station.generalInfo) return false;
|
||||
|
||||
const { availability } = station.generalInfo;
|
||||
|
||||
return (
|
||||
(filters['unavailable'] && availability == 'unavailable' && !station.onlineInfo) ||
|
||||
(filters['abandoned'] && availability == 'abandoned' && !station.onlineInfo) ||
|
||||
(filters['default'] && availability == 'default') ||
|
||||
(filters['notDefault'] &&
|
||||
availability != 'default' &&
|
||||
availability != 'abandoned' &&
|
||||
availability != 'unavailable')
|
||||
);
|
||||
}
|
||||
|
||||
function filterRealitySection(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
||||
return (filters['real'] && generalInfo.lines) || (filters['fictional'] && !generalInfo.lines);
|
||||
}
|
||||
|
||||
function filterProgramsSection(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
||||
return (
|
||||
(filters['SUP'] && generalInfo.SUP) ||
|
||||
(filters['noSUP'] && !generalInfo.SUP) ||
|
||||
(filters['ASDEK'] && generalInfo.ASDEK) ||
|
||||
(filters['noASDEK'] && !generalInfo.ASDEK)
|
||||
);
|
||||
}
|
||||
|
||||
function filterControlsSection(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
||||
return (
|
||||
filters[generalInfo.controlType] == true ||
|
||||
filters[filtersAssociations[generalInfo.controlType]] == true
|
||||
);
|
||||
}
|
||||
|
||||
function filterSignalsSection(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
||||
return (
|
||||
filters[generalInfo.signalType] == true ||
|
||||
filters[filtersAssociations[generalInfo.signalType]] == true ||
|
||||
(filters['SBL'] && generalInfo.routes.sblNames.length > 0) ||
|
||||
(filters['PBL'] && generalInfo.routes.sblNames.length == 0)
|
||||
);
|
||||
}
|
||||
|
||||
function filterStationType(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
||||
const singleTracks = generalInfo.routes.single.filter((r) => !r.isInternal);
|
||||
const doubleTracks = generalInfo.routes.double.filter((r) => !r.isInternal);
|
||||
|
||||
let isJunction = singleTracks.length > 0 && doubleTracks.length > 0;
|
||||
|
||||
return (filters['junction'] && isJunction) || (filters['nonJunction'] && !isJunction);
|
||||
}
|
||||
|
||||
function filterSliderValues(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
||||
const { availability, reqLevel, routes } = generalInfo;
|
||||
|
||||
const otherAvailability =
|
||||
availability == 'nonPublic' || availability == 'unavailable' || availability == 'abandoned';
|
||||
|
||||
return (
|
||||
filters['minLevel'] > reqLevel + (otherAvailability ? 1 : 0) ||
|
||||
filters['maxLevel'] < reqLevel + (otherAvailability ? 1 : 0) ||
|
||||
filters['minVmax'] > routes.maxRouteSpeed ||
|
||||
filters['maxVmax'] < routes.minRouteSpeed ||
|
||||
(filters['no-1track'] && routes.single.length != 0) ||
|
||||
(filters['no-2track'] && routes.double.length != 0) ||
|
||||
filters['minOneWayCatenary'] > routes.singleElectrifiedNames.length ||
|
||||
filters['minOneWay'] > routes.singleOtherNames.length ||
|
||||
filters['minTwoWayCatenary'] > routes.doubleElectrifiedNames.length ||
|
||||
filters['minTwoWay'] > routes.doubleOtherNames.length
|
||||
);
|
||||
}
|
||||
|
||||
function filterInputValues(filters: Record<string, any>, generalInfo: StationGeneralInfo) {
|
||||
return (
|
||||
filters['authors'].length > 3 &&
|
||||
!generalInfo.authors
|
||||
?.map((a) => a.toLocaleLowerCase())
|
||||
.includes(filters['authors'].toLocaleLowerCase())
|
||||
);
|
||||
}
|
||||
|
||||
export const sortStations = (a: Station, b: Station, sorter: ActiveSorter) => {
|
||||
let diff = 0;
|
||||
|
||||
switch (sorter.headerName) {
|
||||
@@ -110,132 +235,40 @@ export const sortStations = (
|
||||
return a.name.localeCompare(b.name);
|
||||
};
|
||||
|
||||
export const filterStations = (station: Station, filters: Filter) => {
|
||||
export const filterStations = (station: Station, filters: Record<string, any>) => {
|
||||
if (filters['free'] && (!station.onlineInfo || station.onlineInfo.dispatcherId == -1))
|
||||
return false;
|
||||
|
||||
if (station.onlineInfo) {
|
||||
const { dispatcherStatus } = station.onlineInfo;
|
||||
// Scenery Timetables section
|
||||
if (filterTimetablesSection(filters, station)) return false;
|
||||
|
||||
const excludeEnding =
|
||||
dispatcherStatus == Status.ActiveDispatcher.ENDING && filters['endingStatus'];
|
||||
// Scenery Accessibility section
|
||||
if (filterAccessibilitySection(filters, station)) return false;
|
||||
|
||||
const excludeNotSigned =
|
||||
(dispatcherStatus == Status.ActiveDispatcher.NOT_LOGGED_IN ||
|
||||
dispatcherStatus == Status.ActiveDispatcher.UNAVAILABLE) &&
|
||||
filters['unavailableStatus'];
|
||||
|
||||
const excludeAFK = dispatcherStatus == Status.ActiveDispatcher.AFK && filters['afkStatus'];
|
||||
|
||||
const excludeNoSpace =
|
||||
dispatcherStatus == Status.ActiveDispatcher.NO_SPACE && filters['noSpaceStatus'];
|
||||
|
||||
const excludeOccupied = filters['occupied'] && dispatcherStatus != Status.ActiveDispatcher.FREE;
|
||||
|
||||
const excludeActiveTTs =
|
||||
(dispatcherStatus == Status.ActiveDispatcher.FREE ||
|
||||
station.onlineInfo.scheduledTrainCount.all != 0) &&
|
||||
filters['withActiveTimetables'];
|
||||
|
||||
if (
|
||||
excludeEnding ||
|
||||
excludeAFK ||
|
||||
excludeNoSpace ||
|
||||
excludeNotSigned ||
|
||||
excludeOccupied ||
|
||||
excludeActiveTTs
|
||||
)
|
||||
return false;
|
||||
|
||||
if (
|
||||
filters['onlineFromHours'] > 0 &&
|
||||
dispatcherStatus <= Date.now() + filters['onlineFromHours'] * 3600000
|
||||
)
|
||||
return false;
|
||||
}
|
||||
|
||||
const excludeNoActiveTTs =
|
||||
filters['withoutActiveTimetables'] &&
|
||||
(!station.onlineInfo || station.onlineInfo.scheduledTrainCount.all == 0);
|
||||
|
||||
if (excludeNoActiveTTs) return false;
|
||||
|
||||
if (
|
||||
(station.generalInfo?.availability == 'nonPublic' || !station.generalInfo) &&
|
||||
filters['nonPublic']
|
||||
)
|
||||
return false;
|
||||
// Scenery Status section
|
||||
if (station.onlineInfo && filterStatusSection(filters, station.onlineInfo)) return false;
|
||||
|
||||
if (station.generalInfo) {
|
||||
const { routes, availability, controlType, lines, reqLevel, signalType, SUP, ASDEK, authors } =
|
||||
station.generalInfo;
|
||||
// Scenery Reality section
|
||||
if (filterRealitySection(filters, station.generalInfo)) return false;
|
||||
|
||||
if (availability == 'unavailable' && filters['unavailable'] && !station.onlineInfo)
|
||||
return false;
|
||||
if (availability == 'abandoned' && filters['abandoned'] && !station.onlineInfo) return false;
|
||||
if (availability == 'default' && filters['default']) return false;
|
||||
// Scenery Additional Programs section
|
||||
if (filterProgramsSection(filters, station.generalInfo)) return false;
|
||||
|
||||
if (
|
||||
availability != 'default' &&
|
||||
filters['notDefault'] &&
|
||||
!(availability == 'abandoned' || availability == 'unavailable')
|
||||
)
|
||||
return false;
|
||||
// Scenery Controls section
|
||||
if (filterControlsSection(filters, station.generalInfo)) return false;
|
||||
|
||||
if (filters['real'] && lines) return false;
|
||||
if (filters['fictional'] && !lines) return false;
|
||||
// Scenery Signalling section(s)
|
||||
if (filterSignalsSection(filters, station.generalInfo)) return false;
|
||||
|
||||
const otherAvailability =
|
||||
availability == 'nonPublic' || availability == 'unavailable' || availability == 'abandoned';
|
||||
// Scenery Station Type section
|
||||
if (filterStationType(filters, station.generalInfo)) return false;
|
||||
|
||||
if (reqLevel + (otherAvailability ? 1 : 0) < filters['minLevel']) return false;
|
||||
if (reqLevel + (otherAvailability ? 1 : 0) > filters['maxLevel']) return false;
|
||||
// Scenery sliders
|
||||
if (filterSliderValues(filters, station.generalInfo)) return false;
|
||||
|
||||
if (filters['minVmax'] > station.generalInfo.routes.maxRouteSpeed) return false;
|
||||
if (filters['maxVmax'] < station.generalInfo.routes.minRouteSpeed) return false;
|
||||
|
||||
if (
|
||||
filters['no-1track'] &&
|
||||
(routes.singleElectrifiedNames.length != 0 || routes.singleOtherNames.length != 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
if (
|
||||
filters['no-2track'] &&
|
||||
(routes.doubleElectrifiedNames.length != 0 || routes.doubleOtherNames.length != 0)
|
||||
)
|
||||
return false;
|
||||
|
||||
if (routes.singleElectrifiedNames.length < filters['minOneWayCatenary']) return false;
|
||||
if (routes.singleOtherNames.length < filters['minOneWay']) return false;
|
||||
|
||||
if (routes.doubleElectrifiedNames.length < filters['minTwoWayCatenary']) return false;
|
||||
if (routes.doubleOtherNames.length < filters['minTwoWay']) return false;
|
||||
|
||||
if (filters[controlType]) return false;
|
||||
if (filters[signalType]) return false;
|
||||
|
||||
if (filters['SUP'] && SUP) return false;
|
||||
if (filters['noSUP'] && !SUP) return false;
|
||||
|
||||
if (filters['ASDEK'] && ASDEK) return false;
|
||||
if (filters['noASDEK'] && !ASDEK) return false;
|
||||
|
||||
if (filters['SBL'] && routes.sblNames.length > 0) return false;
|
||||
if (filters['PBL'] && routes.sblNames.length == 0) return false;
|
||||
|
||||
if (
|
||||
filters['authors'].length > 3 &&
|
||||
!authors?.map((a) => a.toLocaleLowerCase()).includes(filters['authors'].toLocaleLowerCase())
|
||||
)
|
||||
return false;
|
||||
|
||||
const singleTracks = routes.single.filter((r) => !r.isInternal);
|
||||
const doubleTracks = routes.double.filter((r) => !r.isInternal);
|
||||
|
||||
let isJunction = singleTracks.length > 0 && doubleTracks.length > 0;
|
||||
if (filters['junction'] && isJunction) return false;
|
||||
if (filters['nonJunction'] && !isJunction) return false;
|
||||
// Scenery Authors section
|
||||
if (filterInputValues(filters, station.generalInfo)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -2,72 +2,15 @@ import { defineStore } from 'pinia';
|
||||
import inputData from '../data/options.json';
|
||||
import { useMainStore } from './mainStore';
|
||||
import { filterStations, sortStations } from '../scripts/utils/stationFilterUtils';
|
||||
import { HeadIdsTypes } from '../scripts/data/stationHeaderNames';
|
||||
import StorageManager from '../managers/storageManager';
|
||||
import { Filter } from '../components/StationsView/typings';
|
||||
|
||||
const filterInitStates: Filter = {
|
||||
default: false,
|
||||
notDefault: false,
|
||||
real: false,
|
||||
fictional: false,
|
||||
SPK: false,
|
||||
SCS: false,
|
||||
SPE: false,
|
||||
SUP: false,
|
||||
noSUP: false,
|
||||
ASDEK: false,
|
||||
noASDEK: false,
|
||||
ręczne: false,
|
||||
'ręczne+SPK': false,
|
||||
'ręczne+SCS': false,
|
||||
mechaniczne: false,
|
||||
'mechaniczne+SPK': false,
|
||||
'mechaniczne+SCS': false,
|
||||
współczesna: false,
|
||||
kształtowa: false,
|
||||
historyczna: false,
|
||||
mieszana: false,
|
||||
SBL: false,
|
||||
PBL: false,
|
||||
'include-selected': false,
|
||||
'no-1track': false,
|
||||
'no-2track': false,
|
||||
free: true,
|
||||
occupied: false,
|
||||
ending: false,
|
||||
nonPublic: false,
|
||||
unavailable: true,
|
||||
abandoned: true,
|
||||
afkStatus: false,
|
||||
endingStatus: false,
|
||||
noSpaceStatus: false,
|
||||
unavailableStatus: false,
|
||||
unsignedStatus: false,
|
||||
withActiveTimetables: false,
|
||||
withoutActiveTimetables: false,
|
||||
|
||||
junction: false,
|
||||
nonJunction: false,
|
||||
|
||||
maxVmax: 200,
|
||||
minVmax: 0,
|
||||
authors: '',
|
||||
onlineFromHours: 0,
|
||||
minLevel: 0,
|
||||
maxLevel: 20,
|
||||
minOneWayCatenary: 0,
|
||||
minOneWay: 0,
|
||||
minTwoWayCatenary: 0,
|
||||
minTwoWay: 0
|
||||
};
|
||||
import { HeadIdsType } from '../components/StationsView/typings';
|
||||
|
||||
export const useStationFiltersStore = defineStore('stationFiltersStore', {
|
||||
state() {
|
||||
return {
|
||||
inputs: inputData,
|
||||
filters: { ...filterInitStates },
|
||||
sorterActive: { headerName: 'station' as HeadIdsTypes, dir: 1 },
|
||||
// filters: { ...filterInitStates },
|
||||
sorterActive: { headerName: 'station' as HeadIdsType, dir: 1 },
|
||||
lastClickedFilterId: ''
|
||||
};
|
||||
},
|
||||
@@ -112,19 +55,19 @@ export const useStationFiltersStore = defineStore('stationFiltersStore', {
|
||||
if (StorageManager.isRegistered('options_saved')) StorageManager.setValue(name, value);
|
||||
},
|
||||
|
||||
resetFilters() {
|
||||
this.filters = { ...filterInitStates };
|
||||
// resetFilters() {
|
||||
// // this.filters = { ...filterInitStates };
|
||||
|
||||
this.inputs.options.forEach((option) => {
|
||||
option.value = option.defaultValue;
|
||||
StorageManager.setBooleanValue(option.name, !option.defaultValue);
|
||||
});
|
||||
// this.inputs.options.forEach((option) => {
|
||||
// option.value = option.defaultValue;
|
||||
// StorageManager.setBooleanValue(option.name, !option.defaultValue);
|
||||
// });
|
||||
|
||||
this.inputs.sliders.forEach((slider) => {
|
||||
slider.value = slider.defaultValue;
|
||||
StorageManager.setNumericValue(slider.name, slider.defaultValue);
|
||||
});
|
||||
},
|
||||
// this.inputs.sliders.forEach((slider) => {
|
||||
// slider.value = slider.defaultValue;
|
||||
// StorageManager.setNumericValue(slider.name, slider.defaultValue);
|
||||
// });
|
||||
// },
|
||||
|
||||
resetSectionOptions(section: string) {
|
||||
this.inputs.options
|
||||
@@ -135,7 +78,7 @@ export const useStationFiltersStore = defineStore('stationFiltersStore', {
|
||||
});
|
||||
},
|
||||
|
||||
changeSorter(headerName: HeadIdsTypes) {
|
||||
changeSorter(headerName: HeadIdsType) {
|
||||
if (headerName == this.sorterActive.headerName)
|
||||
this.sorterActive.dir = -1 * this.sorterActive.dir;
|
||||
else this.sorterActive.dir = 1;
|
||||
|
||||
+20
-25
@@ -78,35 +78,30 @@ export interface Train {
|
||||
export interface Station {
|
||||
name: string;
|
||||
|
||||
generalInfo?: {
|
||||
name: string;
|
||||
url: string;
|
||||
abbr: string;
|
||||
hash?: string;
|
||||
|
||||
reqLevel: number;
|
||||
// supportersOnly: boolean;
|
||||
|
||||
lines: string;
|
||||
project: string;
|
||||
projectUrl?: string;
|
||||
|
||||
signalType: string;
|
||||
controlType: string;
|
||||
|
||||
SUP: boolean;
|
||||
ASDEK: boolean;
|
||||
authors?: string[];
|
||||
|
||||
availability: Availability;
|
||||
routes: StationRoutes;
|
||||
|
||||
checkpoints: string[];
|
||||
};
|
||||
generalInfo?: StationGeneralInfo;
|
||||
|
||||
onlineInfo?: ActiveScenery;
|
||||
}
|
||||
|
||||
export interface StationGeneralInfo {
|
||||
name: string;
|
||||
url: string;
|
||||
abbr: string;
|
||||
hash?: string;
|
||||
reqLevel: number;
|
||||
lines: string;
|
||||
project: string;
|
||||
projectUrl?: string;
|
||||
signalType: string;
|
||||
controlType: string;
|
||||
SUP: boolean;
|
||||
ASDEK: boolean;
|
||||
authors?: string[];
|
||||
availability: Availability;
|
||||
routes: StationRoutes;
|
||||
checkpoints: string[];
|
||||
}
|
||||
|
||||
export interface StationRoutes {
|
||||
single: StationRoutesInfo[];
|
||||
double: StationRoutesInfo[];
|
||||
|
||||
@@ -30,10 +30,17 @@
|
||||
import { defineComponent } from 'vue';
|
||||
import StationTable from '../components/StationsView/StationTable.vue';
|
||||
import StationFilterCard from '../components/StationsView/StationFilterCard.vue';
|
||||
import { useStationFiltersStore } from '../store/stationFiltersStore';
|
||||
import { useMainStore } from '../store/mainStore';
|
||||
import DonationModal from '../components/Global/DonationModal.vue';
|
||||
import StationStats from '../components/StationsView/StationStats.vue';
|
||||
import { initFilters, setupFilters } from '../managers/stationFilterManager';
|
||||
import { filterStations, sortStations } from '../scripts/utils/stationFilterUtils';
|
||||
import { reactive } from 'vue';
|
||||
import { provide } from 'vue';
|
||||
import { ActiveSorter } from '../components/StationsView/typings';
|
||||
import { onMounted } from 'vue';
|
||||
|
||||
const filterInitStates = { ...initFilters };
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@@ -47,12 +54,19 @@ export default defineComponent({
|
||||
filterCardOpen: false,
|
||||
isDonationModalOpen: false,
|
||||
|
||||
filterStore: useStationFiltersStore(),
|
||||
store: useMainStore()
|
||||
mainStore: useMainStore()
|
||||
}),
|
||||
|
||||
mounted() {
|
||||
this.filterStore.setupFilters();
|
||||
setup() {
|
||||
const filters = reactive(filterInitStates);
|
||||
const activeSorter = reactive({ headerName: 'station', dir: 1 }) as ActiveSorter;
|
||||
|
||||
provide('StationsView_filters', filters);
|
||||
provide('StationsView_activeSorter', activeSorter);
|
||||
|
||||
onMounted(() => {
|
||||
setupFilters(filters);
|
||||
});
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
Reference in New Issue
Block a user