Componentize dashboard middle section and add Mento brand assets.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
<script setup lang="ts">
|
||||
import UiIcon from '@/components/UiIcon.vue';
|
||||
import type { HomeDashboardKpiDto } from '@mento/shared';
|
||||
|
||||
defineProps<{
|
||||
kpis: HomeDashboardKpiDto[];
|
||||
currency: string;
|
||||
formatValue: (key: string, value: number) => string;
|
||||
formatChange: (value: number | null) => string;
|
||||
}>();
|
||||
|
||||
const icons: Record<string, 'calendar' | 'users' | 'briefcase' | 'check'> = {
|
||||
sales: 'calendar',
|
||||
customers: 'users',
|
||||
'open-deals': 'briefcase',
|
||||
followups: 'check',
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="kpi-row">
|
||||
<article v-for="kpi in kpis" :key="kpi.key" class="kpi-card">
|
||||
<div class="kpi-icon">
|
||||
<UiIcon :name="icons[kpi.key] ?? 'chart'" :size="20" />
|
||||
</div>
|
||||
<div class="kpi-text">
|
||||
<p class="kpi-label">{{ kpi.label }}</p>
|
||||
<strong class="kpi-value">{{ formatValue(kpi.key, kpi.value) }}</strong>
|
||||
<span
|
||||
v-if="kpi.changePercent != null"
|
||||
class="kpi-change"
|
||||
:class="{ down: kpi.changePercent < 0 }"
|
||||
>
|
||||
{{ formatChange(kpi.changePercent) }} {{ kpi.changeLabel }}
|
||||
</span>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.kpi-row {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 0.9rem;
|
||||
}
|
||||
|
||||
.kpi-card {
|
||||
display: flex;
|
||||
gap: 0.85rem;
|
||||
align-items: flex-start;
|
||||
background: #fff;
|
||||
border-radius: 22px;
|
||||
padding: 1.1rem 1.15rem;
|
||||
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.04);
|
||||
border: 1px solid #eef2f7;
|
||||
}
|
||||
|
||||
.kpi-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 16px;
|
||||
background: #ecfdf8;
|
||||
color: #14b8a6;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.kpi-label {
|
||||
margin: 0;
|
||||
color: #94a3b8;
|
||||
font-size: 0.84rem;
|
||||
}
|
||||
|
||||
.kpi-value {
|
||||
display: block;
|
||||
margin-top: 0.25rem;
|
||||
font-size: 1.18rem;
|
||||
color: #0f172a;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.kpi-change {
|
||||
display: inline-block;
|
||||
margin-top: 0.45rem;
|
||||
padding: 0.18rem 0.5rem;
|
||||
border-radius: 999px;
|
||||
background: #dcfce7;
|
||||
color: #16a34a;
|
||||
font-size: 0.72rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.kpi-change.down {
|
||||
background: #fee2e2;
|
||||
color: #dc2626;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.kpi-row {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.kpi-row {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user