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>
|