feat: migrate CRM screens to Ant Design Vue and expand home dashboard
Preserve the local Ant UI work across views/components and add the new home dashboard chart panels before merging latest main.
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { toFaDigits } from '@/lib/jalali';
|
||||
import type { HomeDashboardSalesSummaryDto } from '@mento/shared';
|
||||
import UiChart, { type UiChartOption } from '@/components/ui/UiChart.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
summary: HomeDashboardSalesSummaryDto;
|
||||
formatAmount: (value: number) => string;
|
||||
}>();
|
||||
|
||||
const slices = computed(() => [
|
||||
{ name: 'باز', value: props.summary.openCount, color: '#3b82f6' },
|
||||
{ name: 'برنده', value: props.summary.wonCount, color: '#10b981' },
|
||||
{ name: 'باخته', value: props.summary.lostCount, color: '#f43f5e' },
|
||||
]);
|
||||
|
||||
const total = computed(() => slices.value.reduce((a, s) => a + s.value, 0));
|
||||
const hasData = computed(() => total.value > 0);
|
||||
|
||||
const option = computed<UiChartOption>(() => ({
|
||||
animationDuration: 400,
|
||||
color: slices.value.map((s) => s.color),
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
textStyle: { fontFamily: 'IRANSans, Tahoma, sans-serif' },
|
||||
formatter: (p) => {
|
||||
const item = Array.isArray(p) ? p[0] : p;
|
||||
return `${item.name}<br/>${toFaDigits(Number(item.value ?? 0))} — ${toFaDigits(item.percent ?? 0)}٪`;
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'pie',
|
||||
radius: ['58%', '82%'],
|
||||
center: ['50%', '50%'],
|
||||
silent: !hasData.value,
|
||||
avoidLabelOverlap: true,
|
||||
itemStyle: { borderRadius: 6, borderColor: '#fff', borderWidth: 2 },
|
||||
label: { show: false },
|
||||
labelLine: { show: false },
|
||||
data: hasData.value
|
||||
? slices.value.map((s) => ({ name: s.name, value: s.value }))
|
||||
: [{ name: '', value: 1, itemStyle: { color: '#e5e7eb' } }],
|
||||
},
|
||||
],
|
||||
}));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="bg-white rounded-2xl border border-slate-200/80 p-4 shadow-sm h-full flex flex-col">
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<h3 class="!m-0 !leading-6 font-bold text-slate-800 text-base">وضعیت معاملات</h3>
|
||||
<span class="text-xs font-bold bg-emerald-50 text-emerald-700 border border-emerald-200/60 px-2.5 py-1 rounded-lg">
|
||||
نرخ برد {{ toFaDigits(summary.winRate) }}٪
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex flex-col sm:flex-row items-center gap-4">
|
||||
<div class="w-full sm:w-[48%] sm:max-w-[240px] shrink-0">
|
||||
<div class="relative w-full aspect-square">
|
||||
<UiChart :option="option" height="100%" />
|
||||
<div class="absolute inset-0 flex flex-col items-center justify-center pointer-events-none">
|
||||
<span class="text-2xl font-black text-slate-800 leading-none">{{ toFaDigits(total) }}</span>
|
||||
<span class="text-xs text-slate-400 mt-1">معامله کل</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full sm:flex-1 min-w-0 space-y-2.5">
|
||||
<div class="p-3 rounded-xl bg-slate-50/80 border border-slate-100 flex items-center justify-between gap-2">
|
||||
<div>
|
||||
<div class="text-xs font-bold text-slate-700">باز</div>
|
||||
<div class="text-[11px] text-slate-400">در جریان</div>
|
||||
</div>
|
||||
<div class="text-left">
|
||||
<div class="text-sm font-black text-slate-800">{{ toFaDigits(summary.openCount) }}</div>
|
||||
<div class="text-xs text-slate-500">{{ formatAmount(summary.openAmount) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-3 rounded-xl bg-emerald-50/50 border border-emerald-100 flex items-center justify-between gap-2">
|
||||
<div>
|
||||
<div class="text-xs font-bold text-emerald-900">برنده (۱۲ ماه)</div>
|
||||
<div class="text-[11px] text-emerald-600/80">تکمیل موفق</div>
|
||||
</div>
|
||||
<div class="text-left">
|
||||
<div class="text-sm font-black text-emerald-700">{{ toFaDigits(summary.wonCount) }}</div>
|
||||
<div class="text-xs text-emerald-600">{{ formatAmount(summary.wonAmount) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-3 rounded-xl bg-rose-50/40 border border-rose-100 flex items-center justify-between gap-2">
|
||||
<div>
|
||||
<div class="text-xs font-bold text-rose-900">باخته (۱۲ ماه)</div>
|
||||
<div class="text-[11px] text-rose-500">لغو یا عدم توافق</div>
|
||||
</div>
|
||||
<div class="text-left">
|
||||
<div class="text-sm font-black text-rose-600">{{ toFaDigits(summary.lostCount) }}</div>
|
||||
<div class="text-xs text-rose-500">{{ formatAmount(summary.lostAmount) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
Reference in New Issue
Block a user