Files
mbmanager-dashboard/src/components/dashboard/PropertyStatusWidget.vue
T

118 lines
3.9 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup>
import { useLayout } from '@/layout/composables/layout';
import { computed, onMounted, ref, watch } from 'vue';
const props = defineProps({
statusStats: {
type: Array,
default: () => []
},
loading: {
type: Boolean,
default: false
}
});
const { isDarkTheme } = useLayout();
const chartData = ref(null);
const chartOptions = ref(null);
const defaultColors = ['#10b981', '#3b82f6', '#f59e0b', '#8b5cf6', '#ec4899', '#06b6d4', '#64748b'];
function updateChart() {
const statuses = props.statusStats || [];
const labels = statuses.length > 0 ? statuses.map((s) => s.name) : ['نامشخص'];
const data = statuses.length > 0 ? statuses.map((s) => s.count) : [0];
const colors = statuses.map((s, i) => s.color || defaultColors[i % defaultColors.length]);
chartData.value = {
labels: labels,
datasets: [
{
data: data,
backgroundColor: colors,
borderWidth: 2,
borderColor: isDarkTheme.value ? '#18181b' : '#ffffff'
}
]
};
chartOptions.value = {
maintainAspectRatio: false,
responsive: true,
plugins: {
legend: {
position: 'bottom',
rtl: true,
labels: {
usePointStyle: true,
pointStyle: 'circle',
padding: 16,
font: {
family: 'Estedad',
size: 12
}
}
},
tooltip: {
rtl: true,
titleFont: { family: 'Estedad', size: 13 },
bodyFont: { family: 'Estedad', size: 12 },
callbacks: {
label: function (context) {
const count = context.parsed;
const statusItem = statuses[context.dataIndex];
const pct = statusItem?.percentage !== undefined ? ` (${statusItem.percentage}٪)` : '';
return `${context.label}: ${Number(count).toLocaleString('fa-IR')} ملک${pct}`;
}
}
}
},
cutout: '65%'
};
}
watch(() => props.statusStats, () => {
updateChart();
}, { deep: true });
watch(isDarkTheme, () => {
updateChart();
});
onMounted(() => {
updateChart();
});
</script>
<template>
<div class="card h-full p-5 border border-surface-200 dark:border-surface-800 rounded-2xl bg-surface-0 dark:bg-surface-900">
<div class="flex justify-between items-center mb-4">
<div>
<h3 class="font-bold text-lg text-surface-900 dark:text-surface-0 mb-1">وضعیت اسناد و املاک</h3>
<p class="text-xs text-muted-color">تفکیک املاک بر اساس وضعیت سند و مالکیت</p>
</div>
<div class="flex items-center gap-2">
<span class="inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-medium bg-emerald-50 dark:bg-emerald-950/40 text-emerald-600 dark:text-emerald-400">
<i class="pi pi-check-circle text-[10px]"></i>
وضعیت‌ها
</span>
</div>
</div>
<div v-if="loading" class="h-72 flex items-center justify-center">
<i class="pi pi-spin pi-spinner text-primary text-3xl"></i>
</div>
<div v-else-if="!statusStats || statusStats.length === 0" class="h-72 flex flex-col items-center justify-center text-muted-color">
<i class="pi pi-chart-pie text-4xl mb-2 opacity-40"></i>
<span class="text-sm">اطلاعات وضعیت املاک ثبت نشده است</span>
</div>
<div v-else class="h-72">
<Chart type="doughnut" :data="chartData" :options="chartOptions" class="h-full w-full" />
</div>
</div>
</template>