Files
RecruIT/resources/js/Components/Rq/RqStatCard.vue

55 lines
2.1 KiB
Vue

<script setup>
/**
* RqStatCard.vue — Carte KPI dashboard admin
*
* @prop label String — libellé (ex: "Total Candidats")
* @prop value String | Number — valeur principale
* @prop sub String — sous-texte (ex: "+3 ce mois")
* @prop color 'primary' | 'gold' | 'green' | 'sky' | 'red'
* @prop unit String — unité affichée après la valeur (ex: "/ 20")
*/
import { computed } from 'vue';
const props = defineProps({
label: { type: String, required: true },
value: { type: [String, Number], required: true },
sub: { type: String, default: null },
color: { type: String, default: 'primary' },
unit: { type: String, default: null },
});
const colorMap = {
primary: { text: 'text-primary', glow: 'from-primary/10' },
gold: { text: 'text-highlight', glow: 'from-highlight/15' },
green: { text: 'text-success', glow: 'from-success/10' },
sky: { text: 'text-primary-light', glow: 'from-primary-light/10' },
red: { text: 'text-accent', glow: 'from-accent/10' },
};
const c = computed(() => colorMap[props.color] ?? colorMap.primary);
</script>
<template>
<div class="relative bg-surface rounded-2xl border border-ink/[0.07] shadow-sm p-5 overflow-hidden
transition-all duration-200 hover:-translate-y-0.5 hover:shadow-md group cursor-default">
<!-- Label -->
<p class="text-2xs font-black uppercase tracking-[0.18em] text-ink/40 mb-2.5">
{{ label }}
</p>
<!-- Value -->
<p :class="['font-serif font-black leading-none', c.text]"
style="font-size: clamp(1.75rem, 2.5vw, 2.25rem);">
{{ value }}
<span v-if="unit" class="text-base font-sans font-bold text-ink/30 ml-1">{{ unit }}</span>
</p>
<!-- Sub -->
<p v-if="sub" class="mt-1.5 text-2xs font-semibold text-ink/40">{{ sub }}</p>
<!-- Decorative blob -->
<div :class="['absolute bottom-0 right-0 w-20 h-20 rounded-full bg-gradient-radial to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500', c.glow]" />
</div>
</template>