update ui

This commit is contained in:
2026-01-23 19:04:24 +07:00
parent 7d3d33ef7e
commit 476c0eb647
14 changed files with 554 additions and 44 deletions

View File

@@ -1,4 +1,6 @@
<script setup lang="ts">
import { VNode } from 'vue';
interface Trend {
value: number;
isPositive: boolean;
@@ -7,7 +9,7 @@ interface Trend {
interface Props {
title: string;
value: string | number;
icon?: string;
icon?: string | VNode;
trend?: Trend;
color?: 'primary' | 'success' | 'warning' | 'danger' | 'info';
}
@@ -34,24 +36,12 @@ const iconColors = {
</script>
<template>
<div
:class="[
'stats-card relative overflow-hidden rounded-2xl p-6 bg-gradient-to-br',
gradients[color],
'border border-white/50 shadow-sm hover:shadow-md transition-all duration-300',
'group cursor-pointer'
]"
>
<!-- Background Icon (decorative) -->
<div
v-if="icon"
:class="[
'absolute -right-4 -bottom-4 opacity-10 group-hover:opacity-20 transition-opacity',
icon,
'text-8xl'
]"
/>
<div :class="[
'stats-card relative overflow-hidden rounded-2xl p-6 bg-gradient-to-br',
gradients[color],
'border border-white/50 shadow-sm hover:shadow-md transition-all duration-300',
'group cursor-pointer'
]">
<!-- Content -->
<div class="relative z-10">
<div class="flex items-start justify-between mb-3">
@@ -59,33 +49,26 @@ const iconColors = {
<p class="text-sm font-medium text-gray-600 mb-1">{{ title }}</p>
<p class="text-3xl font-bold text-gray-900">{{ value }}</p>
</div>
<div
v-if="icon"
:class="[
'w-12 h-12 rounded-xl flex items-center justify-center',
'bg-white/80 shadow-sm',
iconColors[color]
]"
>
<span :class="[icon, 'w-6 h-6']" />
<div v-if="icon" :class="[
'w-12 h-12 rounded-xl flex items-center justify-center',
'bg-white/80 shadow-sm',
iconColors[color]
]">
<component :is="icon" class="w-6 h-6" />
</div>
</div>
<!-- Trend Indicator -->
<div v-if="trend" class="flex items-center gap-1 text-sm">
<span
:class="[
'flex items-center gap-1 font-medium',
trend.isPositive ? 'text-success' : 'text-danger'
]"
>
<span
:class="[
'w-4 h-4',
trend.isPositive ? 'i-heroicons-arrow-trending-up' : 'i-heroicons-arrow-trending-down'
]"
/>
<span :class="[
'flex items-center gap-1 font-medium',
trend.isPositive ? 'text-success' : 'text-danger'
]">
<span :class="[
'w-4 h-4',
trend.isPositive ? 'i-heroicons-arrow-trending-up' : 'i-heroicons-arrow-trending-down'
]" />
{{ Math.abs(trend.value) }}%
</span>
<span class="text-gray-500">vs last month</span>

View File

@@ -0,0 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" v-if="filled" viewBox="0 0 580 524"><path d="M10 234v112c0 46 38 84 84 84s84-38 84-84V234c0-46-38-84-84-84s-84 38-84 84zM206 94v252c0 46 38 84 84 84s84-38 84-84V94c0-46-38-84-84-84s-84 38-84 84zm196 56v196c0 46 38 84 84 84s84-38 84-84V150c0-46-38-84-84-84s-84 38-84 84z" fill="#a6acb9"/><path d="M10 500c0-8 6-14 14-14h532c8 0 14 6 14 14s-6 14-14 14H24c-8 0-14-6-14-14z" fill="#1e3050"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" v-else viewBox="-10 -226 532 468"><path d="M272-184c9 0 16 7 16 16v352c0 9-7 16-16 16h-32c-9 0-16-7-16-16v-352c0-9 7-16 16-16h32zm-32-32c-26 0-48 22-48 48v352c0 27 22 48 48 48h32c27 0 48-21 48-48v-352c0-26-21-48-48-48h-32zM80 8c9 0 16 7 16 16v160c0 9-7 16-16 16H48c-9 0-16-7-16-16V24c0-9 7-16 16-16h32zM48-24C22-24 0-2 0 24v160c0 27 22 48 48 48h32c27 0 48-21 48-48V24c0-26-21-48-48-48H48zm384-96h32c9 0 16 7 16 16v288c0 9-7 16-16 16h-32c-9 0-16-7-16-16v-288c0-9 7-16 16-16zm-48 16v288c0 27 22 48 48 48h32c27 0 48-21 48-48v-288c0-26-21-48-48-48h-32c-26 0-48 22-48 48z" fill="#1e3050"/></svg>
</template>
<script lang="ts" setup>
defineProps<{ filled?: boolean }>();
</script>