refactor(stats): moved fetching daily stats data to store

This commit is contained in:
2026-02-18 02:51:33 +01:00
parent 7b07a43715
commit 72fa9523e8
2 changed files with 70 additions and 91 deletions
@@ -1,6 +1,6 @@
<template> <template>
<section class="daily-stats"> <section class="daily-stats">
<span :data-active="statsStatus"> <span :data-active="apiStore.dataStatuses.dailyStatsData">
<h3> <h3>
{{ $t('journal.daily-stats.title') }} {{ $t('journal.daily-stats.title') }}
<b class="text--primary">{{ new Date().toLocaleDateString($i18n.locale) }}</b> <b class="text--primary">{{ new Date().toLocaleDateString($i18n.locale) }}</b>
@@ -8,11 +8,11 @@
<hr class="header-separator" /> <hr class="header-separator" />
<b v-if="statsStatus == Status.Data.Loading"> <b v-if="apiStore.dataStatuses.dailyStatsData == Status.Data.Loading">
{{ $t('app.loading') }} {{ $t('app.loading') }}
</b> </b>
<b class="text--error" v-else-if="statsStatus == Status.Data.Error"> <b class="text--error" v-else-if="apiStore.dataStatuses.dailyStatsData == Status.Data.Error">
{{ $t('journal.stats-error') }} {{ $t('journal.stats-error') }}
</b> </b>
@@ -20,42 +20,48 @@
{{ $t('journal.daily-stats.info') }} {{ $t('journal.daily-stats.info') }}
</b> </b>
<div v-else> <div v-else-if="apiStore.dailyStatsData">
<ul class="stats-list"> <ul class="stats-list">
<li v-if="stats.totalTimetables"> <li v-if="apiStore.dailyStatsData.totalTimetables">
<i18n-t keypath="journal.daily-stats.total"> <i18n-t keypath="journal.daily-stats.total">
<template #count> <template #count>
<b class="text--primary"> <b class="text--primary">
{{ stats.totalTimetables }} {{ apiStore.dailyStatsData.totalTimetables }}
{{ $t('journal.daily-stats.count', stats.totalTimetables) }} {{ $t('journal.daily-stats.count', apiStore.dailyStatsData.totalTimetables) }}
</b> </b>
</template> </template>
<template #distance> <template #distance>
<b class="text--primary"> {{ stats.distanceSum?.toFixed(2) }} km</b> <b class="text--primary">
{{ apiStore.dailyStatsData.distanceSum?.toFixed(2) }} km</b
>
</template> </template>
</i18n-t> </i18n-t>
</li> </li>
<li v-if="stats.maxTimetable"> <li v-if="apiStore.dailyStatsData.maxTimetable">
<i18n-t keypath="journal.daily-stats.longest"> <i18n-t keypath="journal.daily-stats.longest">
<template #id> <template #id>
<router-link :to="`/journal/timetables?search-train=%23${stats.maxTimetable.id}`"> <router-link
<b>{{ stats.maxTimetable.id }}</b> :to="`/journal/timetables?search-train=%23${apiStore.dailyStatsData.maxTimetable.id}`"
>
<b>{{ apiStore.dailyStatsData.maxTimetable.id }}</b>
</router-link> </router-link>
</template> </template>
<template #author> <template #author>
<router-link <router-link
:to="`/journal/timetables?search-dispatcher=${stats.maxTimetable.authorName}`" :to="`/journal/timetables?search-dispatcher=${apiStore.dailyStatsData.maxTimetable.authorName}`"
> >
<b>{{ stats.maxTimetable.authorName }}</b> <b>{{ apiStore.dailyStatsData.maxTimetable.authorName }}</b>
</router-link> </router-link>
</template> </template>
<template #driver> <template #driver>
<b class="text--primary">{{ stats.maxTimetable.driverName }}</b> <b class="text--primary">{{ apiStore.dailyStatsData.maxTimetable.driverName }}</b>
</template> </template>
<template #distance> <template #distance>
<b class="text--primary">{{ stats.maxTimetable.routeDistance }} km</b> <b class="text--primary"
>{{ apiStore.dailyStatsData.maxTimetable.routeDistance }} km</b
>
</template> </template>
</i18n-t> </i18n-t>
</li> </li>
@@ -101,35 +107,37 @@
</i18n-t> </i18n-t>
</li> </li>
<li v-if="stats.longestDuties.length > 0"> <li v-if="apiStore.dailyStatsData.longestDuties.length > 0">
<i18n-t keypath="journal.daily-stats.longest-duties"> <i18n-t keypath="journal.daily-stats.longest-duties">
<template #dispatcher> <template #dispatcher>
<router-link <router-link
:to="`/journal/dispatchers?search-dispatcher=${stats.longestDuties[0].name}`" :to="`/journal/dispatchers?search-dispatcher=${apiStore.dailyStatsData.longestDuties[0].name}`"
> >
<b>{{ stats.longestDuties[0].name }}</b> <b>{{ apiStore.dailyStatsData.longestDuties[0].name }}</b>
</router-link> </router-link>
</template> </template>
<template #station>{{ stats.longestDuties[0].station }}</template> <template #station>{{ apiStore.dailyStatsData.longestDuties[0].station }}</template>
<template #duration> <template #duration>
{{ calculateDuration(stats.longestDuties[0].duration) }} {{ humanizeDuration(apiStore.dailyStatsData.longestDuties[0].duration) }}
</template> </template>
</i18n-t> </i18n-t>
</li> </li>
<li v-if="stats.mostActiveDrivers.length > 0"> <li v-if="apiStore.dailyStatsData.mostActiveDrivers.length > 0">
<i18n-t keypath="journal.daily-stats.most-active-driver"> <i18n-t keypath="journal.daily-stats.most-active-driver">
<template #driver> <template #driver>
<router-link <router-link
:to="`/journal/timetables?search-driver=${stats.mostActiveDrivers[0].name}`" :to="`/journal/timetables?search-driver=${apiStore.dailyStatsData.mostActiveDrivers[0].name}`"
> >
<b>{{ stats.mostActiveDrivers[0].name }}</b> <b>{{ apiStore.dailyStatsData.mostActiveDrivers[0].name }}</b>
</router-link> </router-link>
</template> </template>
<template #distance> <template #distance>
<b class="text--primary">{{ stats.mostActiveDrivers[0].distance.toFixed(2) }} km</b> <b class="text--primary"
>{{ apiStore.dailyStatsData.mostActiveDrivers[0].distance.toFixed(2) }} km</b
>
</template> </template>
</i18n-t> </i18n-t>
</li> </li>
@@ -151,7 +159,11 @@
> >
<span>{{ $t(`journal.daily-stats.${key}`) }}</span> <span>{{ $t(`journal.daily-stats.${key}`) }}</span>
<span> <span>
{{ Object.entries(stats.globalDiff).find(([k, v]) => k == key)?.[1] || '--' }} {{
Object.entries(apiStore.dailyStatsData.globalDiff).find(
([k, v]) => k == key
)?.[1] || '--'
}}
</span> </span>
</span> </span>
</div> </div>
@@ -160,76 +172,25 @@
</section> </section>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; import { computed, onMounted } from 'vue';
import dateMixin from '../../mixins/dateMixin';
import { API } from '../../typings/api';
import { Status } from '../../typings/common';
import { useApiStore } from '../../store/apiStore'; import { useApiStore } from '../../store/apiStore';
import { Status } from '../../typings/common';
import { humanizeDuration } from '../../composables/time';
export default defineComponent({ onMounted(() => {
name: 'journal-daily-stats', apiStore.fetchDailyStats();
});
mixins: [dateMixin], const apiStore = useApiStore();
data() { const topDispatchers = computed(() => {
return { if (!apiStore.dailyStatsData || apiStore.dailyStatsData.mostActiveDispatchers.length == 0)
Status, return [];
statsStatus: Status.Data.Loading,
intervalId: -1,
stats: {} as API.DailyStats.Response, const maxCount = apiStore.dailyStatsData.mostActiveDispatchers[0].count;
apiStore: useApiStore()
};
},
activated() { return apiStore.dailyStatsData.mostActiveDispatchers.filter((disp) => disp.count === maxCount);
this.startFetchingDailyStats();
},
deactivated() {
this.stopFetchingDailyStats();
},
computed: {
topDispatchers() {
if (this.stats.mostActiveDispatchers.length == 0) return [];
const maxCount = this.stats.mostActiveDispatchers[0].count;
return this.stats.mostActiveDispatchers.filter((disp) => disp.count === maxCount);
}
},
methods: {
async fetchDailyTimetableStats() {
try {
const res: API.DailyStats.Response = await (
await this.apiStore.client!.get('api/getDailyStats')
).data;
this.stats = res;
this.statsStatus = Status.Data.Loaded;
} catch (error) {
console.error('Ups! Wystąpił błąd podczas pobierania statystyk rozkładów jazdy...');
this.statsStatus = Status.Data.Error;
}
},
startFetchingDailyStats() {
this.fetchDailyTimetableStats();
if (this.intervalId != -1) return;
this.intervalId = window.setInterval(this.fetchDailyTimetableStats, 60000);
},
stopFetchingDailyStats() {
clearInterval(this.intervalId);
this.intervalId = -1;
}
}
}); });
</script> </script>
@@ -265,7 +226,7 @@ ul.stats-list {
gap: 0.5em; gap: 0.5em;
} }
@include responsive.smallScreen{ @include responsive.smallScreen {
h3 { h3 {
text-align: center; text-align: center;
} }
+19 -1
View File
@@ -9,7 +9,8 @@ export const useApiStore = defineStore('apiStore', {
dataStatuses: { dataStatuses: {
connection: Status.Data.Loading, connection: Status.Data.Loading,
sceneries: Status.Data.Loading, sceneries: Status.Data.Loading,
vehicles: Status.Data.Loading vehicles: Status.Data.Loading,
dailyStatsData: Status.Data.Loading
}, },
activeData: undefined as API.ActiveData.Response | undefined, activeData: undefined as API.ActiveData.Response | undefined,
@@ -18,6 +19,8 @@ export const useApiStore = defineStore('apiStore', {
donatorsData: [] as API.Donators.Response, donatorsData: [] as API.Donators.Response,
sceneryData: [] as StationJSONData[], sceneryData: [] as StationJSONData[],
dailyStatsData: null as API.DailyStats.Response | null,
nextUpdateTime: 0, nextUpdateTime: 0,
nextDataCheckTime: 0, nextDataCheckTime: 0,
@@ -119,6 +122,21 @@ export const useApiStore = defineStore('apiStore', {
this.dataStatuses.vehicles = Status.Data.Error; this.dataStatuses.vehicles = Status.Data.Error;
console.error('Ups! Wystąpił błąd podczas pobierania informacji o pojazdach:', error); console.error('Ups! Wystąpił błąd podczas pobierania informacji o pojazdach:', error);
} }
},
async fetchDailyStats() {
try {
const res: API.DailyStats.Response = await (
await this.client!.get('api/getDailyStats')
).data;
this.dailyStatsData = res;
this.dataStatuses.dailyStatsData = Status.Data.Loaded;
} catch (error) {
console.error('Ups! Wystąpił błąd podczas pobierania statystyk rozkładów jazdy...');
this.dataStatuses.dailyStatsData = Status.Data.Error;
}
} }
} }
}); });