50 lines
1.2 KiB
Vue
50 lines
1.2 KiB
Vue
<script setup>
|
|
import { Card, CardContent } from "@/Components/ui/card";
|
|
|
|
const props = defineProps({
|
|
label: String,
|
|
value: [String, Number],
|
|
icon: Object,
|
|
iconBg: {
|
|
type: String,
|
|
default: "bg-primary/10",
|
|
},
|
|
iconColor: {
|
|
type: String,
|
|
default: "text-primary",
|
|
},
|
|
loading: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<Card class="hover:border-primary/30 hover:shadow transition">
|
|
<CardContent class="px-4 py-5 flex items-center gap-4">
|
|
<span
|
|
:class="[
|
|
'inline-flex items-center justify-center h-10 w-10 rounded-md transition',
|
|
iconBg,
|
|
iconColor,
|
|
]"
|
|
>
|
|
<component :is="icon" class="w-5 h-5" />
|
|
</span>
|
|
<div class="flex-1 min-w-0">
|
|
<p class="text-xs text-muted-foreground uppercase tracking-wide truncate">
|
|
{{ label }}
|
|
</p>
|
|
<p
|
|
v-if="!loading"
|
|
class="text-2xl font-semibold tracking-tight text-foreground mt-1"
|
|
>
|
|
{{ value ?? "—" }}
|
|
</p>
|
|
<div v-else class="h-8 w-20 bg-muted animate-pulse rounded mt-1" />
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</template>
|