Browse Source

Añadi las acciones completas

edita, elimina, agrega fotos, lo guarda en una tabla, genera el reporte en pdf con sus respectivas imagenes, ya quedo perron jsjsjs
main
Rubi 15 hours ago
parent
commit
0c56ac8291
  1. 219
      resources/views/user-dashboard/cuestionario.blade.php
  2. 2
      resources/views/user-dashboard/index.blade.php

219
resources/views/user-dashboard/cuestionario.blade.php

@ -1,7 +1,9 @@
@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') }}">
@ -100,6 +102,7 @@
<th>Fecha salida</th>
<th>Fecha regreso</th>
<th>Motivo</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
@ -108,7 +111,24 @@
</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
@ -119,14 +139,37 @@
const fechaRegreso = document.getElementById('fecha_regreso').value;
const motivo = document.getElementById('motivo').value;
// Función para crear miniatura o mostrar nombre si no hay archivo
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.name}"><br><span>${archivo.name}</span></div>`;
return `<div><img src="${url}" class='miniatura-img img-clickable' data-img-url="${url}" alt="${archivo ? archivo.name : ''}"><br><span>${archivo.name}</span></div>`;
}
// Insertar fila en la tabla
// 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 = `
@ -136,14 +179,18 @@
<td>${fechaSalida ? fechaSalida.replace('T', ' ') : ''}</td>
<td>${fechaRegreso ? fechaRegreso.replace('T', ' ') : ''}</td>
<td>${motivo}</td>
<td>${iconoEditar}${iconoEliminar}${iconoPDF}</td>
`;
tabla.appendChild(fila);
// Limpiar formulario
document.getElementById('form-reporte').reset();
// Volver a asignar eventos a todas las miniaturas
asignarEventosMiniaturas();
asignarEventosAcciones();
Swal.fire({
icon: 'success',
title: '¡Guardado correctamente!',
showConfirmButton: false,
timer: 1500
});
});
// Modal para mostrar imagen grande
@ -157,7 +204,7 @@
modal.style.width = '100vw';
modal.style.height = '100vh';
modal.style.background = 'rgba(0,0,0,0.7)';
modal.style.display = 'flex';
modal.style.display = 'none';
modal.style.alignItems = 'center';
modal.style.justifyContent = 'center';
modal.style.zIndex = 9999;
@ -169,7 +216,6 @@
</div>
`;
document.body.appendChild(modal);
// Cerrar modal al hacer clic fuera de la imagen o en la X
modal.addEventListener('click', function(e) {
if (e.target === modal || e.target.id === 'cerrar-modal-img') {
modal.style.display = 'none';
@ -177,7 +223,6 @@
});
}
// Asignar evento a miniaturas
function asignarEventosMiniaturas() {
crearModalImagen();
document.querySelectorAll('.img-clickable').forEach(img => {
@ -191,8 +236,158 @@
});
}
// Inicializar eventos para miniaturas existentes (por si acaso)
window.onload = asignarEventosMiniaturas;
// 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

2
resources/views/user-dashboard/index.blade.php

@ -1,7 +1,9 @@
@extends('layouts.app')
@section('title', 'Dashboard - PrestamosTecmm')
@push('head')
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}">
@endpush
@section('content')
<!-- Enlazamos el CSS personalizado solo para este dashboard -->

Loading…
Cancel
Save