Juan Felipe Zapata Moreno 7986cc3650 Cambio exportación Excel
2025-10-07 13:21:00 -06:00

224 lines
7.2 KiB
Vue

<script setup>
import { ref, watch } from "vue";
import axios from "axios";
import DateRange from "@/Components/Dashboard/Form/DateRange.vue";
const props = defineProps({
show: Boolean
});
const emit = defineEmits(['close']);
const loading = ref(false);
const form = ref({
startDate: new Date().toISOString().slice(0, 10),
endDate: new Date().toISOString().slice(0, 10),
department: '' // 1 para Atención Ciudadana, 3 para DIF
});
const dateRange = ref({
start: new Date().toISOString().slice(0, 10),
end: new Date().toISOString().slice(0, 10)
});
const departments = [
{ id: '', name: 'Seleccionar departamento' },
{ id: 1, name: 'Atención Ciudadana' },
{ id: 3, name: 'DIF' }
];
// Watch para actualizar fechas desde DateRange
watch(dateRange, (newRange) => {
form.value.startDate = newRange.start;
form.value.endDate = newRange.end;
}, { deep: true });
const exportToExcel = async () => {
if (!form.value.department) {
alert('Por favor selecciona el departamento');
return;
}
loading.value = true;
try {
const params = {
start_date: form.value.startDate,
end_date: form.value.endDate,
department: form.value.department
};
console.log('Enviando parámetros:', params);
const response = await axios({
method: 'GET',
url: '/api/export-excel',
params: params,
responseType: 'blob',
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
},
timeout: 60000
});
if (!response.data || response.data.size === 0) {
throw new Error('El archivo descargado está vacío');
}
const contentType = response.headers['content-type'] || '';
if (!contentType.includes('spreadsheet') && !contentType.includes('excel') && !contentType.includes('octet-stream')) {
const text = await response.data.text();
console.error('Respuesta inesperada:', text);
throw new Error('El servidor no devolvió un archivo Excel válido');
}
const blob = new Blob([response.data], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
});
const timestamp = new Date().toISOString().slice(0, 19).replace(/:/g, '-');
const departmentName = departments.find(d => d.id === form.value.department)?.name.replace(/\s+/g, '_') || 'departamento';
const filename = `beneficiarios_${departmentName}_${form.value.startDate}_${form.value.endDate}_${timestamp}.xlsx`;
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, filename);
} else {
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = filename;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
}
closeModal();
alert('Archivo Excel descargado exitosamente');
} catch (error) {
console.error('Error exportando Excel:', error);
let errorMessage = 'Error al exportar el archivo Excel';
if (error.response?.status === 400 && error.response?.data?.error) {
errorMessage = error.response.data.error;
} else if (error.response?.status === 500) {
errorMessage = 'Error interno del servidor. Intente nuevamente.';
} else if (error.message) {
errorMessage = error.message;
} else if (error.code === 'ECONNABORTED') {
errorMessage = 'La descarga tardó demasiado. Intente con un rango de fechas menor.';
}
alert(errorMessage);
} finally {
loading.value = false;
}
};
const closeModal = () => {
form.value = {
startDate: new Date().toISOString().slice(0, 10),
endDate: new Date().toISOString().slice(0, 10),
department: ''
};
dateRange.value = {
start: new Date().toISOString().slice(0, 10),
end: new Date().toISOString().slice(0, 10)
};
emit('close');
};
</script>
<template>
<!-- Modal Backdrop -->
<div
v-if="show"
class="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4"
@click.self="closeModal"
>
<div class="bg-white rounded-xl max-w-2xl w-full max-h-[90vh] overflow-y-auto">
<!-- Header -->
<div class="p-6 border-b border-gray-200">
<div class="flex items-center justify-between">
<h3 class="text-lg font-semibold text-gray-900">
Exportar a Excel
</h3>
<button
@click="closeModal"
class="text-gray-400 hover:text-gray-600 transition-colors"
>
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
<p class="text-sm text-gray-600 mt-2">
Configure los filtros para exportar los datos de beneficiarios
</p>
</div>
<!-- Body -->
<div class="p-6 space-y-6">
<!-- Rango de Fechas -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Rango de Fechas
</label>
<DateRange
v-model="dateRange"
:presets="true"
title-start="Fecha inicio"
title-end="Fecha fin"
/>
</div>
<!-- Departamento -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Departamento <span class="text-red-500">*</span>
</label>
<select
v-model="form.department"
class="w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500"
>
<option v-for="dept in departments" :key="dept.id" :value="dept.id">
{{ dept.name }}
</option>
</select>
<p class="text-xs text-gray-500 mt-2">
Se exportarán todos los registros del departamento seleccionado
</p>
</div>
</div>
<!-- Footer -->
<div class="p-6 border-t border-gray-200 flex justify-end space-x-3">
<button
@click="closeModal"
class="px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 rounded-md hover:bg-gray-200 transition-colors"
>
Cancelar
</button>
<button
@click="exportToExcel"
:disabled="loading || !form.department"
class="px-4 py-2 text-sm font-medium text-white bg-green-600 rounded-md hover:bg-green-700 disabled:bg-gray-300 disabled:cursor-not-allowed transition-colors flex items-center"
>
<svg v-if="loading" class="animate-spin -ml-1 mr-2 h-4 w-4 text-white" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"/>
</svg>
{{ loading ? 'Exportando...' : 'Exportar Excel' }}
</button>
</div>
</div>
</div>
</template>