Files
CRM_Montzar/apps/web/src/views/DiscReportView.vue
T

76 lines
2.9 KiB
Vue
Raw Normal View History

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { RouterLink } from 'vue-router';
import type { DiscDistributionRow } from '@mento/shared';
import { api } from '@/lib/api';
import { toFaDigits } from '@/lib/jalali';
import { UiButton, UiPageHeader } from '@/components/ui';
const rows = ref<DiscDistributionRow[]>([]);
const error = ref('');
const loading = ref(true);
const exporting = ref(false);
onMounted(async () => {
try {
const { data } = await api.get<DiscDistributionRow[]>('/behavior/disc/distribution');
rows.value = data;
} catch {
error.value = 'گزارش توزیع تیپ‌ها بارگذاری نشد.';
} finally {
loading.value = false;
}
});
async function exportExcel() {
exporting.value = true;
error.value = '';
try {
const { data } = await api.get<Blob>('/behavior/disc/export', { responseType: 'blob' });
const url = URL.createObjectURL(data);
const link = document.createElement('a');
link.href = url;
link.download = 'disc.xlsx';
link.click();
URL.revokeObjectURL(url);
} catch {
error.value = 'خروجی اکسل ناموفق بود.';
} finally {
exporting.value = false;
}
}
const total = () => rows.value.reduce((sum, row) => sum + row.count, 0);
</script>
<template>
<section class="page">
<UiPageHeader title="توزیع تیپ‌های DISC" lead="فقط ارزیابی‌های تأییدشده و قابل اتکا، در محدودهٔ دسترسی شما" :back-to="{ name: 'contacts' }">
<template #actions>
<UiButton variant="outline" :disabled="exporting" @click="exportExcel">خروجی اکسل</UiButton>
</template>
</UiPageHeader>
<p v-if="loading" class="muted">در حال بارگذاری…</p>
<p v-else-if="error" class="error">{{ error }}</p>
<p v-else-if="!rows.length" class="muted">هنوز تیپ قابل اتکایی ثبت نشده است.</p>
<ul v-else class="list">
<li v-for="row in rows" :key="row.label">
<RouterLink :to="{ name: 'contacts', query: { disc: row.label } }">{{ row.label }}</RouterLink>
<span>{{ toFaDigits(row.count) }}</span>
<i><b :style="{ width: `${total() ? Math.round((row.count / total()) * 100) : 0}%` }" /></i>
</li>
</ul>
<p class="muted">درصدها سهم مشتریان دارای ارزیابی معتبر هستند، نه دقت یک آزمون روان‌شناسی.</p>
</section>
</template>
<style scoped>
.page { display: flex; flex-direction: column; gap: 0.8rem; }
.list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.55rem; }
.list li { display: grid; grid-template-columns: 6rem auto 1fr; gap: 0.6rem; align-items: center; }
.list i { height: 8px; background: #e2e8f0; border-radius: 99px; overflow: hidden; }
.list b { display: block; height: 100%; background: #0f766e; }
.muted { color: #64748b; }
.error { color: #b91c1c; }
</style>