113 lines
4.3 KiB
Vue

<script setup lang="ts">
const { data: stats } = useFetch('/api/admin/stats-public', { lazy: true });
const runtimeConfig = useRuntimeConfig();
const plausibleHost = runtimeConfig.public.plausible.apiHost;
const heartbeatHost = runtimeConfig.public.heartbeatLink;
const overall = ref(true);
const activeStats = computed(() => {
if (stats.value === null) {
return undefined;
}
return overall.value
? stats.value.overall
: stats.value.current || {};
});
const formatNumber = (number: number): string => {
if (number > 1000000) {
return `${Math.round(10 * number / 1000000) / 10}M`;
}
if (number > 1000) {
return `${Math.round(10 * number / 1000) / 10}k`;
}
return number.toString();
};
const formatDuration = (secondsCount: number): string => {
const minutes = Math.floor(secondsCount / 60);
const seconds = secondsCount % 60;
const res = [];
if (minutes > 0) {
res.push(`${minutes}m`);
}
if (seconds > 0) {
res.push(`${seconds}s`);
}
return res.join(' ');
};
</script>
<template>
<div v-if="stats !== null">
<p class="h6 mb-2">
<T>footer.stats.header</T><T>quotation.colon</T>
</p>
<p v-if="overall" :key="`a${overall}`" class="small mb-2">
<strong><T>footer.stats.overall</T></strong>
|
<a href="#" @click.prevent="overall = false"><T>footer.stats.current</T></a>
</p>
<p v-else :key="`b${overall}`" class="small mb-2">
<a href="#" @click.prevent="overall = true"><T>footer.stats.overall</T></a>
|
<strong><T>footer.stats.current</T></strong>
</p>
<ul v-if="activeStats" :key="`${overall}`" class="list-unstyled">
<li v-if="activeStats.cards" class="mb-2">
<Icon v="id-card" />
<T>footer.stats.keys.cards</T><T>quotation.colon</T>
<strong>{{ formatNumber(activeStats.cards) }}</strong>
</li>
<li v-if="activeStats.visitors" class="mb-2">
<Icon v="fingerprint" />
<T>footer.stats.keys.visitors</T><T>quotation.colon</T>
<strong>{{ formatNumber(activeStats.visitors) }}</strong> / <T>footer.stats.month</T>
</li>
<li v-if="activeStats.pageViews" class="mb-2">
<Icon v="mouse" />
<T>footer.stats.keys.pageviews</T><T>quotation.colon</T>
<strong>{{ formatNumber(activeStats.pageViews) }}</strong> / <T>footer.stats.month</T>
</li>
<li v-if="activeStats.online" class="mb-2">
<Icon v="user-clock" />
<T>footer.stats.keys.realTimeVisitors</T><T>quotation.colon</T>
<strong>{{ formatNumber(activeStats.online) }}</strong>
</li>
<li v-if="activeStats.users" class="mb-2">
<Icon v="user-friends" />
<T>footer.stats.keys.users</T><T>quotation.colon</T>
<strong>{{ formatNumber(activeStats.users) }}</strong>
</li>
<li v-if="activeStats.visitDuration" class="mb-2">
<Icon v="clock" />
<T>footer.stats.keys.visitDuration</T><T>quotation.colon</T>
<strong>{{ formatDuration(activeStats.visitDuration) }}</strong>
</li>
<li v-if="activeStats.uptime" class="mb-2">
<Icon v="monitor-heart-rate" />
<T>footer.stats.keys.uptime</T><T>quotation.colon</T>
<strong>{{ activeStats.uptime }}%</strong>
</li>
<li v-if="activeStats.responseTime" class="mb-2">
<Icon v="stopwatch" />
<T>footer.stats.keys.responseTime</T><T>quotation.colon</T>
<strong>{{ activeStats.responseTime }} ms</strong>
</li>
<li class="mb-2 small">
<a v-if="$isGranted()" :href="`${plausibleHost}/${$t('domain')}?period=30d`" target="_blank" rel="noopener">
<Icon v="external-link" />
Plausible
</a>
<a :href="`${heartbeatHost}`" target="_blank" rel="noopener">
<Icon v="external-link" />
heartbeat
</a>
</li>
</ul>
</div>
</template>