Preserve the local Ant UI work across views/components and add the new home dashboard chart panels before merging latest main.
82 lines
2.5 KiB
Vue
82 lines
2.5 KiB
Vue
<script setup lang="ts">
|
||
import { computed } from 'vue';
|
||
import { Empty as AEmpty } from 'ant-design-vue';
|
||
import { toFaDigits } from '@/lib/jalali';
|
||
import type { HomeDashboardActivityTypeDto } from '@mento/shared';
|
||
import UiChart, { type UiChartOption } from '@/components/ui/UiChart.vue';
|
||
|
||
const props = defineProps<{
|
||
items: HomeDashboardActivityTypeDto[];
|
||
}>();
|
||
|
||
const rows = computed(() => props.items);
|
||
const hasData = computed(() => rows.value.some((r) => r.count > 0));
|
||
const total = computed(() => rows.value.reduce((a, r) => a + r.count, 0));
|
||
|
||
const option = computed<UiChartOption>(() => ({
|
||
animationDuration: 400,
|
||
grid: { top: 28, right: 8, bottom: 28, left: 8, containLabel: true },
|
||
tooltip: {
|
||
trigger: 'axis',
|
||
axisPointer: { type: 'shadow' },
|
||
textStyle: { fontFamily: 'IRANSans, Tahoma, sans-serif' },
|
||
formatter: (params) => {
|
||
const row = Array.isArray(params) ? params[0] : params;
|
||
const point = rows.value[row.dataIndex ?? 0];
|
||
if (!point) return '';
|
||
return `${point.label}<br/>${toFaDigits(point.count)} فعالیت باز`;
|
||
},
|
||
},
|
||
xAxis: {
|
||
type: 'category',
|
||
data: rows.value.map((r) => r.label),
|
||
axisLine: { show: false },
|
||
axisTick: { show: false },
|
||
axisLabel: {
|
||
color: '#94a3b8',
|
||
fontFamily: 'IRANSans, Tahoma, sans-serif',
|
||
fontSize: 11,
|
||
},
|
||
},
|
||
yAxis: {
|
||
type: 'value',
|
||
minInterval: 1,
|
||
...(hasData.value ? {} : { max: 1 }),
|
||
splitLine: { lineStyle: { color: '#e5e7eb', type: 'dashed' } },
|
||
axisLabel: { show: false },
|
||
},
|
||
series: [
|
||
{
|
||
type: 'bar',
|
||
data: rows.value.map((r) => r.count),
|
||
barMaxWidth: 36,
|
||
itemStyle: {
|
||
color: '#14b8a6',
|
||
borderRadius: [8, 8, 0, 0],
|
||
},
|
||
label: {
|
||
show: true,
|
||
position: 'top',
|
||
color: '#0f172a',
|
||
fontWeight: 700,
|
||
fontFamily: 'IRANSans, Tahoma, sans-serif',
|
||
formatter: (p) => toFaDigits(Number(p.value ?? 0)),
|
||
},
|
||
},
|
||
],
|
||
}));
|
||
</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 text-slate-400">{{ toFaDigits(total) }} مورد</span>
|
||
</div>
|
||
<a-empty v-if="!hasData" description="فعالیت بازی نیست" />
|
||
<div v-else class="h-56">
|
||
<UiChart :option="option" height="224px" />
|
||
</div>
|
||
</section>
|
||
</template>
|