122 lines
2.8 KiB
Vue
122 lines
2.8 KiB
Vue
<template>
|
|
<section class="storage-card">
|
|
<template v-if="item.loading">
|
|
<TextSkeleton custom-class="h-5 w-28" />
|
|
<CircleSkeleton custom-class="mt-3 h-[120px] w-[120px]" />
|
|
<BlockSkeleton custom-class="mt-3 h-4 w-32" />
|
|
</template>
|
|
|
|
<template v-else>
|
|
<p class="font-mono text-[11px] font-medium uppercase tracking-[0.2em] text-white/60">
|
|
{{ item.hostName }}
|
|
</p>
|
|
|
|
<div class="chart-wrapper" :class="item.statusColorClass">
|
|
<svg class="chart-svg" viewBox="0 0 120 120" aria-label="Pourcentage restant">
|
|
<circle
|
|
class="track"
|
|
cx="60" cy="60"
|
|
:r="item.chartRadius"
|
|
/>
|
|
<circle
|
|
class="progress"
|
|
cx="60" cy="60"
|
|
:r="item.chartRadius"
|
|
:style="{
|
|
strokeDasharray: `${item.chartCircumference}`,
|
|
strokeDashoffset: `${item.chartOffset}`
|
|
}"
|
|
/>
|
|
</svg>
|
|
<div class="chart-label">
|
|
<strong class="font-mono text-2xl font-bold leading-none">
|
|
{{ item.remainingPercentText }}
|
|
</strong>
|
|
<span class="mt-1 font-mono text-[9px] uppercase tracking-widest text-m-muted">
|
|
libre
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<p class="font-mono text-xs font-medium text-m-muted/80">
|
|
{{ item.usedText }}
|
|
<span class="mx-0.5 text-m-muted/40">/</span>
|
|
{{ item.totalText }}
|
|
</p>
|
|
</template>
|
|
</section>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import CircleSkeleton from "~/components/skeleton/CircleSkeleton.vue"
|
|
import BlockSkeleton from "~/components/skeleton/BlockSkeleton.vue"
|
|
import TextSkeleton from "~/components/skeleton/TextSkeleton.vue"
|
|
|
|
defineProps<{
|
|
item: {
|
|
loading: boolean
|
|
hostName: string
|
|
statusColorClass: string
|
|
chartRadius: number
|
|
chartCircumference: number
|
|
chartOffset: number
|
|
remainingPercentText: string
|
|
usedText: string
|
|
totalText: string
|
|
}
|
|
}>()
|
|
</script>
|
|
|
|
<style scoped>
|
|
.storage-card {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
padding: 1.25rem 1rem;
|
|
gap: 0.25rem;
|
|
}
|
|
|
|
.chart-wrapper {
|
|
position: relative;
|
|
width: 120px;
|
|
height: 120px;
|
|
}
|
|
|
|
.chart-svg {
|
|
width: 100%;
|
|
height: 100%;
|
|
transform: rotate(-90deg);
|
|
}
|
|
|
|
.track {
|
|
fill: none;
|
|
stroke: rgba(255, 255, 255, 0.06);
|
|
stroke-width: 8;
|
|
}
|
|
|
|
.progress {
|
|
fill: none;
|
|
stroke: currentColor;
|
|
stroke-width: 8;
|
|
stroke-linecap: round;
|
|
transition: stroke-dashoffset 0.8s cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
|
|
.chart-label {
|
|
position: absolute;
|
|
inset: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.status-success {
|
|
color: rgb(var(--m-success));
|
|
}
|
|
|
|
.status-error {
|
|
color: rgb(var(--m-error));
|
|
}
|
|
</style>
|