dodatkowe statystyki dnia

This commit is contained in:
2023-06-21 17:16:02 +02:00
parent 5b2b6bdea2
commit 66262e3fcd
4 changed files with 166 additions and 100 deletions
+131 -92
View File
@@ -1,56 +1,59 @@
<template> <template>
<section class="daily-stats"> <section class="daily-stats">
<span :data-active="data.statsStatus"> <span :data-active="statsStatus">
<b v-if="data.statsStatus == DataStatus.Loading"> <b v-if="statsStatus == DataStatus.Loading">
{{ $t('app.loading') }} {{ $t('app.loading') }}
</b> </b>
<b v-else-if="data.stats.distanceSum == null"> <b v-else-if="stats.distanceSum == null">
{{ $t('journal.daily-stats-info') }} {{ $t('journal.daily-stats-info') }}
</b> </b>
<span> <h3>{{ $t('journal.daily-stats-title') }} {{ new Date().toLocaleDateString($i18n.locale) }}</h3>
<div v-if="data.stats.totalTimetables"> <hr style="margin-bottom: 0.5em" />
<span class="stats-list">
<div v-if="stats.totalTimetables">
&bull; &bull;
<i18n-t keypath="journal.timetable-stats-total"> <i18n-t keypath="journal.timetable-stats-total">
<template #count> <template #count>
<b class="text--primary"> <b class="text--primary">
{{ data.stats.totalTimetables }} {{ stats.totalTimetables }}
{{ $t('journal.timetable-count', data.stats.totalTimetables) }} {{ $t('journal.timetable-count', stats.totalTimetables) }}
</b> </b>
</template> </template>
<template #distance> <template #distance>
<b class="text--primary"> {{ data.stats.distanceSum?.toFixed(2) }} km </b> <b class="text--primary"> {{ stats.distanceSum?.toFixed(2) }} km</b>
</template> </template>
</i18n-t> </i18n-t>
</div> </div>
<div v-if="data.stats.timetableId"> <div v-if="stats.timetableId">
&bull; &bull;
<i18n-t keypath="journal.timetable-stats-longest"> <i18n-t keypath="journal.timetable-stats-longest">
<template #id> <template #id>
<router-link :to="`/journal/timetables?timetableId=${data.stats.timetableId}`"> <router-link :to="`/journal/timetables?timetableId=${stats.timetableId}`">
<b>{{ data.stats.timetableId }}</b> <b>{{ stats.timetableId }}</b>
</router-link> </router-link>
</template> </template>
<template #author> <template #author>
<router-link :to="`/journal/dispatchers?dispatcherName=${data.stats.timetableAuthor}`"> <router-link :to="`/journal/dispatchers?dispatcherName=${stats.timetableAuthor}`">
<b>{{ data.stats.timetableAuthor }}</b> <b>{{ stats.timetableAuthor }}</b>
</router-link> </router-link>
</template> </template>
<template #driver> <template #driver>
<b>{{ data.stats.timetableDriver }}</b> <b class="text--primary">{{ stats.timetableDriver }}</b>
</template> </template>
<template #distance> <template #distance>
<b class="text--primary">{{ data.stats.timetableRouteDistance }} km</b> <b class="text--primary">{{ stats.timetableRouteDistance }} km</b>
</template> </template>
</i18n-t> </i18n-t>
</div> </div>
<div v-if="firstPlaceDispatchers.length == 1"> <div v-if="firstPlaceDispatchers.length == 1">
&bull; &bull;
<i18n-t keypath="journal.timetable-stats-most-active"> <i18n-t keypath="journal.timetable-stats-most-active-dr">
<template #dispatcher> <template #dispatcher>
<router-link :to="`/journal/dispatchers?dispatcherName=${firstPlaceDispatchers[0].name}`"> <router-link :to="`/journal/dispatchers?dispatcherName=${firstPlaceDispatchers[0].name}`">
<b>{{ firstPlaceDispatchers[0].name }}</b> <b>{{ firstPlaceDispatchers[0].name }}</b>
@@ -67,7 +70,7 @@
<div v-if="firstPlaceDispatchers.length > 1"> <div v-if="firstPlaceDispatchers.length > 1">
&bull; &bull;
<i18n-t keypath="journal.timetable-stats-most-active-many"> <i18n-t keypath="journal.timetable-stats-most-active-dr-many">
<template #dispatchers> <template #dispatchers>
<span v-for="(disp, i) in firstPlaceDispatchers"> <span v-for="(disp, i) in firstPlaceDispatchers">
<span v-if="i == firstPlaceDispatchers.length - 1"> {{ $t('general.and') }} </span> <span v-if="i == firstPlaceDispatchers.length - 1"> {{ $t('general.and') }} </span>
@@ -88,101 +91,133 @@
</template> </template>
</i18n-t> </i18n-t>
</div> </div>
<div v-if="stats.longestDuties.length > 0">
&bull;
<i18n-t keypath="journal.timetable-stats-longest-duties">
<template #dispatcher>
<router-link :to="`/journal/dispatchers?dispatcherName=${stats.longestDuties[0].name}`">
<b>{{ stats.longestDuties[0].name }}</b>
</router-link>
</template>
<template #station>{{ stats.longestDuties[0].station }}</template>
<template #duration>
{{ calculateDuration(stats.longestDuties[0].duration) }}
</template>
</i18n-t>
</div>
<div v-if="stats.mostActiveDrivers.length > 0">
&bull;
<i18n-t keypath="journal.timetable-stats-most-active-driver">
<template #driver>
<b class="text--primary">{{ stats.mostActiveDrivers[0].name }}</b>
</template>
<template #distance>
<b class="text--primary">{{ stats.mostActiveDrivers[0].distance }} km</b>
</template>
</i18n-t>
</div>
</span> </span>
</span> </span>
</section> </section>
</template> </template>
<script setup lang="ts"> <script lang="ts">
import axios from 'axios'; import axios from 'axios';
import { computed, onActivated, onDeactivated, onMounted, reactive, ref } from 'vue'; import { defineComponent } from 'vue';
import dateMixin from '../../mixins/dateMixin';
import { DataStatus } from '../../scripts/enums/DataStatus'; import { DataStatus } from '../../scripts/enums/DataStatus';
import { ITimetablesDailyStats, ITimetablesDailyStatsResponse } from '../../scripts/interfaces/api/StatsAPIData'; import { ITimetablesDailyStats, ITimetablesDailyStatsResponse } from '../../scripts/interfaces/api/StatsAPIData';
import { URLs } from '../../scripts/utils/apiURLs'; import { URLs } from '../../scripts/utils/apiURLs';
import StorageManager from '../../scripts/managers/storageManager';
const intervalId = ref(-1); export default defineComponent({
mixins: [dateMixin],
emits: ['toggleStatsOpen'],
const emit = defineEmits<{ data() {
(e: 'toggleStatsOpen', value: boolean): void; return {
}>(); DataStatus,
statsStatus: DataStatus.Loading,
intervalId: -1,
const data = reactive({ stats: {
statsStatus: DataStatus.Loading, totalTimetables: 0,
distanceSum: 0,
stats: { distanceAvg: 0,
totalTimetables: 0, timetableAuthor: '',
distanceSum: 0, timetableDriver: '',
distanceAvg: 0, timetableId: 0,
timetableAuthor: '', timetableRouteDistance: 0,
timetableDriver: '', longestDuties: [],
timetableId: 0, mostActiveDrivers: [],
timetableRouteDistance: 0, mostActiveDispatchers: [],
} as ITimetablesDailyStats,
mostActiveDispatchers: [],
} as ITimetablesDailyStats,
});
const firstPlaceDispatchers = computed(() => {
if (data.stats.mostActiveDispatchers.length == 0) return [];
const maxCount = data.stats.mostActiveDispatchers[0].count;
return data.stats.mostActiveDispatchers.filter((disp) => disp.count === maxCount);
});
async function fetchDailyTimetableStats() {
try {
const {
distanceAvg,
distanceSum,
maxTimetable,
totalTimetables,
mostActiveDispatchers,
}: ITimetablesDailyStatsResponse = await (
await axios.get(`${URLs.stacjownikAPI}/api/getDailyTimetableStats`)
).data;
data.stats = {
totalTimetables,
distanceSum,
distanceAvg,
timetableAuthor: maxTimetable?.authorName || '',
timetableDriver: maxTimetable?.driverName || '',
timetableId: maxTimetable?.id || 0,
timetableRouteDistance: maxTimetable?.routeDistance || 0,
mostActiveDispatchers,
}; };
},
data.statsStatus = DataStatus.Loaded; activated() {
} catch (error) { this.startFetchingDailyStats();
console.error('Ups! Wystąpił błąd podczas pobierania statystyk rozkładów jazdy...'); this.$emit('toggleStatsOpen', true);
data.statsStatus = DataStatus.Error; },
}
}
function startFetchingDailyStats() { deactivated() {
fetchDailyTimetableStats(); this.stopFetchingDailyStats();
},
if (intervalId.value != -1) return; computed: {
firstPlaceDispatchers() {
if (this.stats.mostActiveDispatchers.length == 0) return [];
const maxCount = this.stats.mostActiveDispatchers[0].count;
intervalId.value = setInterval(fetchDailyTimetableStats, 60000); return this.stats.mostActiveDispatchers.filter((disp) => disp.count === maxCount);
} },
},
function stopFetchingDailyStats() { methods: {
clearInterval(intervalId.value); async fetchDailyTimetableStats() {
intervalId.value = -1; try {
} const res: ITimetablesDailyStatsResponse = await (
await axios.get(`${URLs.stacjownikAPI}/api/getDailyTimetableStats`)
).data;
onActivated(() => { this.stats = {
startFetchingDailyStats(); totalTimetables: res.totalTimetables,
emit('toggleStatsOpen', true); distanceSum: res.distanceSum,
distanceAvg: res.distanceAvg,
timetableAuthor: res.maxTimetable?.authorName || '',
timetableDriver: res.maxTimetable?.driverName || '',
timetableId: res.maxTimetable?.id || 0,
timetableRouteDistance: res.maxTimetable?.routeDistance || 0,
mostActiveDispatchers: res.mostActiveDispatchers,
mostActiveDrivers: res.mostActiveDrivers,
longestDuties: res.longestDuties,
};
this.statsStatus = DataStatus.Loaded;
} catch (error) {
console.error('Ups! Wystąpił błąd podczas pobierania statystyk rozkładów jazdy...');
this.statsStatus = DataStatus.Error;
}
},
startFetchingDailyStats() {
this.fetchDailyTimetableStats();
if (this.intervalId != -1) return;
this.intervalId = setInterval(this.fetchDailyTimetableStats, 60000);
},
stopFetchingDailyStats() {
clearInterval(this.intervalId);
this.intervalId = -1;
},
},
}); });
onDeactivated(() => {
stopFetchingDailyStats();
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@@ -192,5 +227,9 @@ onDeactivated(() => {
.daily-stats > span[data-active='0'] { .daily-stats > span[data-active='0'] {
opacity: 0.75; opacity: 0.75;
} }
.stats-list a {
text-decoration: underline;
}
</style> </style>
+7 -4
View File
@@ -312,10 +312,13 @@
"stats-distance": "DISTANCE", "stats-distance": "DISTANCE",
"stats-stations": "STATIONS", "stats-stations": "STATIONS",
"timetable-stats-total": "Today, dispatchers made so far {count} with total distance of {distance}", "timetable-stats-title": "Daily stats on {date}",
"timetable-stats-longest": "The longest timetable today is #{id} made by {author} for {driver} - {distance}", "timetable-stats-total": "Issued timetables: {count} (total distance: {distance})",
"timetable-stats-most-active": "The most active dispatcher today is {dispatcher} who created {count}", "timetable-stats-longest": "The longest timetable: #{id} (made by {author} for {driver}, distance: {distance})",
"timetable-stats-most-active-many": "The most active dispatchers today are {dispatchers} who created {count} each", "timetable-stats-most-active-dr": "The most active dispatcher: {dispatcher} (created {count})",
"timetable-stats-most-active-dr-many": "The most active dispatchers: {dispatchers} (created {count} each)",
"timetable-stats-most-active-driver": "The most active driver: {driver} (has driven {distance})",
"timetable-stats-longest-duties": "The longest service: {dispatcher} at {station} (duration: {duration})",
"timetable-count": "timetable | timetables", "timetable-count": "timetable | timetables",
+6 -4
View File
@@ -317,10 +317,12 @@
"stats-distance": "DYSTANS", "stats-distance": "DYSTANS",
"stats-stations": "STACJE", "stats-stations": "STACJE",
"timetable-stats-total": "Dyżurni stworzyli dziś {count} o łącznym dystansie {distance}", "timetable-stats-total": "Stworzone rozkłady jazdy: {count} (łączny dystans: {distance})",
"timetable-stats-longest": "Najdłuższym rozkładem jazdy jest dzisiaj #{id} stworzony przez dyżurnego {author} dla maszynisty {driver} - {distance}", "timetable-stats-longest": "Najdłuższy rozkład jazdy: #{id} (stworzony przez dyżurnego {author} dla maszynisty {driver} o dystansie {distance})",
"timetable-stats-most-active": "Dzisiejszym najaktywniejszym dyżurnym jest {dispatcher}, który stworzył {count}", "timetable-stats-most-active-dr": "Najaktywniejszy dyżurny: {dispatcher} (stworzył {count})",
"timetable-stats-most-active-many": "Dzisiejszymi najaktywniejszymi dyżurnymi są {dispatchers}, którzy stworzyli po {count}", "timetable-stats-most-active-dr-many": "Najaktywniejsi dyżurni: {dispatchers} (stworzyli po {count})",
"timetable-stats-most-active-driver": "Najaktywniejszy maszynista: {driver} (przejechał łącznie {distance})",
"timetable-stats-longest-duties": "Najdłuższa służba: {dispatcher} na scenerii {station} (czas trwania: {duration})",
"timetable-count": "rozkład jazdy | rozkładów jazdy", "timetable-count": "rozkład jazdy | rozkładów jazdy",
@@ -14,6 +14,17 @@ export interface ITimetablesDailyStats {
name: string; name: string;
count: number; count: number;
}[]; }[];
mostActiveDrivers: {
name: string;
distance: number;
}[];
longestDuties: {
name: string;
duration: number;
station: string;
}[];
} }
export interface ITimetablesDailyStatsResponse { export interface ITimetablesDailyStatsResponse {
@@ -26,5 +37,16 @@ export interface ITimetablesDailyStatsResponse {
name: string; name: string;
count: number; count: number;
}[]; }[];
mostActiveDrivers: {
name: string;
distance: number;
}[];
longestDuties: {
name: string;
duration: number;
station: string;
}[];
} }