feat: Implement initial Vue 3 application structure with SSR, routing, authentication, and core dashboard components.

This commit is contained in:
2026-01-19 00:37:35 +07:00
parent 9f521c76f4
commit eed14fa0e5
14 changed files with 1029 additions and 127 deletions

View File

@@ -0,0 +1,105 @@
<script setup lang="ts">
interface Trend {
value: number;
isPositive: boolean;
}
interface Props {
title: string;
value: string | number;
icon?: string;
trend?: Trend;
color?: 'primary' | 'success' | 'warning' | 'danger' | 'info';
}
const props = withDefaults(defineProps<Props>(), {
color: 'primary'
});
const gradients = {
primary: 'from-primary/20 to-primary/5',
success: 'from-success/20 to-success/5',
warning: 'from-yellow-100 to-yellow-50',
danger: 'from-danger/20 to-danger/5',
info: 'from-info/20 to-info/5',
};
const iconColors = {
primary: 'text-primary',
success: 'text-success',
warning: 'text-yellow-600',
danger: 'text-danger',
info: 'text-info',
};
</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'
]"
/>
<!-- Content -->
<div class="relative z-10">
<div class="flex items-start justify-between mb-3">
<div>
<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>
</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'
]"
/>
{{ Math.abs(trend.value) }}%
</span>
<span class="text-gray-500">vs last month</span>
</div>
</div>
</div>
</template>
<style scoped>
.stats-card {
transform: translateY(0);
}
.stats-card:hover {
transform: translateY(-2px);
}
</style>