Files
pleno-vue/src/components/displays/superuser/configuration/ModuleUsageMeter.vue
T

117 lines
3.0 KiB
Vue

<script setup>
import { computed, onMounted, ref } from "vue";
import { useI18n } from "vue-i18n";
import { listModuleUsageSummary } from "@/services/moduleUsage.js";
const props = defineProps({
moduleKey: {
type: String,
required: true,
},
metricKey: {
type: String,
required: true,
},
});
const { t, locale } = useI18n();
const loading = ref(false);
const metric = ref(null);
const usagePercent = computed(() => Number(metric.value?.usage_percent ?? 0));
const hasMetric = computed(() => metric.value && (metric.value.used !== null || metric.value.limit !== null));
const load = async () => {
loading.value = true;
try {
const response = await listModuleUsageSummary({ module: props.moduleKey });
const metrics = Array.isArray(response?.data?.data?.metrics) ? response.data.data.metrics : [];
metric.value = metrics.find((row) => row.metric_key === props.metricKey) || null;
} finally {
loading.value = false;
}
};
function formatNumber(value) {
if (value === null || value === undefined || Number.isNaN(Number(value))) {
return "--";
}
return new Intl.NumberFormat(locale.value || "da").format(Number(value));
}
function formatPercent(value) {
if (value === null || value === undefined || Number.isNaN(Number(value))) {
return "--";
}
return `${Number(value).toFixed(1)}%`;
}
function progressClass(value) {
const percent = Number(value);
if (!Number.isFinite(percent)) {
return "";
}
if (percent >= 100) {
return "is-danger";
}
if (percent >= 90) {
return "is-warning";
}
return "is-success";
}
onMounted(load);
</script>
<template>
<div v-if="loading || hasMetric" class="module-usage-meter" :data-testid="`module-usage-meter-${moduleKey}-${metricKey}`">
<div class="module-usage-meter__top">
<span>{{ metric?.metric_label || $t("system_status.labels.quota_usage") }}</span>
<strong>{{ loading ? "--" : formatPercent(metric?.usage_percent) }}</strong>
</div>
<progress
class="progress module-usage-meter__progress"
:class="progressClass(usagePercent)"
:value="Math.max(0, Math.min(100, usagePercent))"
max="100"
/>
<div class="module-usage-meter__stats">
<span>{{ t("system_status.labels.used") }}: {{ formatNumber(metric?.used) }}</span>
<span>{{ t("system_status.labels.limit") }}: {{ formatNumber(metric?.limit) }}</span>
<span>{{ t("system_status.labels.remaining") }}: {{ formatNumber(metric?.remaining) }}</span>
</div>
</div>
</template>
<style scoped>
.module-usage-meter {
display: grid;
gap: 0.4rem;
margin-top: 0.75rem;
padding: 0.75rem;
border: 1px solid #d7dde7;
border-radius: 8px;
background: #f8fafc;
}
.module-usage-meter__top {
display: flex;
justify-content: space-between;
gap: 0.75rem;
color: #334155;
}
.module-usage-meter__progress {
height: 0.55rem;
margin: 0;
}
.module-usage-meter__stats {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
color: #475569;
font-size: 0.85rem;
}
</style>