275 lines
9.6 KiB
Vue
275 lines
9.6 KiB
Vue
<script setup>
|
|
import { computed } from 'vue';
|
|
import GoogleIcon from '@Shared/GoogleIcon.vue';
|
|
import VueApexCharts from 'vue3-apexcharts';
|
|
|
|
// Props
|
|
const props = defineProps({
|
|
adminInfo: {
|
|
type: Object,
|
|
default: () => ({})
|
|
},
|
|
charts: {
|
|
type: Object,
|
|
default: () => ({})
|
|
}
|
|
});
|
|
|
|
// Datos procesados para los charts
|
|
const chartData = computed(() => {
|
|
// Datos para el gráfico de línea (Solicitudes por Mes)
|
|
const monthlyData = props.charts.requests_by_month || [];
|
|
const lineChartCategories = monthlyData.map(item => item.month_name);
|
|
const lineChartSeries = [{
|
|
name: 'Solicitudes',
|
|
data: monthlyData.map(item => item.total_requests)
|
|
}];
|
|
|
|
// Datos para el gráfico de dona (Solicitudes por Departamento)
|
|
const departmentData = props.charts.requests_by_department || [];
|
|
const donutChartLabels = departmentData.map(item => item.department_name);
|
|
const donutChartSeries = departmentData.map(item => item.total_requests);
|
|
|
|
return {
|
|
lineChartCategories,
|
|
lineChartSeries,
|
|
donutChartLabels,
|
|
donutChartSeries
|
|
};
|
|
});
|
|
|
|
// Datos para el gráfico de línea (Solicitudes por Mes) - Solo para admin
|
|
const lineChartOptions = computed(() => ({
|
|
chart: {
|
|
type: 'line',
|
|
height: 350,
|
|
toolbar: {
|
|
show: false
|
|
},
|
|
background: 'transparent'
|
|
},
|
|
colors: ['#3b82f6'],
|
|
stroke: {
|
|
curve: 'smooth',
|
|
width: 3
|
|
},
|
|
grid: {
|
|
borderColor: 'rgba(148, 163, 184, 0.2)',
|
|
strokeDashArray: 3,
|
|
xaxis: {
|
|
lines: {
|
|
show: true
|
|
}
|
|
},
|
|
yaxis: {
|
|
lines: {
|
|
show: true
|
|
}
|
|
}
|
|
},
|
|
xaxis: {
|
|
categories: chartData.value.lineChartCategories,
|
|
labels: {
|
|
style: {
|
|
colors: '#64748b',
|
|
fontSize: '12px'
|
|
}
|
|
},
|
|
axisBorder: {
|
|
color: 'rgba(148, 163, 184, 0.2)'
|
|
}
|
|
},
|
|
yaxis: {
|
|
min: 0,
|
|
labels: {
|
|
style: {
|
|
colors: '#64748b',
|
|
fontSize: '12px'
|
|
}
|
|
}
|
|
},
|
|
markers: {
|
|
size: 6,
|
|
colors: ['#3b82f6'],
|
|
strokeColors: '#fff',
|
|
strokeWidth: 2,
|
|
hover: {
|
|
size: 8
|
|
}
|
|
},
|
|
tooltip: {
|
|
theme: 'dark'
|
|
}
|
|
}));
|
|
|
|
const lineChartSeries = computed(() => chartData.value.lineChartSeries);
|
|
|
|
// Datos para el gráfico de dona (Solicitudes por Departamento) - Solo para admin
|
|
const donutChartOptions = computed(() => ({
|
|
chart: {
|
|
type: 'donut',
|
|
height: 350
|
|
},
|
|
colors: ['#8b5cf6', '#10b981', '#f59e0b', '#ef4444', '#3b82f6', '#f97316'],
|
|
labels: chartData.value.donutChartLabels,
|
|
legend: {
|
|
position: 'right',
|
|
fontSize: '14px',
|
|
labels: {
|
|
colors: '#64748b'
|
|
}
|
|
},
|
|
plotOptions: {
|
|
pie: {
|
|
donut: {
|
|
size: '60%'
|
|
}
|
|
}
|
|
},
|
|
dataLabels: {
|
|
enabled: true,
|
|
formatter: function(val, opts) {
|
|
return opts.w.config.series[opts.seriesIndex]
|
|
},
|
|
style: {
|
|
fontSize: '14px',
|
|
colors: ['#fff']
|
|
}
|
|
},
|
|
tooltip: {
|
|
theme: 'dark'
|
|
}
|
|
}));
|
|
|
|
const donutChartSeries = computed(() => chartData.value.donutChartSeries);
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<!-- Banner de bienvenida -->
|
|
<section
|
|
class="relative mb-8 overflow-hidden rounded-2xl bg-gradient-to-r from-indigo-600 to-purple-600 text-white"
|
|
>
|
|
<div class="relative z-10 p-6 md:p-8">
|
|
<p class="text-2xl md:text-3xl font-semibold">
|
|
Bienvenido, {{ $page.user.name }}
|
|
</p>
|
|
<p class="mt-2 text-white/90">
|
|
Administra el sistema de vacaciones y supervisa el rendimiento organizacional.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Tarjetas de KPIs -->
|
|
<section class="mb-8 grid grid-cols-1 gap-6 md:grid-cols-2 xl:grid-cols-4">
|
|
<!-- Total Empleados -->
|
|
<article class="rounded-xl bg-white p-6 shadow with-transition hover:shadow-lg dark:bg-slate-800">
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center gap-4">
|
|
<GoogleIcon name="group" class="text-blue-500 text-5xl" />
|
|
<div>
|
|
<h3 class="text-sm text-slate-500 dark:text-slate-400">Total Empleados</h3>
|
|
<p class="text-2xl font-bold text-slate-900 dark:text-slate-100">{{ adminInfo.total_users }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</article>
|
|
|
|
<!-- Solicitudes Este Mes -->
|
|
<article class="rounded-xl bg-white p-6 shadow with-transition hover:shadow-lg dark:bg-slate-800">
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center gap-4">
|
|
<GoogleIcon name="description" class="text-blue-500 text-5xl" />
|
|
<div>
|
|
<h3 class="text-sm text-slate-500 dark:text-slate-400">Solicitudes Este Mes</h3>
|
|
<p class="text-2xl font-bold text-slate-900 dark:text-slate-100">{{ adminInfo.monthly_requests }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</article>
|
|
|
|
<!-- Solicitudes Aprobadas -->
|
|
<article class="rounded-xl bg-white p-6 shadow with-transition hover:shadow-lg dark:bg-slate-800">
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center gap-4">
|
|
<GoogleIcon name="check_circle" class="text-emerald-500 text-5xl" />
|
|
<div>
|
|
<h3 class="text-sm text-slate-500 dark:text-slate-400">Solicitudes Aprobadas</h3>
|
|
<p class="text-2xl font-bold text-slate-900 dark:text-slate-100">{{ adminInfo.approved_requests }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</article>
|
|
|
|
<!-- Eficiencia Aprobación -->
|
|
<article class="rounded-xl bg-white p-6 shadow with-transition hover:shadow-lg dark:bg-slate-800">
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center gap-4">
|
|
<GoogleIcon name="trending_up" class="text-emerald-500 text-5xl" />
|
|
<div>
|
|
<h3 class="text-sm text-slate-500 dark:text-slate-400">Eficiencia Aprobación</h3>
|
|
<p class="text-2xl font-bold text-slate-900 dark:text-slate-100">{{ adminInfo.approval_efficiency }}%</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</article>
|
|
</section>
|
|
|
|
<!-- Gráficos -->
|
|
<section v-if="charts.requests_by_month && charts.requests_by_department" class="grid grid-cols-1 gap-6 lg:grid-cols-2">
|
|
<!-- Gráfico de Solicitudes por Mes -->
|
|
<article class="rounded-xl bg-white p-6 shadow dark:bg-slate-800">
|
|
<div class="mb-6 flex items-center gap-3">
|
|
<GoogleIcon name="trending_up" class="text-blue-500 text-2xl" />
|
|
<div>
|
|
<h3 class="text-lg font-semibold text-slate-900 dark:text-slate-100">Solicitudes por Mes</h3>
|
|
<p class="text-sm text-slate-500 dark:text-slate-400">Tendencia de solicitudes durante el año</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="h-80">
|
|
<VueApexCharts
|
|
type="line"
|
|
height="100%"
|
|
:options="lineChartOptions"
|
|
:series="lineChartSeries"
|
|
/>
|
|
</div>
|
|
</article>
|
|
|
|
<!-- Gráfico de Solicitudes por Departamento -->
|
|
<article class="rounded-xl bg-white p-6 shadow dark:bg-slate-800">
|
|
<div class="mb-6 flex items-center gap-3">
|
|
<GoogleIcon name="pie_chart" class="text-purple-500 text-2xl" />
|
|
<div>
|
|
<h3 class="text-lg font-semibold text-slate-900 dark:text-slate-100">Solicitudes por Departamento</h3>
|
|
<p class="text-sm text-slate-500 dark:text-slate-400">Distribución de solicitudes por área</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="h-80">
|
|
<VueApexCharts
|
|
type="donut"
|
|
height="100%"
|
|
:options="donutChartOptions"
|
|
:series="donutChartSeries"
|
|
/>
|
|
</div>
|
|
</article>
|
|
</section>
|
|
|
|
<!-- Estado vacío para charts -->
|
|
<section v-else class="rounded-xl bg-white p-6 shadow dark:bg-slate-800">
|
|
<div class="text-center py-12">
|
|
<GoogleIcon name="analytics" class="text-slate-400 text-6xl mx-auto mb-4" />
|
|
<h3 class="text-lg font-semibold text-slate-900 dark:text-slate-100 mb-2">
|
|
No hay datos de gráficos disponibles
|
|
</h3>
|
|
<p class="text-slate-500 dark:text-slate-400">
|
|
Los gráficos se mostrarán cuando haya datos de solicitudes disponibles.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</template>
|