mirror of
https://github.com/Spythere/stacjownik.git
synced 2026-05-03 05:18:11 +00:00
Filtry pociągów
This commit is contained in:
@@ -1,67 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="train-filters">
|
|
||||||
<span v-for="category in availableCategories" :key="category">
|
|
||||||
{{ category }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import Train from '@/scripts/interfaces/Train';
|
|
||||||
import { computed, defineComponent, inject, TrainFilter } from 'vue';
|
|
||||||
|
|
||||||
const defaultFilters: TrainFilter[] = [
|
|
||||||
{
|
|
||||||
id: "comments",
|
|
||||||
isActive: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "twr",
|
|
||||||
isActive: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "skr",
|
|
||||||
isActive: true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
props: {
|
|
||||||
trainList: {
|
|
||||||
type: Object as () => Train[],
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setup(props) {
|
|
||||||
const filters = inject('filtersActive') as TrainFilter[];
|
|
||||||
const trainList = props.trainList;
|
|
||||||
|
|
||||||
|
|
||||||
// Setup default train filters
|
|
||||||
filters.push(...defaultFilters);
|
|
||||||
|
|
||||||
const availableCategories = computed(() => trainList.reduce((acc, train) => {
|
|
||||||
if(!train.timetableData) return acc;
|
|
||||||
if(acc.includes(train.timetableData.category)) return acc;
|
|
||||||
|
|
||||||
acc.push(train.timetableData.category);
|
|
||||||
return acc;
|
|
||||||
}, [] as string[]));
|
|
||||||
|
|
||||||
|
|
||||||
// Remove unavailable train categories
|
|
||||||
for(let filter of filters) {
|
|
||||||
if(availableCategories.value.includes(filter.id)) continue;
|
|
||||||
|
|
||||||
filters.slice(filters.indexOf(filter), -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
availableCategories
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
|
||||||
@@ -26,11 +26,37 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="filters">
|
||||||
|
<span
|
||||||
|
:class="{ active: filter.isActive }"
|
||||||
|
class="filter"
|
||||||
|
v-for="filter in filterList"
|
||||||
|
:key="filter.id"
|
||||||
|
tabindex="0"
|
||||||
|
@contextmenu="
|
||||||
|
(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@click.left="toggleFilter(filter)"
|
||||||
|
@keydown.enter="toggleFilter(filter)"
|
||||||
|
@click.right="setFilterOnly(filter)"
|
||||||
|
@keydown.space="setFilterOnly(filter)"
|
||||||
|
>
|
||||||
|
{{ $t(`trains.filter-${filter.id}`) }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="filter reset-btn" @click="resetFilters" tabindex="0">
|
||||||
|
{{ $t('trains.filter-reset') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineComponent, inject } from 'vue';
|
import { computed, defineComponent, inject, TrainFilter } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import SelectBox from '../Global/SelectBox.vue';
|
import SelectBox from '../Global/SelectBox.vue';
|
||||||
|
|
||||||
@@ -50,10 +76,6 @@ export default defineComponent({
|
|||||||
id: 'distance',
|
id: 'distance',
|
||||||
value: 'kilometraż',
|
value: 'kilometraż',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: 'comments',
|
|
||||||
value: 'komentarze',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 'progress',
|
id: 'progress',
|
||||||
value: 'przebyta trasa',
|
value: 'przebyta trasa',
|
||||||
@@ -76,6 +98,8 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let filterList = inject('filterList') as TrainFilter[];
|
||||||
|
|
||||||
const translatedSorterOptions = computed(() =>
|
const translatedSorterOptions = computed(() =>
|
||||||
sorterOptions.map(({ id }) => ({
|
sorterOptions.map(({ id }) => ({
|
||||||
id,
|
id,
|
||||||
@@ -88,6 +112,7 @@ export default defineComponent({
|
|||||||
searchedTrain: inject('searchedTrain') as string,
|
searchedTrain: inject('searchedTrain') as string,
|
||||||
searchedDriver: inject('searchedDriver') as string,
|
searchedDriver: inject('searchedDriver') as string,
|
||||||
sorterActive: inject('sorterActive') as { id: string | number; dir: number },
|
sorterActive: inject('sorterActive') as { id: string | number; dir: number },
|
||||||
|
filterList,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -96,6 +121,18 @@ export default defineComponent({
|
|||||||
this.sorterActive.id = item.id;
|
this.sorterActive.id = item.id;
|
||||||
this.sorterActive.dir = -1;
|
this.sorterActive.dir = -1;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
toggleFilter(filter: TrainFilter) {
|
||||||
|
filter.isActive = !filter.isActive;
|
||||||
|
},
|
||||||
|
|
||||||
|
setFilterOnly(filter: TrainFilter) {
|
||||||
|
this.filterList.forEach((f) => (f.isActive = f.id == filter.id));
|
||||||
|
},
|
||||||
|
|
||||||
|
resetFilters() {
|
||||||
|
this.filterList.forEach((f) => (f.isActive = true));
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@@ -108,6 +145,7 @@ export default defineComponent({
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.options {
|
.options {
|
||||||
&_wrapper {
|
&_wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -178,4 +216,31 @@ export default defineComponent({
|
|||||||
width: 1em;
|
width: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filters {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
@include smallScreen() {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter {
|
||||||
|
background: #333;
|
||||||
|
padding: 0.2em 0.25em;
|
||||||
|
margin: 0.25em 0.25em 0 0;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
color: gray;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: gold;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.reset-btn {
|
||||||
|
color: salmon;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -145,6 +145,15 @@
|
|||||||
"option-delay": "current delay",
|
"option-delay": "current delay",
|
||||||
"option-comments": "comments",
|
"option-comments": "comments",
|
||||||
|
|
||||||
|
"filter-comments": "comments",
|
||||||
|
"filter-twr": "TWR",
|
||||||
|
"filter-skr": "SKR",
|
||||||
|
"filter-passenger": "passenger",
|
||||||
|
"filter-freight": "freight",
|
||||||
|
"filter-other": "other",
|
||||||
|
"filter-noTimetable": "no timetable",
|
||||||
|
"filter-reset": "X RESET",
|
||||||
|
|
||||||
"sorter-prefix": "Sort: ",
|
"sorter-prefix": "Sort: ",
|
||||||
"search-train": "Train no.",
|
"search-train": "Train no.",
|
||||||
"search-driver": "Driver name",
|
"search-driver": "Driver name",
|
||||||
|
|||||||
@@ -146,6 +146,16 @@
|
|||||||
"option-delay": "opóźnienie",
|
"option-delay": "opóźnienie",
|
||||||
"option-comments": "uwagi ekspl.",
|
"option-comments": "uwagi ekspl.",
|
||||||
|
|
||||||
|
"filter-comments": "uwagi ekspl.",
|
||||||
|
"filter-twr": "TWR",
|
||||||
|
"filter-skr": "SKR",
|
||||||
|
"filter-passenger": "pasażerskie",
|
||||||
|
"filter-freight": "towarowe",
|
||||||
|
"filter-other": "inne",
|
||||||
|
"filter-noTimetable": "bez RJ",
|
||||||
|
"filter-reset": "X RESETUJ",
|
||||||
|
|
||||||
|
|
||||||
"sorter-prefix": "Sortuj: ",
|
"sorter-prefix": "Sortuj: ",
|
||||||
"search-train": "Numer pociągu",
|
"search-train": "Numer pociągu",
|
||||||
"search-driver": "Nick maszynisty",
|
"search-driver": "Nick maszynisty",
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
export const enum TrainFilterType {
|
||||||
|
comments = "comments",
|
||||||
|
twr = "twr",
|
||||||
|
skr = "skr",
|
||||||
|
passenger = "passenger",
|
||||||
|
freight = "freight",
|
||||||
|
other = "other",
|
||||||
|
noTimetable = "noTimetable"
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { TrainFilter } from "vue";
|
import { TrainFilter } from "vue";
|
||||||
|
import { TrainFilterType } from "../enums/TrainFilterType";
|
||||||
import Train from "../interfaces/Train";
|
import Train from "../interfaces/Train";
|
||||||
import TrainStop from "../interfaces/TrainStop";
|
import TrainStop from "../interfaces/TrainStop";
|
||||||
|
|
||||||
@@ -19,11 +20,41 @@ function currentDelay(stops: TrainStop[] | undefined) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function filterTrainList(trainList: Train[], searchedTrain: string, searchedDriver: string, filters: TrainFilter[]) {
|
function filterTrainList(trainList: Train[], searchedTrain: string, searchedDriver: string, filters: TrainFilter[]) {
|
||||||
|
|
||||||
return trainList.filter(
|
return trainList.filter(
|
||||||
(train) =>
|
(train) => {
|
||||||
(searchedTrain.length > 0 ? train.trainNo.toString().startsWith(searchedTrain) : true) &&
|
const isFiltered = filters.every(f => {
|
||||||
(searchedDriver.length > 0 ? train.driverName.toLowerCase().startsWith(searchedDriver.toLowerCase()) : true)
|
if (f.isActive) return true;
|
||||||
|
|
||||||
|
if (!train.timetableData) return filters.find(filter => filter.id == TrainFilterType.noTimetable)!.isActive;
|
||||||
|
|
||||||
|
switch (f.id) {
|
||||||
|
case TrainFilterType.comments:
|
||||||
|
return !train.timetableData.followingStops.some(stop => stop.comments);
|
||||||
|
|
||||||
|
case TrainFilterType.twr:
|
||||||
|
return !train.timetableData.TWR;
|
||||||
|
|
||||||
|
case TrainFilterType.skr:
|
||||||
|
return !train.timetableData.SKR;
|
||||||
|
|
||||||
|
case TrainFilterType.passenger:
|
||||||
|
return !/^[AMRE]\D{2}$/.test(train.timetableData.category);
|
||||||
|
|
||||||
|
case TrainFilterType.freight:
|
||||||
|
return !train.timetableData.category.startsWith('T');
|
||||||
|
|
||||||
|
case TrainFilterType.other:
|
||||||
|
return !/^[PXZ]\D{2}$/.test(train.timetableData.category);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return (searchedTrain.length > 0 ? train.trainNo.toString().startsWith(searchedTrain) : true) &&
|
||||||
|
(searchedDriver.length > 0 ? train.driverName.toLowerCase().startsWith(searchedDriver.toLowerCase()) : true) && isFiltered
|
||||||
|
}
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,34 +109,7 @@ export function filteredTrainList(
|
|||||||
sorterActive: { id: string; dir: number },
|
sorterActive: { id: string; dir: number },
|
||||||
filters: TrainFilter[]
|
filters: TrainFilter[]
|
||||||
) {
|
) {
|
||||||
let finalTrainList: Train[] = [];
|
|
||||||
|
|
||||||
const filtered = filterTrainList(trainList, searchedTrain, searchedDriver, filters);
|
const filtered = filterTrainList(trainList, searchedTrain, searchedDriver, filters);
|
||||||
|
return [...sortTrainList(filtered, sorterActive)];
|
||||||
switch (sorterActive.id) {
|
|
||||||
case 'comments':
|
|
||||||
const trainsSortedByComments = filtered
|
|
||||||
.sort((a, b) => {
|
|
||||||
const commentsA = a.timetableData?.followingStops.some((s) => s.comments) ? 1 : 0;
|
|
||||||
const commentsB = b.timetableData?.followingStops.some((s) => s.comments) ? 1 : 0;
|
|
||||||
|
|
||||||
return commentsB - commentsA;
|
|
||||||
});
|
|
||||||
|
|
||||||
const trainsWithComments = trainsSortedByComments.filter((train) =>
|
|
||||||
train.timetableData?.followingStops.some((s) => s.comments)
|
|
||||||
);
|
|
||||||
|
|
||||||
const trainsWithoutComments = trainsSortedByComments.slice(trainsWithComments.length);
|
|
||||||
|
|
||||||
finalTrainList.push(...trainsWithComments);
|
|
||||||
finalTrainList.push(...sortTrainList(trainsWithoutComments, sorterActive));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
finalTrainList.push(...sortTrainList(filtered, sorterActive));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return finalTrainList;
|
|
||||||
};
|
};
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, ComputedRef, defineComponent, provide, reactive, ref, TrainFilter } from 'vue';
|
import { computed, ComputedRef, defineComponent, provide, reactive, ref, TrainFilter } from 'vue';
|
||||||
import { filteredTrainList } from "@/scripts/managers/trainFilterManager";
|
import { filteredTrainList } from '@/scripts/managers/trainFilterManager';
|
||||||
|
|
||||||
import Train from '@/scripts/interfaces/Train';
|
import Train from '@/scripts/interfaces/Train';
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ import TrainOptions from '@/components/TrainsView/TrainOptions.vue';
|
|||||||
|
|
||||||
import { useStore } from '@/store';
|
import { useStore } from '@/store';
|
||||||
import { GETTERS } from '@/constants/storeConstants';
|
import { GETTERS } from '@/constants/storeConstants';
|
||||||
|
import { TrainFilterType } from '@/scripts/enums/TrainFilterType';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
@@ -45,10 +45,39 @@ export default defineComponent({
|
|||||||
|
|
||||||
const trainList: ComputedRef<Train[]> = computed(() => store.getters[GETTERS.trainList]);
|
const trainList: ComputedRef<Train[]> = computed(() => store.getters[GETTERS.trainList]);
|
||||||
|
|
||||||
// const timetableDataStatus: ComputedRef<DataStatus> = computed(() => store.getters[GETTERS.timetableDataStatus]);
|
const initFilters: TrainFilter[] = [
|
||||||
|
{
|
||||||
|
id: TrainFilterType.twr,
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: TrainFilterType.skr,
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: TrainFilterType.passenger,
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: TrainFilterType.freight,
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: TrainFilterType.other,
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: TrainFilterType.comments,
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: TrainFilterType.noTimetable,
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const sorterActive = ref({ id: 'distance', dir: -1 });
|
const sorterActive = ref({ id: 'distance', dir: -1 });
|
||||||
const filtersActive = reactive([]) as TrainFilter[];
|
const filterList = reactive([...initFilters]) as TrainFilter[];
|
||||||
|
|
||||||
const searchedDriver = ref('');
|
const searchedDriver = ref('');
|
||||||
const searchedTrain = ref('');
|
const searchedTrain = ref('');
|
||||||
@@ -56,7 +85,7 @@ export default defineComponent({
|
|||||||
provide('searchedTrain', searchedTrain);
|
provide('searchedTrain', searchedTrain);
|
||||||
provide('searchedDriver', searchedDriver);
|
provide('searchedDriver', searchedDriver);
|
||||||
provide('sorterActive', sorterActive);
|
provide('sorterActive', sorterActive);
|
||||||
provide('filtersActive', filtersActive);
|
provide('filterList', filterList);
|
||||||
|
|
||||||
const computedTrains: ComputedRef<Train[]> = computed(() => {
|
const computedTrains: ComputedRef<Train[]> = computed(() => {
|
||||||
return filteredTrainList(
|
return filteredTrainList(
|
||||||
@@ -64,7 +93,7 @@ export default defineComponent({
|
|||||||
searchedTrain.value,
|
searchedTrain.value,
|
||||||
searchedDriver.value,
|
searchedDriver.value,
|
||||||
sorterActive.value,
|
sorterActive.value,
|
||||||
filtersActive
|
filterList
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Vendored
+2
-1
@@ -1,5 +1,6 @@
|
|||||||
import { ComponentCustomProperties } from 'vue'
|
import { ComponentCustomProperties } from 'vue'
|
||||||
import { Store } from 'vuex'
|
import { Store } from 'vuex'
|
||||||
|
import { TrainFilterType } from './scripts/enums/TrainFilterType';
|
||||||
|
|
||||||
declare module '@vue/runtime-core' {
|
declare module '@vue/runtime-core' {
|
||||||
// declare your own store states
|
// declare your own store states
|
||||||
@@ -14,7 +15,7 @@ declare module '@vue/runtime-core' {
|
|||||||
|
|
||||||
// Train filter for TrainView
|
// Train filter for TrainView
|
||||||
interface TrainFilter {
|
interface TrainFilter {
|
||||||
id: string;
|
id: TrainFilterType;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user