Preserve the local Ant UI work across views/components and add the new home dashboard chart panels before merging latest main.
99 lines
2.9 KiB
Vue
99 lines
2.9 KiB
Vue
<script setup lang="ts">
|
|
import { computed } from 'vue';
|
|
import { toFaDigits } from '@/lib/jalali';
|
|
import type { HomeDashboardSeriesPointDto } from '@mento/shared';
|
|
import UiChart, { type UiChartOption } from '@/components/ui/UiChart.vue';
|
|
|
|
const props = defineProps<{
|
|
series: HomeDashboardSeriesPointDto[];
|
|
}>();
|
|
|
|
const points = computed(() => props.series);
|
|
const hasData = computed(() => points.value.some((p) => p.value > 0));
|
|
const total = computed(() => points.value.reduce((a, p) => a + p.value, 0));
|
|
|
|
const option = computed<UiChartOption>(() => ({
|
|
animationDuration: 450,
|
|
grid: { top: 36, right: 12, bottom: 28, left: 12, containLabel: true },
|
|
tooltip: {
|
|
trigger: 'axis',
|
|
textStyle: { fontFamily: 'IRANSans, Tahoma, sans-serif' },
|
|
formatter: (params) => {
|
|
const row = Array.isArray(params) ? params[0] : params;
|
|
const point = points.value[row.dataIndex ?? 0];
|
|
if (!point) return '';
|
|
return `${point.monthLabel}<br/><strong>${toFaDigits(point.value)}</strong> مشتری جدید`;
|
|
},
|
|
},
|
|
xAxis: {
|
|
type: 'category',
|
|
data: points.value.map((p) => p.monthLabel),
|
|
axisLine: { show: false },
|
|
axisTick: { show: false },
|
|
axisLabel: {
|
|
color: '#94a3b8',
|
|
fontFamily: 'IRANSans, Tahoma, sans-serif',
|
|
fontSize: 11,
|
|
},
|
|
},
|
|
yAxis: {
|
|
type: 'value',
|
|
min: 0,
|
|
minInterval: 1,
|
|
...(hasData.value ? {} : { max: 1 }),
|
|
splitLine: { lineStyle: { color: '#e5e7eb', type: 'dashed' } },
|
|
axisLabel: { show: false },
|
|
},
|
|
series: [
|
|
{
|
|
type: 'bar',
|
|
data: points.value.map((p) => p.value),
|
|
barMaxWidth: 32,
|
|
itemStyle: {
|
|
color: {
|
|
type: 'linear',
|
|
x: 0,
|
|
y: 0,
|
|
x2: 0,
|
|
y2: 1,
|
|
colorStops: [
|
|
{ offset: 0, color: '#34d399' },
|
|
{ offset: 1, color: '#059669' },
|
|
],
|
|
},
|
|
borderRadius: [8, 8, 0, 0],
|
|
},
|
|
label: {
|
|
show: true,
|
|
position: 'top',
|
|
color: '#64748b',
|
|
fontFamily: 'IRANSans, Tahoma, sans-serif',
|
|
fontSize: 11,
|
|
formatter: (p) => toFaDigits(Number(p.value ?? 0)),
|
|
},
|
|
},
|
|
{
|
|
type: 'line',
|
|
data: points.value.map((p) => p.value),
|
|
smooth: 0.35,
|
|
symbol: 'none',
|
|
lineStyle: { color: '#0f766e', width: 2, opacity: 0.55 },
|
|
},
|
|
],
|
|
}));
|
|
</script>
|
|
|
|
<template>
|
|
<section class="bg-white rounded-2xl border border-slate-200/80 p-4 shadow-sm h-full">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 class="font-bold text-slate-800 text-base">روند رشد مشتریان</h3>
|
|
<span v-if="hasData" class="text-xs font-bold bg-emerald-50 text-emerald-700 px-2.5 py-1 rounded-lg">
|
|
{{ toFaDigits(total) }} در ۱۲ ماه
|
|
</span>
|
|
</div>
|
|
<div class="h-56">
|
|
<UiChart :option="option" height="224px" />
|
|
</div>
|
|
</section>
|
|
</template>
|