mirror of
https://github.com/Spythere/stacjownik.git
synced 2026-05-03 05:18:11 +00:00
Dodano filtry dla dziennika rozkładów jazdy
This commit is contained in:
@@ -41,26 +41,34 @@
|
||||
</div>
|
||||
|
||||
<div class="options_filters">
|
||||
<span class="journal-filter active" tabindex="0">AKTYWNY</span>
|
||||
<span class="journal-filter abandoned" tabindex="0">PORZUCONY</span>
|
||||
<span class="journal-filter fulfilled" tabindex="0">WYPEŁNIONY</span>
|
||||
<button
|
||||
v-for="filter in journalFilters"
|
||||
class="journal-filter-option btn--option"
|
||||
:class="{ checked: journalFilterActive.id === filter.id }"
|
||||
:id="filter.id"
|
||||
@click="changeJournalFilter(filter)"
|
||||
>
|
||||
{{ $t(`journal.filter-${filter.id}`) }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, inject } from 'vue';
|
||||
import { journalFilters } from '@/data/journalFilters';
|
||||
import { computed, defineComponent, inject, JournalFilter } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import ActionButton from '../Global/ActionButton.vue';
|
||||
import SelectBox from '../Global/SelectBox.vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: { SelectBox, ActionButton },
|
||||
emits: ['changedOptions'],
|
||||
emits: ['changedOptions', 'changedFilter'],
|
||||
|
||||
data: () => ({
|
||||
exitIcon: require('@/assets/icon-exit.svg'),
|
||||
journalFilters,
|
||||
}),
|
||||
|
||||
setup() {
|
||||
@@ -81,6 +89,7 @@ export default defineComponent({
|
||||
searchedTrain: inject('searchedTrain') as string,
|
||||
searchedDriver: inject('searchedDriver') as string,
|
||||
sorterActive: inject('sorterActive') as { id: string | number; dir: number },
|
||||
journalFilterActive: inject('journalFilterActive') as JournalFilter
|
||||
};
|
||||
},
|
||||
|
||||
@@ -92,6 +101,11 @@ export default defineComponent({
|
||||
this.$emit('changedOptions');
|
||||
},
|
||||
|
||||
changeJournalFilter(filter: JournalFilter) {
|
||||
this.journalFilterActive = filter;
|
||||
this.$emit('changedFilter');
|
||||
},
|
||||
|
||||
search() {
|
||||
this.$emit('changedOptions');
|
||||
},
|
||||
@@ -111,6 +125,7 @@ export default defineComponent({
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../styles/responsive';
|
||||
@import '../../styles/option.scss';
|
||||
|
||||
.options {
|
||||
&_wrapper {
|
||||
@@ -133,24 +148,21 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
&_filters {
|
||||
display: flex;
|
||||
margin: 0.5em 0 0 0;
|
||||
|
||||
.journal-filter {
|
||||
background-color: #333;
|
||||
padding: 0.25em 0.3em;
|
||||
.journal-filter-option {
|
||||
margin: 0 0.25em 0 0;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
&.abandoned {
|
||||
&#abandoned {
|
||||
color: salmon;
|
||||
}
|
||||
|
||||
&.fulfilled {
|
||||
&#fulfilled {
|
||||
color: lightgreen;
|
||||
}
|
||||
|
||||
&.active {
|
||||
&#active {
|
||||
color: lightblue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { JournalFilterType } from "@/scripts/enums/JournalFilterType";
|
||||
import { JournalFilter } from "vue";
|
||||
|
||||
export const journalFilters: JournalFilter[] = [
|
||||
{
|
||||
id: JournalFilterType.all,
|
||||
filterSection: "timetable-status",
|
||||
isActive: true
|
||||
},
|
||||
|
||||
{
|
||||
id: JournalFilterType.active,
|
||||
filterSection: "timetable-status",
|
||||
isActive: false
|
||||
},
|
||||
|
||||
{
|
||||
id: JournalFilterType.fulfilled,
|
||||
filterSection: "timetable-status",
|
||||
isActive: false
|
||||
},
|
||||
|
||||
{
|
||||
id: JournalFilterType.abandoned,
|
||||
filterSection: "timetable-status",
|
||||
isActive: false
|
||||
},
|
||||
|
||||
]
|
||||
+6
-1
@@ -193,7 +193,12 @@
|
||||
"option-distance": "distance",
|
||||
"option-total-stops": "total stops",
|
||||
"option-beginDate": "date",
|
||||
"option-timetableId": "timetable ID"
|
||||
"option-timetableId": "timetable ID",
|
||||
|
||||
"filter-all": "ALL ENTRIES",
|
||||
"filter-abandoned": "ABANDONED",
|
||||
"filter-fulfilled": "FULFILLED",
|
||||
"filter-active": "ACTIVE"
|
||||
},
|
||||
"scenery": {
|
||||
"users": "PLAYERS ONLINE",
|
||||
|
||||
+6
-1
@@ -195,7 +195,12 @@
|
||||
"option-distance": "kilometraż",
|
||||
"option-total-stops": "stacje",
|
||||
"option-beginDate": "data",
|
||||
"option-timetableId": "ID rozkładu"
|
||||
"option-timetableId": "ID rozkładu",
|
||||
|
||||
"filter-all": "WSZYSTKIE",
|
||||
"filter-abandoned": "PORZUCONE",
|
||||
"filter-fulfilled": "WYPEŁNIONE",
|
||||
"filter-active": "AKTYWNE"
|
||||
},
|
||||
"scenery": {
|
||||
"users": "GRACZE ONLINE",
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
export const enum JournalFilterType {
|
||||
active = "active",
|
||||
fulfilled = "fulfilled",
|
||||
abandoned = "abandoned",
|
||||
all = "all"
|
||||
}
|
||||
@@ -114,6 +114,8 @@ select {
|
||||
// font-family: "Open Sans", sans-serif;
|
||||
border: none;
|
||||
font-family: "Quicksand", sans-serif;
|
||||
font-size: 1em;
|
||||
|
||||
}
|
||||
|
||||
input {
|
||||
@@ -214,7 +216,24 @@ ul {
|
||||
&--image {
|
||||
color: white;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
&--option {
|
||||
cursor: pointer;
|
||||
|
||||
color: white;
|
||||
background-color: #333;
|
||||
|
||||
border-radius: 0.25em;
|
||||
padding: 0.25em 0.5em;
|
||||
|
||||
&:hover {
|
||||
background-color: #3c3c3c;
|
||||
}
|
||||
|
||||
&.checked {
|
||||
color: var(--clr-primary);
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,9 @@
|
||||
}
|
||||
|
||||
span {
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
// user-select: none;
|
||||
// -moz-user-select: none;
|
||||
// -webkit-user-select: none;
|
||||
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
@@ -33,4 +33,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:focus span {
|
||||
// outline: 1px solid white;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
+32
-44
@@ -1,13 +1,17 @@
|
||||
<template>
|
||||
<section class="history-view">
|
||||
<div class="history-wrapper">
|
||||
<JournalOptions @changedOptions="search" />
|
||||
<JournalOptions @changedOptions="search" @changedFilter="search" />
|
||||
|
||||
<div class="history_list">
|
||||
<div class="list_wrapper" ref="scrollElement">
|
||||
<transition name="warning" mode="out-in">
|
||||
<div :key="historyDataStatus.status">
|
||||
<!-- <div v-if="isDataLoading" class="history_warning"></div> -->
|
||||
|
||||
<div class="history_loading" v-if="isDataLoading">
|
||||
<img :src="icons.loading" alt="loading icon" />
|
||||
<span class="loading-label">{{ $t('app.loading') }}</span>
|
||||
</div>
|
||||
|
||||
<div v-if="!isDataLoading && isDataError" class="history_warning error">
|
||||
{{ $t('app.error') }}
|
||||
@@ -112,17 +116,12 @@
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="history-loading" v-if="isDataLoading">
|
||||
<img :src="icons.loading" alt="loading icon" />
|
||||
<span class="loading-label">{{ $t('app.loading') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, provide, reactive, Ref, ref } from 'vue';
|
||||
import { computed, defineComponent, JournalFilter, provide, Ref, ref } from 'vue';
|
||||
import axios from 'axios';
|
||||
|
||||
import SearchBox from '@/components/Global/SearchBox.vue';
|
||||
@@ -132,8 +131,9 @@ import { DataStatus } from '@/scripts/enums/DataStatus';
|
||||
import ActionButton from '@/components/Global/ActionButton.vue';
|
||||
import JournalOptions from '@/components/JournalView/JournalOptions.vue';
|
||||
|
||||
import FilterOption from '@/scripts/interfaces/FilterOption';
|
||||
import { URLs } from '@/scripts/utils/apiURLs';
|
||||
import { journalFilters } from '@/data/journalFilters';
|
||||
import { JournalFilterType } from '@/scripts/enums/JournalFilterType';
|
||||
|
||||
const PROD_MODE = true;
|
||||
|
||||
@@ -174,31 +174,6 @@ interface TimetableHistory {
|
||||
authorId?: number;
|
||||
}
|
||||
|
||||
const initFilters = {
|
||||
status: {
|
||||
active: {
|
||||
id: 'active',
|
||||
name: 'status',
|
||||
value: false,
|
||||
defaultValue: false,
|
||||
},
|
||||
|
||||
abandoned: {
|
||||
id: 'abandoned',
|
||||
name: 'status',
|
||||
value: false,
|
||||
defaultValue: false,
|
||||
},
|
||||
|
||||
fulfilled: {
|
||||
id: 'fulfilled',
|
||||
name: 'status',
|
||||
value: true,
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
components: { SearchBox, ActionButton, JournalOptions },
|
||||
mixins: [dateMixin],
|
||||
@@ -216,6 +191,8 @@ export default defineComponent({
|
||||
});
|
||||
|
||||
const sorterActive = ref({ id: 'timetableId', dir: -1 });
|
||||
const journalFilterActive = ref(journalFilters[0]);
|
||||
|
||||
const searchedDriver = ref('');
|
||||
const searchedTrain = ref('');
|
||||
const countFromIndex = ref(0);
|
||||
@@ -224,6 +201,7 @@ export default defineComponent({
|
||||
provide('searchedTrain', searchedTrain);
|
||||
provide('searchedDriver', searchedDriver);
|
||||
provide('sorterActive', sorterActive);
|
||||
provide('journalFilterActive', journalFilterActive);
|
||||
|
||||
const scrollElement: Ref<HTMLElement | null> = ref(null);
|
||||
|
||||
@@ -256,14 +234,13 @@ export default defineComponent({
|
||||
searchedDriver,
|
||||
searchedTrain,
|
||||
sorterActive,
|
||||
journalFilterActive,
|
||||
|
||||
countFromIndex,
|
||||
countLimit,
|
||||
|
||||
scrollElement,
|
||||
maxCount: ref(15),
|
||||
|
||||
filters: reactive({ ...initFilters }) as { [filterSection: string]: { [filterId: string]: FilterOption } },
|
||||
};
|
||||
},
|
||||
|
||||
@@ -290,9 +267,7 @@ export default defineComponent({
|
||||
this.fetchHistoryData({
|
||||
searchedDriver: this.searchedDriver,
|
||||
searchedTrain: this.searchedTrain,
|
||||
fulfilled: true,
|
||||
abandoned: true,
|
||||
terminated: true
|
||||
filter: this.journalFilterActive,
|
||||
});
|
||||
},
|
||||
|
||||
@@ -304,9 +279,7 @@ export default defineComponent({
|
||||
props: {
|
||||
searchedDriver?: string;
|
||||
searchedTrain?: string;
|
||||
fulfilled?: boolean;
|
||||
terminated?: boolean;
|
||||
abandoned?: boolean;
|
||||
filter?: JournalFilter;
|
||||
} = {}
|
||||
) {
|
||||
this.historyDataStatus.status = DataStatus.Loading;
|
||||
@@ -324,7 +297,22 @@ export default defineComponent({
|
||||
|
||||
queries.push('countLimit=15');
|
||||
|
||||
// queries.push(`fulfilled=${Number(props.fulfilled) || 1}`, `terminated=${Number(props.terminated) || 1}`, `abandoned=${Number(props.abandoned) || 1}`, `active=1`);
|
||||
switch (props.filter?.id) {
|
||||
case JournalFilterType.abandoned:
|
||||
queries.push('fulfilled=0', 'terminated=1');
|
||||
break;
|
||||
|
||||
case JournalFilterType.active:
|
||||
queries.push('terminated=0');
|
||||
break;
|
||||
|
||||
case JournalFilterType.fulfilled:
|
||||
queries.push('fulfilled=1');
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
const responseData: APIResponse | null = await (await axios.get(`${API_URL}?${queries.join('&')}`)).data;
|
||||
@@ -459,7 +447,7 @@ li,
|
||||
}
|
||||
}
|
||||
|
||||
.history-loading {
|
||||
.history_loading {
|
||||
margin-top: 2em;
|
||||
|
||||
img {
|
||||
|
||||
Vendored
+7
@@ -1,5 +1,6 @@
|
||||
import { ComponentCustomProperties } from 'vue'
|
||||
import { Store } from 'vuex'
|
||||
import { JournalFilterType } from './scripts/enums/JournalFilterType';
|
||||
import { TrainFilterType } from './scripts/enums/TrainFilterType';
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
@@ -18,4 +19,10 @@ declare module '@vue/runtime-core' {
|
||||
id: TrainFilterType;
|
||||
isActive: boolean;
|
||||
}
|
||||
|
||||
interface JournalFilter {
|
||||
id: JournalFilterType;
|
||||
filterSection: string;
|
||||
isActive: boolean;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user