chore(api): improved fetching data from api; changed to new vehicles data endpoint

This commit is contained in:
2026-04-05 01:28:23 +02:00
parent cd22a23aef
commit cd8c29f327
8 changed files with 103 additions and 31 deletions
+1 -1
View File
@@ -19,7 +19,7 @@ async function main() {
if (!existsSync('endpoints')) await mkdir('endpoints'); if (!existsSync('endpoints')) await mkdir('endpoints');
Promise.all( Promise.all(
['getActiveData', 'getDonators', 'getSceneries', 'getVehicles'].map((endpointName) => ['getActiveData', 'getDonators', 'getSceneries', 'getVehiclesData'].map((endpointName) =>
fetchJSONEndpointData( fetchJSONEndpointData(
`https://stacjownik.spythere.eu/api/${endpointName}`, `https://stacjownik.spythere.eu/api/${endpointName}`,
`${endpointName}.json` `${endpointName}.json`
+2 -2
View File
@@ -15,8 +15,8 @@ app.get('/api/getSceneries', (_, res) => {
res.sendFile(path.join(cwd(), 'endpoints', 'getSceneries.json')); res.sendFile(path.join(cwd(), 'endpoints', 'getSceneries.json'));
}); });
app.get('/api/getVehicles', (_, res) => { app.get('/api/getVehiclesData', (_, res) => {
res.sendFile(path.join(cwd(), 'endpoints', 'getVehicles.json')); res.sendFile(path.join(cwd(), 'endpoints', 'getVehiclesData.json'));
}); });
app.get('/api/getDonators', (_, res) => { app.get('/api/getDonators', (_, res) => {
@@ -8,13 +8,30 @@
<Minimize2Icon :size="22" /> <Minimize2Icon :size="22" />
</button> </button>
<!-- Timetable render based on current view mode -->
<CurrentTimetableView v-if="globalStore.currentTimetableData != null" />
<!-- If there is no timetable chosen --> <!-- If there is no timetable chosen -->
<div class="overflow-auto text-center font-bold text-zinc-400 p-1 min-h-full" v-else> <div
class="overflow-auto text-center font-bold text-zinc-400 p-2 min-h-full"
v-if="globalStore.currentTimetableData == null"
>
<component :is="viewModes[globalStore.viewMode]" /> <component :is="viewModes[globalStore.viewMode]" />
</div> </div>
<div
class="overflow-auto text-center font-bold text-white p-2 min-h-full"
v-else-if="apiStore.apiDataStatus == DataStatus.LOADING"
>
Pobieranie danych...
</div>
<div
class="overflow-auto text-center font-bold text-red-500 p-2 min-h-full"
v-else-if="apiStore.apiDataStatus == DataStatus.ERROR"
>
Ups! Coś poszło nie tak przy pobieraniu danych! :/
</div>
<!-- Timetable render based on current view mode -->
<CurrentTimetableView v-else />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -24,8 +41,11 @@ import JournalStorageView from '../TimetableViews/JournalStorageView.vue';
import ActiveDataView from '../TimetableViews/ActiveDataView.vue'; import ActiveDataView from '../TimetableViews/ActiveDataView.vue';
import CurrentTimetableView from '../TimetableViews/CurrentTimetableView.vue'; import CurrentTimetableView from '../TimetableViews/CurrentTimetableView.vue';
import { Minimize2Icon } from 'lucide-vue-next'; import { Minimize2Icon } from 'lucide-vue-next';
import { useApiStore } from '../../stores/api.store';
import { DataStatus } from '../../types/api.types';
const globalStore = useGlobalStore(); const globalStore = useGlobalStore();
const apiStore = useApiStore();
const viewModes: Record<typeof globalStore.viewMode, any> = { const viewModes: Record<typeof globalStore.viewMode, any> = {
active: ActiveDataView, active: ActiveDataView,
@@ -5,12 +5,12 @@
name="trains" name="trains"
id="trains-select" id="trains-select"
class="bg-zinc-800 p-1 rounded-md print:hidden w-full" class="bg-zinc-800 p-1 rounded-md print:hidden w-full"
:disabled="apiStore.activeDataStatus != DataStatus.SUCCESS" :disabled="apiStore.apiDataStatus != DataStatus.SUCCESS"
aria-label="Active train select" aria-label="Active train select"
> >
<option :value="null" disabled> <option :value="null" disabled>
{{ {{
apiStore.activeDataStatus == DataStatus.LOADING apiStore.apiDataStatus == DataStatus.LOADING
? $t('data-loading-text') ? $t('data-loading-text')
: $t('train-select-placeholder') : $t('train-select-placeholder')
}} }}
+24 -12
View File
@@ -42,7 +42,7 @@ export const useApiStore = defineStore('api', {
outdatedTimerId: -1, outdatedTimerId: -1,
isActiveDataOutdated: false, isActiveDataOutdated: false,
activeDataStatus: DataStatus.LOADING, apiDataStatus: DataStatus.LOADING,
journalDataStatus: DataStatus.SUCCESS, journalDataStatus: DataStatus.SUCCESS,
connectionMode: 'online' as 'online' | 'offline' connectionMode: 'online' as 'online' | 'offline'
@@ -53,14 +53,24 @@ export const useApiStore = defineStore('api', {
async setupAPIData() { async setupAPIData() {
clearInterval(activeDataInterval); clearInterval(activeDataInterval);
try {
this.apiDataStatus = DataStatus.LOADING;
await Promise.all([
this.fetchSceneriesData(),
this.fetchVehiclesData(),
this.fetchActiveData()
]);
this.apiDataStatus = DataStatus.SUCCESS;
} catch (error) {
this.apiDataStatus = DataStatus.ERROR;
console.log('Data fetching error: ', error);
}
activeDataInterval = setInterval(() => { activeDataInterval = setInterval(() => {
this.fetchActiveData(); this.fetchActiveData();
}, 25000); }, 25000);
this.fetchSceneriesData();
this.fetchVehiclesData();
await this.fetchActiveData();
}, },
async fetchActiveData() { async fetchActiveData() {
@@ -68,7 +78,6 @@ export const useApiStore = defineStore('api', {
const response = await this.client.get<ActiveDataResponse>('api/getActiveData'); const response = await this.client.get<ActiveDataResponse>('api/getActiveData');
this.activeData = response; this.activeData = response;
this.activeDataStatus = DataStatus.SUCCESS;
this.isActiveDataOutdated = false; this.isActiveDataOutdated = false;
if (this.outdatedTimerId != -1) clearTimeout(this.outdatedTimerId); if (this.outdatedTimerId != -1) clearTimeout(this.outdatedTimerId);
@@ -77,7 +86,7 @@ export const useApiStore = defineStore('api', {
this.isActiveDataOutdated = true; this.isActiveDataOutdated = true;
}, 60000); }, 60000);
} catch (error) { } catch (error) {
console.error(error); throw error;
} }
}, },
@@ -87,17 +96,20 @@ export const useApiStore = defineStore('api', {
this.sceneryData = response; this.sceneryData = response;
} catch (error) { } catch (error) {
console.error(error); throw error;
} }
}, },
async fetchVehiclesData() { async fetchVehiclesData() {
try { try {
const response = await this.client.get<VehiclesDataResponse>('api/getVehicles'); const response = await this.client.get<VehiclesDataResponse>('api/getVehiclesData');
this.vehiclesData = response; this.vehiclesData = response.vehicles.map((v) => ({
...v,
group: response.vehicleGroups.find((g) => g.id == v.vehicleGroupsId)!
}));
} catch (error) { } catch (error) {
console.error(error); throw error;
} }
} }
} }
+48 -7
View File
@@ -1,12 +1,15 @@
import type { ActiveData, JournalTimetableShort, SceneryData, VehicleData } from './common.types'; import type {
ActiveData,
JournalTimetableShort,
SceneryData,
VehicleGroup,
VehicleRestrictions
} from './common.types';
export type ActiveDataResponse = ActiveData; /***
* API Data Status
* */
export type SceneriesDataResponse = SceneryData[];
export type JournalTimetablesShortResponse = JournalTimetableShort[];
export type VehiclesDataResponse = VehicleData[];
export enum DataStatus { export enum DataStatus {
'INIT' = -1, 'INIT' = -1,
@@ -14,3 +17,41 @@ export enum DataStatus {
'SUCCESS' = 1, 'SUCCESS' = 1,
'ERROR' = 2 'ERROR' = 2
} }
/***
* Active Data API
* */
export type ActiveDataResponse = ActiveData;
/***
* Sceneries API
* */
export type SceneriesDataResponse = SceneryData[];
/***
* Journal API
* */
export type JournalTimetablesShortResponse = JournalTimetableShort[];
/***
* Vehicles API
* */
export interface VehiclesDataResponse {
vehicles: VehicleDataAPI[];
vehicleGroups: VehicleGroupAPI[];
}
export interface VehicleDataAPI {
id: number;
name: string;
type: string;
cabinName?: string;
restrictions?: VehicleRestrictions;
vehicleGroupsId: number;
}
export interface VehicleGroupAPI extends VehicleGroup {}
-1
View File
@@ -298,7 +298,6 @@ export interface VehicleData {
group: VehicleGroup; group: VehicleGroup;
cabinName?: string; cabinName?: string;
restrictions?: VehicleRestrictions; restrictions?: VehicleRestrictions;
simulatorVersion: string;
} }
export interface VehicleRestrictions { export interface VehicleRestrictions {
+2 -2
View File
@@ -14,8 +14,8 @@ export default defineConfig({
cleanupOutdatedCaches: true, cleanupOutdatedCaches: true,
runtimeCaching: [ runtimeCaching: [
{ {
urlPattern: /^https:\/\/stacjownik.spythere.eu\/api\/(getSceneries|getVehicles)/i, urlPattern: /^https:\/\/stacjownik.spythere.eu\/api\/(getSceneries|getVehiclesData)/i,
handler: 'NetworkFirst', handler: 'StaleWhileRevalidate',
options: { options: {
expiration: { expiration: {
maxAgeSeconds: 3600 maxAgeSeconds: 3600