6f68bf5fa7
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
66 lines
1.9 KiB
Vue
66 lines
1.9 KiB
Vue
<template>
|
|
<v-row dense>
|
|
<v-col v-for="card in cards" :key="card.label" cols="12" sm="6" md="4" lg="3" xl="2">
|
|
<v-card class="fc-stat">
|
|
<v-card-text>
|
|
<div class="fc-stat__label text-caption">{{ card.label }}</div>
|
|
<div class="fc-stat__value">{{ card.value }}</div>
|
|
</v-card-text>
|
|
</v-card>
|
|
</v-col>
|
|
</v-row>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed } from 'vue'
|
|
|
|
const props = defineProps({
|
|
stats: { type: Object, default: null }
|
|
})
|
|
|
|
function formatBytes(bytes) {
|
|
if (!bytes) return '0 B'
|
|
const units = ['B', 'KiB', 'MiB', 'GiB', 'TiB']
|
|
let i = 0
|
|
let value = bytes
|
|
while (value >= 1024 && i < units.length - 1) { value /= 1024; i++ }
|
|
return `${value.toFixed(value >= 100 || i === 0 ? 0 : 1)} ${units[i]}`
|
|
}
|
|
|
|
const cards = computed(() => {
|
|
const s = props.stats
|
|
if (!s) return [
|
|
{ label: 'Total images', value: '—' },
|
|
{ label: 'Total tags', value: '—' },
|
|
{ label: 'Storage used', value: '—' },
|
|
{ label: 'Subscriptions', value: '—' },
|
|
{ label: 'Pending tasks', value: '—' },
|
|
{ label: 'Failed tasks', value: '—' }
|
|
]
|
|
return [
|
|
{ label: 'Total images', value: s.total_images.toLocaleString() },
|
|
{ label: 'Total tags', value: s.total_tags.toLocaleString() },
|
|
{ label: 'Storage used', value: formatBytes(s.storage_bytes) },
|
|
{ label: 'Subscriptions', value: (s.subscription_count ?? 0).toLocaleString() },
|
|
{ label: 'Pending', value: (s.tasks.pending + s.tasks.queued).toLocaleString() },
|
|
{ label: 'Failed', value: s.tasks.failed.toLocaleString() }
|
|
]
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.fc-stat__label {
|
|
color: rgb(var(--v-theme-on-surface-variant, var(--v-theme-on-surface)));
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.05em;
|
|
font-weight: 500;
|
|
}
|
|
.fc-stat__value {
|
|
font-family: 'Fraunces', Georgia, serif;
|
|
font-size: 28px;
|
|
font-weight: 500;
|
|
color: rgb(var(--v-theme-on-surface));
|
|
margin-top: 4px;
|
|
}
|
|
</style>
|