diff --git a/src/components/StationsView/StationFilterCard.vue b/src/components/StationsView/StationFilterCard.vue index 20878fb..50b6a60 100644 --- a/src/components/StationsView/StationFilterCard.vue +++ b/src/components/StationsView/StationFilterCard.vue @@ -101,7 +101,14 @@ {{ $t('filters.save') }} - + @@ -121,6 +128,7 @@ import { useStore } from '../../store/store'; import ActionButton from '../Global/ActionButton.vue'; import FilterOption from './FilterOption.vue'; +import { filterInitStates } from '../../store/constants/initFilterStates'; export default defineComponent({ components: { ActionButton, FilterOption }, @@ -304,7 +312,7 @@ export default defineComponent({ } &_content { - padding: 0.5em; + padding: 1em 0.5em; display: flex; flex-direction: column; @@ -392,7 +400,7 @@ export default defineComponent({ &_actions { width: 100%; - padding: 0.25em; + padding: 0.5em; .filter-option { max-width: 50%; @@ -412,8 +420,7 @@ export default defineComponent({ padding: 0.5em; &[data-selected='true'] { - background-color: lightgreen; - color: black; + background-color: forestgreen; } } } diff --git a/src/locales/en.json b/src/locales/en.json index 264301a..5b5dac2 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -129,7 +129,7 @@ "filter-active": "ACTIVE" }, "filters": { - "desc": " • Left mouse click: select / unselect chosen filter
• Double left click: unselect all filters but chosen from group
RESET: reset all filters from group", + "desc": " • Left mouse click: select / unselect chosen filter
• Double left click: unselect all filters but chosen from a group
RESET: reset all filters from a group", "sections": { "reality": "SCENERY REALITY", @@ -138,7 +138,7 @@ "control": "CONTROLS", "signals": "SIGNALLING", "addons": "ADDITIONAL PROGRAMS", - "blockades": "BLOCKADE TYPE", + "blockades": "BLOCK SIGNALLING", "status": "ONLINE STATUS" }, @@ -170,8 +170,8 @@ "SUP": "SUP (RASP-UZK)", "noSUP": "NO SUP", - "SBL": "ABS (SBL)", - "PBL": "NO ABS (PBL)", + "SBL": "AUTOMATIC (SBL)", + "PBL": "SEMIAUTOMATIC (PBL)", "modern": "MODERN", "semaphores": "SEMAPHORES", diff --git a/src/locales/pl.json b/src/locales/pl.json index ebd2977..455c7e9 100644 --- a/src/locales/pl.json +++ b/src/locales/pl.json @@ -171,8 +171,8 @@ "SUP": "SUP (RASP-UZK)", "noSUP": "BEZ SUP", - "SBL": "SBL", - "PBL": "PBL", + "SBL": "SAMOCZYNNA", + "PBL": "PÓŁSAMOCZYNNA", "mechanical": "MECHANICZNE", "modern": "WSPÓŁCZESNA", diff --git a/src/main.ts b/src/main.ts index 0382cfc..b29c074 100644 --- a/src/main.ts +++ b/src/main.ts @@ -12,6 +12,7 @@ import { registerSW } from 'virtual:pwa-register'; const i18n = createI18n({ locale: 'pl', legacy: false, + warnHtmlMessage: false, fallbackLocale: 'pl', messages: { en: enLang, diff --git a/src/store/constants/initFilterStates.ts b/src/store/constants/initFilterStates.ts new file mode 100644 index 0000000..9e2aa83 --- /dev/null +++ b/src/store/constants/initFilterStates.ts @@ -0,0 +1,49 @@ +import Filter from "../../scripts/interfaces/Filter"; + +export const filterInitStates: Filter = { + default: false, + notDefault: false, + real: false, + fictional: false, + SPK: false, + SCS: false, + SPE: false, + SUP: false, + noSUP: 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, + minLevel: 0, + maxLevel: 20, + minOneWayCatenary: 0, + minOneWay: 0, + minTwoWayCatenary: 0, + minTwoWay: 0, + '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, + + authors: '', + + onlineFromHours: 0, +}; diff --git a/src/store/stationFiltersStore.ts b/src/store/stationFiltersStore.ts index 8d9f95b..ca48eb9 100644 --- a/src/store/stationFiltersStore.ts +++ b/src/store/stationFiltersStore.ts @@ -4,221 +4,8 @@ import Filter from '../scripts/interfaces/Filter'; import Station from '../scripts/interfaces/Station'; import StorageManager from '../scripts/managers/storageManager'; import { useStore } from './store'; - -const sortStations = (a: Station, b: Station, sorter: { index: number; dir: number }) => { - switch (sorter.index) { - case 0: - return sorter.dir == 1 ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name); - - case 1: - if ((a.generalInfo?.reqLevel || 0) > (b.generalInfo?.reqLevel || 0)) return sorter.dir; - if ((a.generalInfo?.reqLevel || 0) < (b.generalInfo?.reqLevel || 0)) return -sorter.dir; - break; - - case 2: - if ((a.onlineInfo?.statusTimestamp || 0) > (b.onlineInfo?.statusTimestamp || 0)) return sorter.dir; - if ((a.onlineInfo?.statusTimestamp || 0) < (b.onlineInfo?.statusTimestamp || 0)) return -sorter.dir; - break; - - case 3: - if ((a.onlineInfo?.dispatcherName.toLowerCase() || '') > (b.onlineInfo?.dispatcherName.toLowerCase() || '')) - return sorter.dir; - if ((a.onlineInfo?.dispatcherName.toLowerCase() || '') < (b.onlineInfo?.dispatcherName.toLowerCase() || '')) - return -sorter.dir; - break; - - case 4: - if ((a.onlineInfo?.dispatcherExp || 0) > (b.onlineInfo?.dispatcherExp || 0)) return sorter.dir; - if ((a.onlineInfo?.dispatcherExp || 0) < (b.onlineInfo?.dispatcherExp || 0)) return -sorter.dir; - break; - - case 7: - if ((a.onlineInfo?.currentUsers || 0) > (b.onlineInfo?.currentUsers || 0)) return sorter.dir; - if ((a.onlineInfo?.currentUsers || 0) < (b.onlineInfo?.currentUsers || 0)) return -sorter.dir; - - if ((a.onlineInfo?.maxUsers || 0) > (b.onlineInfo?.maxUsers || 0)) return sorter.dir; - if ((a.onlineInfo?.maxUsers || 0) < (b.onlineInfo?.maxUsers || 0)) return -sorter.dir; - break; - - case 8: - if ((a.onlineInfo?.spawns.length || 0) > (b.onlineInfo?.spawns.length || 0)) return sorter.dir; - if ((a.onlineInfo?.spawns.length || 0) < (b.onlineInfo?.spawns.length || 0)) return -sorter.dir; - - break; - - case 9: - if ((a.onlineInfo?.scheduledTrains?.length || 0) > (b.onlineInfo?.scheduledTrains?.length || 0)) - return sorter.dir; - if ((a.onlineInfo?.scheduledTrains?.length || 0) < (b.onlineInfo?.scheduledTrains?.length || 0)) - return -sorter.dir; - - default: - break; - } - - return a.name.localeCompare(b.name); -}; - -const filterStations = (station: Station, filters: Filter, isOffline = false) => { - const returnMode = false; - - if ((station.generalInfo?.availability == 'nonPublic' || !station.generalInfo) && filters['nonPublic']) - return returnMode; - - if (station.onlineInfo?.statusID == 'ending' && filters['ending']) return returnMode; - - if ( - station.onlineInfo && - station.onlineInfo.statusTimestamp > 0 && - filters['onlineFromHours'] < 8 && - station.onlineInfo.statusTimestamp <= Date.now() + filters['onlineFromHours'] * 3600000 - ) - return returnMode; - - if (filters['onlineFromHours'] > 0 && station.onlineInfo && station.onlineInfo.statusTimestamp <= 0) - return returnMode; - if (filters['onlineFromHours'] == 8 && station.onlineInfo?.statusID != 'no-limit') return returnMode; - - if (station.onlineInfo?.statusID == 'ending' && filters['endingStatus']) return returnMode; - if ( - (station.onlineInfo?.statusID == 'not-signed' || station.onlineInfo?.statusID == 'unavailable') && - filters['unavailableStatus'] - ) - return returnMode; - if (station.onlineInfo?.statusID == 'brb' && filters['afkStatus']) return returnMode; - if (station.onlineInfo?.statusID == 'no-space' && filters['noSpaceStatus']) return returnMode; - - if (station.onlineInfo && filters['occupied']) return returnMode; - if (!station.onlineInfo && filters['free']) return returnMode; - if (station.generalInfo?.availability == 'unavailable' && filters['unavailable'] && !station.onlineInfo) - return returnMode; - - if (station.generalInfo) { - const { routes, availability, controlType, lines, reqLevel, signalType, SUP, authors } = station.generalInfo; - - if (availability == 'abandoned' && filters['abandoned'] && !station.onlineInfo) return returnMode; - - if (availability == 'default' && filters['default']) return returnMode; - - if ( - availability != 'default' && - filters['notDefault'] && - !(availability == 'abandoned' || availability == 'unavailable') - ) - return returnMode; - - if (filters['real'] && lines) return returnMode; - if (filters['fictional'] && !lines) return returnMode; - - if ( - reqLevel + (availability == 'nonPublic' || availability == 'unavailable' || availability == 'abandoned' ? 1 : 0) < - filters['minLevel'] - ) - return returnMode; - - if ( - reqLevel + (availability == 'nonPublic' || availability == 'unavailable' || availability == 'abandoned' ? 1 : 0) > - filters['maxLevel'] - ) - return returnMode; - - if ( - filters['no-1track'] && - (routes.oneWayCatenaryRouteNames.length != 0 || routes.oneWayNoCatenaryRouteNames.length != 0) - ) - return returnMode; - if ( - filters['no-2track'] && - (routes.twoWayCatenaryRouteNames.length != 0 || routes.twoWayNoCatenaryRouteNames.length != 0) - ) - return returnMode; - - if (routes.oneWayCatenaryRouteNames.length < filters['minOneWayCatenary']) return returnMode; - if (routes.oneWayNoCatenaryRouteNames.length < filters['minOneWay']) return returnMode; - - if (routes.twoWayCatenaryRouteNames.length < filters['minTwoWayCatenary']) return returnMode; - if (routes.twoWayNoCatenaryRouteNames.length < filters['minTwoWay']) return returnMode; - - if (filters[controlType]) return returnMode; - if (filters[signalType]) return returnMode; - - if (filters['SPK'] && controlType === 'SPK') return returnMode; - if (filters['SCS'] && controlType === 'SCS') return returnMode; - if (filters['SPE'] && controlType === 'SPE') return returnMode; - if (filters['SUP'] && SUP) return returnMode; - if (filters['noSUP'] && !SUP) return returnMode; - - // if (filters['SCS'] && filters['SPK'] && (controlType.includes('SPK') || controlType.includes('SCS'))) - // return returnMode; - - if (filters['mechaniczne'] && controlType == 'mechaniczne') return returnMode; - if (filters['mechaniczne+SPK'] && controlType == 'mechaniczne+SPK') return returnMode; - if (filters['mechaniczne+SCS'] && controlType == 'mechaniczne+SCS') return returnMode; - - if (filters['ręczne'] && controlType == 'ręczne') return returnMode; - if (filters['ręczne+SPK'] && controlType == 'ręczne+SPK') return returnMode; - if (filters['ręczne+SCS'] && controlType == 'ręczne+SCS') return returnMode; - - if (filters['SBL'] && routes.sblRouteNames.length > 0) return returnMode; - if (filters['PBL'] && routes.sblRouteNames.length == 0) return returnMode; - - if ( - filters['authors'].length > 3 && - !authors?.map((a) => a.toLocaleLowerCase()).includes(filters['authors'].toLocaleLowerCase()) - ) - return returnMode; - } - - return true; -}; - -const filterInitStates: Filter = { - default: false, - notDefault: false, - real: false, - fictional: false, - SPK: false, - SCS: false, - SPE: false, - SUP: false, - noSUP: 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, - minLevel: 0, - maxLevel: 20, - minOneWayCatenary: 0, - minOneWay: 0, - minTwoWayCatenary: 0, - minTwoWay: 0, - '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, - - authors: '', - - onlineFromHours: 0, -}; +import { filterInitStates } from './constants/initFilterStates'; +import { filterStations, sortStations } from './utils/filterUtils'; export const useStationFiltersStore = defineStore('stationFiltersStore', { state() { @@ -231,6 +18,12 @@ export const useStationFiltersStore = defineStore('stationFiltersStore', { }; }, + getters: { + areFiltersAtDefault(state) { + return Object.keys(state.filters).every((f) => state.filters[f] === filterInitStates[f]); + }, + }, + actions: { getFilteredStationList(stationList: Station[], region: string): Station[] { return stationList @@ -241,7 +34,7 @@ export const useStationFiltersStore = defineStore('stationFiltersStore', { return station; }) - .filter((station) => filterStations(station, this.filters, this.store.isOffline)) + .filter((station) => filterStations(station, this.filters)) .sort((a, b) => sortStations(a, b, this.sorterActive)); }, @@ -249,10 +42,10 @@ export const useStationFiltersStore = defineStore('stationFiltersStore', { if (!StorageManager.isRegistered('options_saved')) return; this.inputs.options.forEach((option) => { - if (!StorageManager.isRegistered(option.id)) return; - const savedValue = StorageManager.getBooleanValue(option.id); + if (!StorageManager.isRegistered(option.name)) return; + const savedValue = StorageManager.getBooleanValue(option.name); - this.filters[option.id] = savedValue; + this.filters[option.name] = savedValue; option.value = !savedValue; }); diff --git a/src/store/utils/filterUtils.ts b/src/store/utils/filterUtils.ts index 1c19a31..02a3c7b 100644 --- a/src/store/utils/filterUtils.ts +++ b/src/store/utils/filterUtils.ts @@ -1,3 +1,4 @@ +import Filter from '../../scripts/interfaces/Filter'; import Station from '../../scripts/interfaces/Station'; export const sortStations = (a: Station, b: Station, sorter: { index: number; dir: number }) => { @@ -54,131 +55,86 @@ export const sortStations = (a: Station, b: Station, sorter: { index: number; di return a.name.localeCompare(b.name); }; -export const filterStations = (station: Station, filters: { [key: string]: any }, isOffline = false) => { - const returnMode = false; +export const filterStations = (station: Station, filters: Filter) => { + if (!station.onlineInfo && filters['free']) return false; - if ((station.generalInfo?.availability == 'nonPublic' || !station.generalInfo) && filters['nonPublic']) - return returnMode; + if (station.onlineInfo) { + const { statusID, statusTimestamp } = station.onlineInfo; - if (station.onlineInfo?.statusID == 'ending' && filters['ending']) return returnMode; + const isEnding = statusID == 'ending' && filters['endingStatus']; + const isNotSigned = (statusID == 'not-signed' || statusID == 'unavailable') && filters['unavailableStatus']; + const isAFK = statusID == 'brb' && filters['afkStatus']; + const isNoSpace = statusID == 'no-space' && filters['noSpaceStatus']; + const isOccupied = station.onlineInfo && filters['occupied']; - if ( - station.onlineInfo && - station.onlineInfo.statusTimestamp > 0 && - filters['onlineFromHours'] < 8 && - station.onlineInfo.statusTimestamp <= Date.now() + filters['onlineFromHours'] * 3600000 - ) - return returnMode; + const isOnlineInBounds = + (filters['onlineFromHours'] < 8 && + statusTimestamp > 0 && + statusTimestamp <= Date.now() + filters['onlineFromHours'] * 3600000) || + (filters['onlineFromHours'] > 0 && statusTimestamp <= 0) || + (filters['onlineFromHours'] == 8 && statusID != 'no-limit'); - if (filters['onlineFromHours'] > 0 && station.onlineInfo && station.onlineInfo.statusTimestamp <= 0) - return returnMode; - if (filters['onlineFromHours'] == 8 && station.onlineInfo?.statusID != 'no-limit') return returnMode; + if (isEnding || isOnlineInBounds || isNotSigned || isAFK || isNoSpace || isOccupied) return false; + } - if (station.onlineInfo?.statusID == 'ending' && filters['endingStatus']) return returnMode; - if ( - (station.onlineInfo?.statusID == 'not-signed' || station.onlineInfo?.statusID == 'unavailable') && - filters['unavailableStatus'] - ) - return returnMode; - if (station.onlineInfo?.statusID == 'brb' && filters['afkStatus']) return returnMode; - if (station.onlineInfo?.statusID == 'no-space' && filters['noSpaceStatus']) return returnMode; - - if (station.onlineInfo && filters['occupied']) return returnMode; - if (!station.onlineInfo && filters['free']) return returnMode; - if (station.generalInfo?.availability == 'unavailable' && filters['unavailable'] && !station.onlineInfo) - return returnMode; + if ((station.generalInfo?.availability == 'nonPublic' || !station.generalInfo) && filters['nonPublic']) return false; if (station.generalInfo) { - const routes = station.generalInfo.routes; - const availability = station.generalInfo.availability; + const { routes, availability, controlType, lines, reqLevel, signalType, SUP, authors } = station.generalInfo; - if (filters['abandoned'] && availability == 'abandoned' && !station.onlineInfo) return returnMode; + 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; - if (availability == 'default' && filters['default']) return returnMode; if ( availability != 'default' && filters['notDefault'] && !(availability == 'abandoned' || availability == 'unavailable') ) - return returnMode; + return false; - if (filters['real'] && station.generalInfo.lines != '') return returnMode; - if ( - filters['fictional'] && - station.generalInfo.lines == '' && - availability != 'abandoned' && - availability != 'unavailable' - ) - return returnMode; + if (filters['real'] && lines) return false; + if (filters['fictional'] && !lines) return false; - if ( - station.generalInfo.reqLevel + - (availability == 'nonPublic' || availability == 'unavailable' || availability == 'abandoned' ? 1 : 0) < - filters['minLevel'] - ) - return returnMode; - if ( - station.generalInfo.reqLevel + - (availability == 'nonPublic' || availability == 'unavailable' || availability == 'abandoned' ? 1 : 0) > - filters['maxLevel'] - ) - return returnMode; + const otherAvailability = + availability == 'nonPublic' || availability == 'unavailable' || availability == 'abandoned'; + + if (reqLevel + (otherAvailability ? 1 : 0) < filters['minLevel']) return false; + + if (reqLevel + (otherAvailability ? 1 : 0) > filters['maxLevel']) return false; if ( filters['no-1track'] && (routes.oneWayCatenaryRouteNames.length != 0 || routes.oneWayNoCatenaryRouteNames.length != 0) ) - return returnMode; + return false; + if ( filters['no-2track'] && (routes.twoWayCatenaryRouteNames.length != 0 || routes.twoWayNoCatenaryRouteNames.length != 0) ) - return returnMode; + return false; - if (routes.oneWayCatenaryRouteNames.length < filters['minOneWayCatenary']) return returnMode; - if (routes.oneWayNoCatenaryRouteNames.length < filters['minOneWay']) return returnMode; + if (routes.oneWayCatenaryRouteNames.length < filters['minOneWayCatenary']) return false; + if (routes.oneWayNoCatenaryRouteNames.length < filters['minOneWay']) return false; - if (routes.twoWayCatenaryRouteNames.length < filters['minTwoWayCatenary']) return returnMode; - if (routes.twoWayNoCatenaryRouteNames.length < filters['minTwoWay']) return returnMode; + if (routes.twoWayCatenaryRouteNames.length < filters['minTwoWayCatenary']) return false; + if (routes.twoWayNoCatenaryRouteNames.length < filters['minTwoWay']) return false; - if (filters[station.generalInfo.controlType]) return returnMode; - if (filters[station.generalInfo.signalType]) return returnMode; + if (filters[controlType]) return false; + if (filters[signalType]) return false; - if ( - filters['SPK'] && - (station.generalInfo.controlType === 'SPK' || station.generalInfo.controlType.includes('+SPK')) - ) - return returnMode; - if ( - filters['SCS'] && - (station.generalInfo.controlType === 'SCS' || station.generalInfo.controlType.includes('+SCS')) - ) - return returnMode; - if ( - filters['SPE'] && - (station.generalInfo.controlType === 'SPE' || station.generalInfo.controlType.includes('+SPE')) - ) - return returnMode; - if (filters['SUP'] && station.generalInfo.SUP) return returnMode; + if (filters['SUP'] && SUP) return false; + if (filters['noSUP'] && !SUP) return false; - if ( - filters['SCS'] && - filters['SPK'] && - (station.generalInfo.controlType.includes('SPK') || station.generalInfo.controlType.includes('SCS')) - ) - return returnMode; - - if (filters['mechaniczne'] && station.generalInfo.controlType.includes('mechaniczne')) return returnMode; - - if (filters['ręczne'] && station.generalInfo.controlType.includes('ręczne')) return returnMode; - - if (filters['SBL'] && routes.sblRouteNames.length > 0) return returnMode; + if (filters['SBL'] && routes.sblRouteNames.length > 0) return false; + if (filters['PBL'] && routes.sblRouteNames.length == 0) return false; if ( filters['authors'].length > 3 && - !station.generalInfo.authors?.map((a) => a.toLocaleLowerCase()).includes(filters['authors'].toLocaleLowerCase()) + !authors?.map((a) => a.toLocaleLowerCase()).includes(filters['authors'].toLocaleLowerCase()) ) - return returnMode; + return false; } return true; diff --git a/src/styles/card.scss b/src/styles/card.scss index 0906d22..9739d44 100644 --- a/src/styles/card.scss +++ b/src/styles/card.scss @@ -24,7 +24,8 @@ overflow: hidden; background: #202020e8; - box-shadow: 0 0 15px 5px #303030; + box-shadow: 0 0 15px 0 black; + border: 1px solid #202020e8; width: 95%; max-width: 700px; @@ -44,3 +45,9 @@ cursor: pointer; } } + +@include smallScreen { + .card { + max-height: 85vh; + } +}