102 lines
2.3 KiB
Vue
102 lines
2.3 KiB
Vue
<template>
|
|
<!--
|
|
Ported from legacy henza_admin/src/components/statistics-cards/StatisticsCardLine.vue.
|
|
|
|
The legacy component renders an ApexCharts sparkline under the figure, but
|
|
EVERY live caller passes :hideChart="true" (verified: 3 of 3 on the wholesale
|
|
dashboard), and the only apexchart markup in either dashboard sits inside
|
|
commented-out Vuexy demo cards. So the chart branch is not ported and
|
|
vue-apexcharts is not a dependency — adding it would ship a library nothing
|
|
renders.
|
|
-->
|
|
<a-card class="stat-card">
|
|
<div class="stat-row">
|
|
<span class="stat-icon" :class="`icon-${color}`">
|
|
<component :is="iconComponent" />
|
|
</span>
|
|
<div>
|
|
<h2 class="stat-value">{{ statistic }}</h2>
|
|
<span class="stat-title">{{ statisticTitle }}</span>
|
|
</div>
|
|
</div>
|
|
</a-card>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed } from 'vue';
|
|
import {
|
|
ShoppingOutlined,
|
|
TeamOutlined,
|
|
DollarOutlined,
|
|
BarChartOutlined,
|
|
} from '@ant-design/icons-vue';
|
|
|
|
const props = withDefaults(
|
|
defineProps<{
|
|
icon?: string;
|
|
statistic?: string | number;
|
|
statisticTitle?: string;
|
|
color?: string;
|
|
/** Kept for call-site parity; the chart branch is not ported (see above). */
|
|
hideChart?: boolean;
|
|
}>(),
|
|
{ color: 'primary', hideChart: true },
|
|
);
|
|
|
|
/** feather name -> ant icon, matching the icons the live cards ask for */
|
|
const ICONS: Record<string, unknown> = {
|
|
UsersIcon: TeamOutlined,
|
|
ShoppingBagIcon: ShoppingOutlined,
|
|
DollarSignIcon: DollarOutlined,
|
|
BarChartIcon: BarChartOutlined,
|
|
};
|
|
|
|
const iconComponent = computed(() => ICONS[props.icon ?? ''] ?? BarChartOutlined);
|
|
</script>
|
|
|
|
<style scoped>
|
|
.stat-card {
|
|
height: 100%;
|
|
}
|
|
.stat-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 1rem;
|
|
}
|
|
.stat-icon {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 48px;
|
|
height: 48px;
|
|
border-radius: 50%;
|
|
font-size: 22px;
|
|
flex-shrink: 0;
|
|
}
|
|
.icon-primary {
|
|
background: rgba(28, 45, 86, 0.1);
|
|
color: #1c2d56;
|
|
}
|
|
.icon-warning {
|
|
background: rgba(255, 159, 67, 0.12);
|
|
color: #ff9f43;
|
|
}
|
|
.icon-success {
|
|
background: rgba(40, 199, 111, 0.12);
|
|
color: #28c76f;
|
|
}
|
|
.icon-danger {
|
|
background: rgba(234, 84, 85, 0.12);
|
|
color: #ea5455;
|
|
}
|
|
.stat-value {
|
|
margin: 0;
|
|
font-size: 20px;
|
|
color: #1c2d56;
|
|
}
|
|
.stat-title {
|
|
font-size: 12px;
|
|
color: #888;
|
|
}
|
|
</style>
|