205 lines
7.2 KiB
Vue
205 lines
7.2 KiB
Vue
<script setup>
|
|
import { ref, computed } from 'vue';
|
|
import GoogleIcon from '@Shared/GoogleIcon.vue';
|
|
|
|
// Datos de ejemplo de gastos
|
|
const expenses = ref([
|
|
{
|
|
id: 1,
|
|
date: '2024-08-15',
|
|
concept: 'Catering para evento X',
|
|
reason: 'Servicio de comida para 50 asistentes.',
|
|
amount: 1500.00,
|
|
justificationFile: 'catering_evento_x.pdf'
|
|
},
|
|
{
|
|
id: 2,
|
|
date: '2024-08-14',
|
|
concept: 'Renta de equipo de audio',
|
|
reason: 'Micrófonos y bocinas para el auditorio.',
|
|
amount: 800.00,
|
|
justificationFile: 'renta_audio.pdf'
|
|
},
|
|
{
|
|
id: 3,
|
|
date: '2024-08-10',
|
|
concept: 'Viáticos para conferencista',
|
|
reason: 'Vuelo y hospedaje para Dr. Smith.',
|
|
amount: 1250.00,
|
|
justificationFile: 'viaticos_dr_smith.pdf'
|
|
}
|
|
]);
|
|
|
|
// Computed para calcular el total
|
|
const totalExpenses = computed(() => {
|
|
return expenses.value.reduce((total, expense) => {
|
|
return total + expense.amount;
|
|
}, 0);
|
|
});
|
|
|
|
// Función para ver PDF
|
|
const viewPDF = (fileName) => {
|
|
console.log('Ver PDF:', fileName);
|
|
// Aquí implementarías la lógica para abrir el PDF
|
|
// Por ejemplo: window.open(`/pdfs/${fileName}`, '_blank');
|
|
alert(`Abriendo archivo: ${fileName}`);
|
|
};
|
|
|
|
// Función para formatear moneda
|
|
const formatCurrency = (amount) => {
|
|
return new Intl.NumberFormat('es-MX', {
|
|
style: 'currency',
|
|
currency: 'USD'
|
|
}).format(amount);
|
|
};
|
|
|
|
// Función para formatear fecha
|
|
const formatDate = (dateString) => {
|
|
const date = new Date(dateString);
|
|
return date.toLocaleDateString('es-MX', {
|
|
year: 'numeric',
|
|
month: '2-digit',
|
|
day: '2-digit'
|
|
});
|
|
};
|
|
|
|
// Función para exportar reporte
|
|
const exportReport = () => {
|
|
console.log('Exportar reporte:', expenses.value);
|
|
// Aquí implementarías la lógica para exportar el reporte
|
|
alert('Reporte exportado correctamente');
|
|
};
|
|
|
|
// Función para filtrar por fecha
|
|
const filterByDate = () => {
|
|
// Aquí podrías implementar filtros por fecha
|
|
console.log('Filtrar por fecha');
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div class="p-6 max-w-auto mx-auto">
|
|
<!-- Header -->
|
|
<div class="flex items-start justify-between gap-4">
|
|
<div>
|
|
<h1 class="text-4xl font-extrabold text-gray-900 dark:text-primary-dt">Reporte de Gastos de Eventos</h1>
|
|
<p class="mt-1 text-sm text-gray-500 dark:text-primary-dt/70">Consulta y gestiona los gastos realizados en eventos</p>
|
|
</div>
|
|
|
|
<div class="flex gap-3">
|
|
<button
|
|
@click="filterByDate"
|
|
class="inline-flex items-center gap-2 px-4 py-2 rounded-lg border border-gray-300 bg-white text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-[#2563eb] focus:border-transparent dark:bg-primary-d dark:border-primary/20 dark:text-primary-dt dark:hover:bg-primary/10"
|
|
>
|
|
<GoogleIcon class="text-gray-600 dark:text-primary-dt text-xl" name="filter_list" />
|
|
Filtrar
|
|
</button>
|
|
|
|
<button
|
|
@click="exportReport"
|
|
class="inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-[#2563eb] hover:bg-[#1e40af] text-white shadow-sm focus:outline-none focus:ring-2 focus:ring-[#2563eb] focus:ring-offset-2"
|
|
>
|
|
<GoogleIcon class="text-white text-xl" name="download" />
|
|
Exportar
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Card principal -->
|
|
<section class="mt-6 bg-white rounded-lg shadow-sm p-6 dark:bg-primary-d dark:border-primary/20 dark:text-primary-dt">
|
|
|
|
<!-- Tabla de gastos -->
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full">
|
|
<thead>
|
|
<tr class="border-b border-gray-100 dark:border-primary/20">
|
|
<th class="text-left py-3 px-4 font-semibold text-gray-800 dark:text-primary-dt">FECHA</th>
|
|
<th class="text-left py-3 px-4 font-semibold text-gray-800 dark:text-primary-dt">CONCEPTO</th>
|
|
<th class="text-left py-3 px-4 font-semibold text-gray-800 dark:text-primary-dt">RAZÓN</th>
|
|
<th class="text-right py-3 px-4 font-semibold text-gray-800 dark:text-primary-dt">MONTO</th>
|
|
<th class="text-left py-3 px-4 font-semibold text-gray-800 dark:text-primary-dt">JUSTIFICANTE</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr
|
|
v-for="expense in expenses"
|
|
:key="expense.id"
|
|
class="border-b border-gray-50 dark:border-primary/10 hover:bg-gray-50 dark:hover:bg-primary/5"
|
|
>
|
|
<!-- Fecha -->
|
|
<td class="py-4 px-4">
|
|
<div class="text-sm text-gray-900 dark:text-primary-dt">
|
|
{{ formatDate(expense.date) }}
|
|
</div>
|
|
</td>
|
|
|
|
<!-- Concepto -->
|
|
<td class="py-4 px-4">
|
|
<div class="font-medium text-gray-900 dark:text-primary-dt">
|
|
{{ expense.concept }}
|
|
</div>
|
|
</td>
|
|
|
|
<!-- Razón -->
|
|
<td class="py-4 px-4">
|
|
<div class="text-sm text-gray-600 dark:text-primary-dt/70">
|
|
{{ expense.reason }}
|
|
</div>
|
|
</td>
|
|
|
|
<!-- Monto -->
|
|
<td class="py-4 px-4 text-right">
|
|
<div class="text-lg font-bold text-[#2563eb] dark:text-primary-dt">
|
|
{{ formatCurrency(expense.amount) }}
|
|
</div>
|
|
</td>
|
|
|
|
<!-- Justificante -->
|
|
<td class="py-4 px-4">
|
|
<button
|
|
@click="viewPDF(expense.justificationFile)"
|
|
class="text-blue-600 hover:text-blue-800 underline text-sm font-medium dark:text-blue-400 dark:hover:text-blue-300 transition-colors"
|
|
>
|
|
Ver PDF
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Resumen de gastos -->
|
|
<div class="mt-6 p-4 bg-gray-50 rounded-lg dark:bg-primary/5">
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center gap-2">
|
|
<GoogleIcon class="text-gray-600 dark:text-primary-dt text-xl" name="account_balance_wallet" />
|
|
<span class="text-lg font-medium text-gray-800 dark:text-primary-dt">Total de Gastos:</span>
|
|
</div>
|
|
<div class="text-2xl font-bold text-[#2563eb] dark:text-primary-dt">
|
|
{{ formatCurrency(totalExpenses) }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Footer con estadísticas -->
|
|
<div class="mt-6 border-t border-gray-100 pt-4 flex items-center justify-between dark:border-primary/20">
|
|
<div class="text-sm text-gray-500 dark:text-primary-dt/70">
|
|
Mostrando {{ expenses.length }} gastos registrados
|
|
</div>
|
|
|
|
<div class="flex items-center gap-4">
|
|
<div class="flex items-center gap-2 text-sm">
|
|
<span class="w-3 h-3 bg-blue-400 rounded-full"></span>
|
|
<span class="text-gray-600 dark:text-primary-dt/70">Total: {{ expenses.length }} registros</span>
|
|
</div>
|
|
<div class="flex items-center gap-2 text-sm">
|
|
<span class="w-3 h-3 bg-green-400 rounded-full"></span>
|
|
<span class="text-gray-600 dark:text-primary-dt/70">Justificados: {{ expenses.length }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</section>
|
|
</div>
|
|
</template>
|