@extends('layouts.app')
@section('title', 'Reporte de Usuario - PrestamosTecmm')
@push('head')
< link rel = "icon" type = "image/x-icon" href = "{{ asset('favicon.ico') }}" >
@endpush
@section('content')
< link rel = "stylesheet" href = "{{ asset('css/user-dashboard.css') }}" >
< link rel = "stylesheet" href = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" >
< style >
.contenedor-flex {
display: flex;
gap: 32px;
align-items: flex-start;
justify-content: center;
flex-wrap: nowrap;
height: 100%;
}
.tabla-reporte {
font-family: 'Century Gothic', sans-serif;
font-size: 12px;
border-collapse: collapse;
width: 100%;
min-width: 500px;
max-width: 800px;
background: #fff;
box-shadow: 0 2px 8px #0001;
border-radius: 10px;
overflow: hidden;
margin: 0 auto;
}
.tabla-reporte th, .tabla-reporte td {
border: 1px solid #e2e8f0;
padding: 8px;
text-align: center;
vertical-align: middle;
}
.tabla-reporte th {
background: #f7fafc;
font-weight: bold;
}
.miniatura-img {
width: 50px;
height: 50px;
object-fit: cover;
border-radius: 6px;
border: 1px solid #ccc;
}
< / style >
< body class = "user-dashboard-bg" >
<!-- Botón de cerrar sesión -->
< div class = "user-dashboard-logout" >
< form method = "POST" action = "{{ route('logout') }}" >
@csrf
< button type = "submit" class = "user-dashboard-logout-btn" >
< i class = "fas fa-sign-out-alt" > < / i > Cerrar Sesión
< / button >
< / form >
< / div >
< div class = "user-dashboard-header" > PrestamosTecmm< / div >
< div class = "contenedor-flex" >
< div class = "user-dashboard-card" style = "min-width:350px;max-width:400px;flex:1; margin-top:40px;" >
< h1 class = "user-dashboard-title" > Reporte de Usuario< / h1 >
< form id = "form-reporte" style = "font-family: 'Century Gothic', sans-serif; font-size: 12px;" >
< div style = "margin-bottom: 18px; text-align:left;" >
< label for = "foto_gasolina_inicio" style = "font-weight:600; color:#2d3748;" > Foto de la gasolina (antes de salir):< / label > < br > < br >
< input type = "file" id = "foto_gasolina_inicio" name = "foto_gasolina_inicio" accept = "image/*" style = "width:100%;" >
< / div >
< div style = "margin-bottom: 18px; text-align:left;" >
< label for = "foto_vehiculo" style = "font-weight:600; color:#2d3748;" > Foto del vehículo:< / label > < br > < br >
< input type = "file" id = "foto_vehiculo" name = "foto_vehiculo" accept = "image/*" style = "width:100%;" >
< / div >
< div style = "margin-bottom: 18px; text-align:left;" >
< label for = "foto_gasolina_fin" style = "font-weight:600; color:#2d3748;" > Foto de la gasolina (después de regresar):< / label > < br > < br >
< input type = "file" id = "foto_gasolina_fin" name = "foto_gasolina_fin" accept = "image/*" style = "width:100%;" >
< / div >
< div style = "margin-bottom: 18px; text-align:left;" >
< label for = "fecha_salida" style = "font-weight:600; color:#2d3748;" > Fecha y hora de salida:< / label > < br > < br >
< input type = "datetime-local" id = "fecha_salida" name = "fecha_salida" style = "width:100%; padding:8px; border-radius:6px; border:1px solid #ccc;" >
< / div >
< div style = "margin-bottom: 18px; text-align:left;" >
< label for = "fecha_regreso" style = "font-weight:600; color:#2d3748;" > Fecha y hora de regreso:< / label > < br > < br >
< input type = "datetime-local" id = "fecha_regreso" name = "fecha_regreso" style = "width:100%; padding:8px; border-radius:6px; border:1px solid #ccc;" >
< / div >
< div style = "margin-bottom: 18px; text-align:left;" >
< label for = "motivo" style = "font-weight:600; color:#2d3748;" > Motivo del préstamo:< / label > < br > < br >
< textarea id = "motivo" name = "motivo" style = "width:100%; padding:8px; border-radius:6px; border:1px solid #ccc; min-height:100px;" placeholder = "Especifique el motivo del préstamo del vehículo..." > < / textarea >
< / div >
< button type = "submit" class = "user-dashboard-btn" style = "width:100%; margin-top:10px;" > Guardar< / button >
< / form >
< / div >
< div style = "flex:1; min-width:350px; max-width:800px;" >
< table class = "tabla-reporte" id = "tabla-reporte" >
< thead >
< tr >
< th > Gasolina (salida)< / th >
< th > Vehículo< / th >
< th > Gasolina (regreso)< / th >
< th > Fecha salida< / th >
< th > Fecha regreso< / th >
< th > Motivo< / th >
< th > Acciones< / th >
< / tr >
< / thead >
< tbody >
<!-- Aquí se agregarán los registros -->
< / tbody >
< / table >
< / div >
< / div >
<!-- jsPDF y autoTable -->
< script src = "https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js" > < / script >
< script src = "https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.7.0/jspdf.plugin.autotable.min.js" > < / script >
< script >
// Iconos SVG para editar, eliminar y PDF
const iconoEditar = `< button type = 'button' class = 'btn-accion editar' title = 'Editar' style = 'background:none;border:none;cursor:pointer;' > < i class = "fas fa-edit" style = "color:#3182ce;font-size:20px;" > < / i > < / button > `;
const iconoEliminar = `< button type = 'button' class = 'btn-accion eliminar' title = 'Eliminar' style = 'background:none;border:none;cursor:pointer;' > < i class = "fas fa-trash-alt" style = "color:#e53e3e;font-size:20px;" > < / i > < / button > `;
const iconoPDF = `< button type = 'button' class = 'btn-accion pdf' title = 'Generar PDF' style = 'background:none;border:none;cursor:pointer;' > < i class = "fas fa-file-pdf" style = "color:#e53e3e;font-size:20px;" > < / i > < / button > `;
let filaEditando = null;
// Agregar SweetAlert2 CDN si no está
if (!window.Swal) {
var script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/sweetalert2@11';
document.head.appendChild(script);
}
document.getElementById('form-reporte').addEventListener('submit', function(e) {
e.preventDefault();
// Obtener los archivos y datos
const fotoGasIni = document.getElementById('foto_gasolina_inicio').files[0];
const fotoVehiculo = document.getElementById('foto_vehiculo').files[0];
const fotoGasFin = document.getElementById('foto_gasolina_fin').files[0];
const fechaSalida = document.getElementById('fecha_salida').value;
const fechaRegreso = document.getElementById('fecha_regreso').value;
const motivo = document.getElementById('motivo').value;
function crearMiniatura(archivo) {
if (!archivo) return '';
const url = URL.createObjectURL(archivo);
return `< div > < img src = "${url}" class = 'miniatura-img img-clickable' data-img-url = "${url}" alt = "${archivo ? archivo.name : ''}" > < br > < span > ${archivo.name}< / span > < / div > `;
}
// Si estamos editando una fila, actualizamos esa fila y no agregamos una nueva
if (filaEditando) {
filaEditando.innerHTML = `
< td > ${crearMiniatura(fotoGasIni)}< / td >
< td > ${crearMiniatura(fotoVehiculo)}< / td >
< td > ${crearMiniatura(fotoGasFin)}< / td >
< td > ${fechaSalida ? fechaSalida.replace('T', ' ') : ''}< / td >
< td > ${fechaRegreso ? fechaRegreso.replace('T', ' ') : ''}< / td >
< td > ${motivo}< / td >
< td > ${iconoEditar}${iconoEliminar}${iconoPDF}< / td >
`;
filaEditando = null;
document.getElementById('form-reporte').reset();
asignarEventosMiniaturas();
asignarEventosAcciones();
Swal.fire({
icon: 'success',
title: '¡Editado correctamente!',
showConfirmButton: false,
timer: 1500
});
return;
}
// Si no estamos editando, agregamos una nueva fila
const tabla = document.getElementById('tabla-reporte').querySelector('tbody');
const fila = document.createElement('tr');
fila.innerHTML = `
< td > ${crearMiniatura(fotoGasIni)}< / td >
< td > ${crearMiniatura(fotoVehiculo)}< / td >
< td > ${crearMiniatura(fotoGasFin)}< / td >
< td > ${fechaSalida ? fechaSalida.replace('T', ' ') : ''}< / td >
< td > ${fechaRegreso ? fechaRegreso.replace('T', ' ') : ''}< / td >
< td > ${motivo}< / td >
< td > ${iconoEditar}${iconoEliminar}${iconoPDF}< / td >
`;
tabla.appendChild(fila);
document.getElementById('form-reporte').reset();
asignarEventosMiniaturas();
asignarEventosAcciones();
Swal.fire({
icon: 'success',
title: '¡Guardado correctamente!',
showConfirmButton: false,
timer: 1500
});
});
// Modal para mostrar imagen grande
function crearModalImagen() {
if (document.getElementById('modal-img-grande')) return;
const modal = document.createElement('div');
modal.id = 'modal-img-grande';
modal.style.position = 'fixed';
modal.style.top = 0;
modal.style.left = 0;
modal.style.width = '100vw';
modal.style.height = '100vh';
modal.style.background = 'rgba(0,0,0,0.7)';
modal.style.display = 'none';
modal.style.alignItems = 'center';
modal.style.justifyContent = 'center';
modal.style.zIndex = 9999;
modal.style.cursor = 'pointer';
modal.innerHTML = `
< div style = "position:relative; max-width:90vw; max-height:90vh;" >
< span id = "cerrar-modal-img" style = "position:absolute;top:-30px;right:0;font-size:2rem;color:white;cursor:pointer;font-weight:bold;" > × < / span >
< img id = "img-modal-grande" src = "" alt = "Imagen grande" style = "max-width:90vw; max-height:80vh; border-radius:10px; box-shadow:0 2px 16px #0008; background:#fff;" >
< / div >
`;
document.body.appendChild(modal);
modal.addEventListener('click', function(e) {
if (e.target === modal || e.target.id === 'cerrar-modal-img') {
modal.style.display = 'none';
}
});
}
function asignarEventosMiniaturas() {
crearModalImagen();
document.querySelectorAll('.img-clickable').forEach(img => {
img.onclick = function(e) {
e.stopPropagation();
const modal = document.getElementById('modal-img-grande');
const imgModal = document.getElementById('img-modal-grande');
imgModal.src = img.getAttribute('data-img-url');
modal.style.display = 'flex';
};
});
}
// Asignar eventos a los botones de editar, eliminar y PDF
function asignarEventosAcciones() {
document.querySelectorAll('.btn-accion.eliminar').forEach(btn => {
btn.onclick = function() {
Swal.fire({
title: '¿Estás seguro?',
text: 'Esta acción no se puede deshacer',
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Sí, eliminar',
cancelButtonText: 'Cancelar'
}).then((result) => {
if (result.isConfirmed) {
const fila = btn.closest('tr');
fila.remove();
Swal.fire({
icon: 'success',
title: '¡Eliminado correctamente!',
showConfirmButton: false,
timer: 1500
});
}
});
};
});
document.querySelectorAll('.btn-accion.editar').forEach(btn => {
btn.onclick = function() {
const fila = btn.closest('tr');
const celdas = fila.querySelectorAll('td');
document.getElementById('foto_gasolina_inicio').value = '';
document.getElementById('foto_vehiculo').value = '';
document.getElementById('foto_gasolina_fin').value = '';
document.getElementById('fecha_salida').value = celdas[3].innerText.replace(' ', 'T');
document.getElementById('fecha_regreso').value = celdas[4].innerText.replace(' ', 'T');
document.getElementById('motivo').value = celdas[5].innerText;
filaEditando = fila;
window.scrollTo({top:0, behavior:'smooth'});
};
});
document.querySelectorAll('.btn-accion.pdf').forEach(btn => {
btn.onclick = function() {
const fila = btn.closest('tr');
const celdas = fila.querySelectorAll('td');
generarPDFPersonalizado({
motivo: celdas[5].innerText.trim(),
fechaSalida: celdas[3].innerText.trim(),
fechaRegreso: celdas[4].innerText.trim(),
imagenes: [
fila.querySelectorAll('img.miniatura-img')[0]?.src,
fila.querySelectorAll('img.miniatura-img')[1]?.src,
fila.querySelectorAll('img.miniatura-img')[2]?.src
].filter(Boolean),
callback: function() {
Swal.fire({
icon: 'success',
title: '¡PDF generado!',
showConfirmButton: false,
timer: 1500
});
}
});
};
});
}
// Generar PDF con la estructura solicitada, sin recuadros y fechas bien alineadas
function generarPDFPersonalizado(data) {
const { jsPDF } = window.jspdf;
const doc = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'letter' });
const pageWidth = doc.internal.pageSize.getWidth();
const pageHeight = doc.internal.pageSize.getHeight();
// Título
doc.setFont('helvetica', 'bold');
doc.setFontSize(30);
doc.text('PRESTAMOS TECMM', pageWidth / 2, 60, { align: 'center' });
// REPORTE
doc.setFontSize(13);
doc.setFont('helvetica', 'bold');
doc.text('REPORTE', 40, 110);
doc.setFont('helvetica', 'normal');
doc.setFontSize(12);
doc.text(data.motivo || '', 40, 130, { maxWidth: 250 });
// FECHA Y HORA (alineado a la derecha, una debajo de otra)
doc.setFont('helvetica', 'bold');
doc.setFontSize(13);
doc.text('FECHA Y HORA', 320, 110);
doc.setFont('helvetica', 'normal');
doc.setFontSize(12);
doc.text(`Salida: ${data.fechaSalida || ''}`, 320, 130);
doc.text(`Regreso: ${data.fechaRegreso || ''}`, 320, 150);
// LAS 3 IMÁGENES
doc.setFont('helvetica', 'bold');
doc.setFontSize(13);
doc.text('LAS 3 IMÁGENES', 320, 190);
let yImg = 210;
let xImg = 320;
const imagenes = (data.imagenes || []).filter(Boolean);
let cargadas = 0;
if (imagenes.length > 0) {
imagenes.forEach((src, idx) => {
if (src & & src.startsWith('blob:')) {
const img = new window.Image();
img.crossOrigin = '';
img.onload = function() {
doc.addImage(img, 'PNG', xImg, yImg, 60, 60);
xImg += 70;
cargadas++;
if (cargadas === imagenes.length) {
// Firma
doc.setFont('helvetica', 'normal');
doc.setFontSize(15);
doc.line(150, 500, 350, 500);
doc.text('FIRMA', pageWidth / 2, 520, { align: 'center' });
doc.save('reporte_prestamo.pdf');
if (typeof data.callback === 'function') data.callback();
}
};
img.onerror = function() {
cargadas++;
if (cargadas === imagenes.length) {
doc.setFont('helvetica', 'normal');
doc.setFontSize(15);
doc.line(150, 500, 350, 500);
doc.text('FIRMA', pageWidth / 2, 520, { align: 'center' });
doc.save('reporte_prestamo.pdf');
if (typeof data.callback === 'function') data.callback();
}
};
img.src = src;
}
});
} else {
// Firma
doc.setFont('helvetica', 'normal');
doc.setFontSize(15);
doc.line(150, 500, 350, 500);
doc.text('FIRMA', pageWidth / 2, 520, { align: 'center' });
doc.save('reporte_prestamo.pdf');
if (typeof data.callback === 'function') data.callback();
}
}
window.onload = function() {
asignarEventosMiniaturas();
asignarEventosAcciones();
};
< / script >
< / body >
@endsection