feat(herramientas): agregar soporte de fotografias y evidencias para herramientas, kits y asignaciones de custodia
This commit is contained in:
+103
-13
@@ -146,6 +146,13 @@
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<div class="app-card h-100 p-3.5 d-flex flex-column justify-content-between border shadow-sm rounded-3">
|
||||
<div>
|
||||
<% if (s.foto_url) { %>
|
||||
<div class="mb-3 rounded overflow-hidden border shadow-sm position-relative" style="height: 140px; background-color: #f8fafc;">
|
||||
<a href="<%= s.foto_url %>" target="_blank" title="Ver foto ampliada">
|
||||
<img src="<%= s.foto_url %>" alt="<%= s.nombre %>" style="width: 100%; height: 100%; object-fit: cover;">
|
||||
</a>
|
||||
</div>
|
||||
<% } %>
|
||||
<div class="d-flex align-items-center justify-content-between mb-2">
|
||||
<span class="badge bg-dark text-white font-monospace" style="font-size: 0.7rem;">
|
||||
<%= s.codigo || 'KIT-' + s.id %>
|
||||
@@ -171,8 +178,12 @@
|
||||
<ul class="list-unstyled mb-0 small" style="font-size: 0.78rem;">
|
||||
<% s.herramientas.forEach(h => { %>
|
||||
<li class="d-flex align-items-center justify-content-between py-1 border-bottom border-light">
|
||||
<div class="text-truncate me-2">
|
||||
<i class="fas fa-check text-success me-1.5" style="font-size: 0.7rem;"></i>
|
||||
<div class="text-truncate me-2 d-flex align-items-center gap-1.5">
|
||||
<% if (h.foto_url) { %>
|
||||
<img src="<%= h.foto_url %>" alt="Foto" class="rounded flex-shrink-0" style="width: 22px; height: 22px; object-fit: cover;">
|
||||
<% } else { %>
|
||||
<i class="fas fa-check text-success" style="font-size: 0.7rem;"></i>
|
||||
<% } %>
|
||||
<strong><%= h.nombre %></strong>
|
||||
<% if (h.marca) { %><span class="text-muted">(<%= h.marca %>)</span><% } %>
|
||||
</div>
|
||||
@@ -211,7 +222,7 @@
|
||||
<div class="modal fade" id="modalEditarSet<%= s.id %>" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content rounded-3 border-0 shadow">
|
||||
<form action="/admin/herramientas/sets/edit/<%= s.id %>" method="POST">
|
||||
<form action="/admin/herramientas/sets/edit/<%= s.id %>" method="POST" enctype="multipart/form-data">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title fw-bold">Editar Kit: <%= s.nombre %></h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
@@ -247,6 +258,16 @@
|
||||
<label class="form-label small fw-bold">Descripción / Alcance</label>
|
||||
<textarea name="descripcion" class="form-control" rows="2"><%= s.descripcion || '' %></textarea>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label small fw-bold"><i class="fas fa-camera text-primary me-1"></i> Fotografía del Set / Maletín</label>
|
||||
<% if (s.foto_url) { %>
|
||||
<div class="d-flex align-items-center gap-2 mb-2 p-2 border rounded bg-light">
|
||||
<img src="<%= s.foto_url %>" alt="Foto" class="rounded border" style="width: 50px; height: 50px; object-fit: cover;">
|
||||
<span class="small text-muted">Fotografía actual del kit registrada. Selecciona una nueva imagen para reemplazarla.</span>
|
||||
</div>
|
||||
<% } %>
|
||||
<input type="file" name="foto" accept="image/*" class="form-control">
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label small fw-bold mb-1">Seleccionar Herramientas del Inventario</label>
|
||||
<div class="border rounded p-2.5" style="max-height: 200px; overflow-y: auto;">
|
||||
@@ -277,7 +298,7 @@
|
||||
<div class="modal fade" id="modalAsignarDirecto<%= s.id %>" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content rounded-3 border-0 shadow">
|
||||
<form action="/admin/herramientas/asignar" method="POST">
|
||||
<form action="/admin/herramientas/asignar" method="POST" enctype="multipart/form-data">
|
||||
<input type="hidden" name="set_id" value="<%= s.id %>">
|
||||
<div class="modal-header bg-primary text-white">
|
||||
<h5 class="modal-title fw-bold">Asignar Kit: <%= s.nombre %></h5>
|
||||
@@ -304,6 +325,11 @@
|
||||
<label class="form-label small fw-bold">Observaciones de Entrega</label>
|
||||
<textarea name="observaciones_entrega" class="form-control" rows="2" placeholder="Ej: Entregado completo con estuche y cargadores en buen estado"></textarea>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small fw-bold"><i class="fas fa-camera text-primary me-1"></i> Foto de Evidencia / Entrega (Opcional)</label>
|
||||
<input type="file" name="foto_entrega" accept="image/*" class="form-control">
|
||||
<small class="text-muted" style="font-size: 0.72rem;">Respaldo fotográfico del estado del kit entregado en custodia.</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-light border" data-bs-dismiss="modal">Cancelar</button>
|
||||
@@ -347,8 +373,21 @@
|
||||
<tr>
|
||||
<td class="ps-3 font-monospace fw-bold text-dark"><%= h.codigo || 'HERR-' + h.id %></td>
|
||||
<td>
|
||||
<strong class="text-dark"><%= h.nombre %></strong>
|
||||
<% if (h.notas) { %><div class="small text-muted text-truncate" style="max-width: 250px;"><%= h.notas %></div><% } %>
|
||||
<div class="d-flex align-items-center gap-2.5">
|
||||
<% if (h.foto_url) { %>
|
||||
<a href="<%= h.foto_url %>" target="_blank" class="flex-shrink-0" title="Ver foto ampliada">
|
||||
<img src="<%= h.foto_url %>" alt="<%= h.nombre %>" class="rounded border shadow-sm" style="width: 42px; height: 42px; object-fit: cover;">
|
||||
</a>
|
||||
<% } else { %>
|
||||
<div class="icon-circle bg-light text-muted border flex-shrink-0" style="width: 42px; height: 42px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 0.95rem;">
|
||||
<i class="fas fa-tools"></i>
|
||||
</div>
|
||||
<% } %>
|
||||
<div>
|
||||
<strong class="text-dark"><%= h.nombre %></strong>
|
||||
<% if (h.notas) { %><div class="small text-muted text-truncate" style="max-width: 250px;"><%= h.notas %></div><% } %>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-light text-dark border"><%= h.categoria %></span>
|
||||
@@ -387,7 +426,7 @@
|
||||
<div class="modal fade" id="modalEditarHerramienta<%= h.id %>" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content rounded-3 border-0 shadow">
|
||||
<form action="/admin/herramientas/edit/<%= h.id %>" method="POST">
|
||||
<form action="/admin/herramientas/edit/<%= h.id %>" method="POST" enctype="multipart/form-data">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title fw-bold">Editar Herramienta: <%= h.nombre %></h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
@@ -443,6 +482,16 @@
|
||||
<label class="form-label small fw-bold">Notas Adicionales</label>
|
||||
<textarea name="notas" class="form-control" rows="2"><%= h.notas || '' %></textarea>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label small fw-bold"><i class="fas fa-camera text-primary me-1"></i> Fotografía del Instrumento / Placa</label>
|
||||
<% if (h.foto_url) { %>
|
||||
<div class="d-flex align-items-center gap-2 mb-2 p-2 border rounded bg-light">
|
||||
<img src="<%= h.foto_url %>" alt="Foto" class="rounded border" style="width: 50px; height: 50px; object-fit: cover;">
|
||||
<span class="small text-muted">Fotografía actual registrada. Selecciona una nueva imagen si deseas actualizarla.</span>
|
||||
</div>
|
||||
<% } %>
|
||||
<input type="file" name="foto" accept="image/*" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
@@ -474,6 +523,7 @@
|
||||
<th>Modalidad</th>
|
||||
<th>Fecha Asignación</th>
|
||||
<th>Contexto / Visita</th>
|
||||
<th>Evidencia Fotográfica</th>
|
||||
<th>Estado</th>
|
||||
<th class="text-end pe-3">Acciones</th>
|
||||
</tr>
|
||||
@@ -481,7 +531,7 @@
|
||||
<tbody>
|
||||
<% if (asignaciones.length === 0) { %>
|
||||
<tr>
|
||||
<td colspan="7" class="text-center py-4 text-muted">No hay asignaciones registradas actualmente.</td>
|
||||
<td colspan="8" class="text-center py-4 text-muted">No hay asignaciones registradas actualmente.</td>
|
||||
</tr>
|
||||
<% } %>
|
||||
|
||||
@@ -523,6 +573,23 @@
|
||||
<span class="text-muted small"><%= a.observaciones_entrega || 'Sin observaciones' %></span>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex flex-column gap-1">
|
||||
<% if (a.foto_entrega_url) { %>
|
||||
<a href="<%= a.foto_entrega_url %>" target="_blank" class="badge bg-primary-subtle text-primary border border-primary-subtle text-decoration-none d-inline-flex align-items-center gap-1" style="font-size: 0.7rem;">
|
||||
<i class="fas fa-camera"></i> <span>Foto Entrega</span>
|
||||
</a>
|
||||
<% } %>
|
||||
<% if (a.foto_devolucion_url) { %>
|
||||
<a href="<%= a.foto_devolucion_url %>" target="_blank" class="badge bg-success-subtle text-success border border-success-subtle text-decoration-none d-inline-flex align-items-center gap-1" style="font-size: 0.7rem;">
|
||||
<i class="fas fa-camera"></i> <span>Foto Devolución</span>
|
||||
</a>
|
||||
<% } %>
|
||||
<% if (!a.foto_entrega_url && !a.foto_devolucion_url) { %>
|
||||
<span class="text-muted small" style="font-size: 0.72rem;">Sin fotos</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<% if (a.estado === 'asignado') { %>
|
||||
<span class="badge bg-success"><i class="fas fa-user-check me-1"></i> En Custodia</span>
|
||||
@@ -551,7 +618,7 @@
|
||||
<div class="modal fade" id="modalDevolver<%= a.id %>" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content rounded-3 border-0 shadow">
|
||||
<form action="/admin/herramientas/devolver/<%= a.id %>" method="POST">
|
||||
<form action="/admin/herramientas/devolver/<%= a.id %>" method="POST" enctype="multipart/form-data">
|
||||
<div class="modal-header bg-success text-white">
|
||||
<h5 class="modal-title fw-bold">Registrar Devolución a Bodega</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
@@ -571,6 +638,11 @@
|
||||
<label class="form-label small fw-bold">Observaciones de Devolución</label>
|
||||
<textarea name="observaciones_devolucion" class="form-control" rows="2" placeholder="Ej: Kit revisado e ingresado completo al estante A1 sin novedades"></textarea>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small fw-bold"><i class="fas fa-camera text-success me-1"></i> Foto de Evidencia de Retorno (Opcional)</label>
|
||||
<input type="file" name="foto_devolucion" accept="image/*" class="form-control">
|
||||
<small class="text-muted" style="font-size: 0.72rem;">Constancia fotográfica del estado físico al reingreso en bodega.</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-light border" data-bs-dismiss="modal">Cancelar</button>
|
||||
@@ -596,7 +668,7 @@
|
||||
<div class="modal fade" id="modalNuevaHerramienta" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content rounded-3 border-0 shadow">
|
||||
<form action="/admin/herramientas/create" method="POST">
|
||||
<form action="/admin/herramientas/create" method="POST" enctype="multipart/form-data">
|
||||
<div class="modal-header bg-primary text-white">
|
||||
<h5 class="modal-title fw-bold"><i class="fas fa-plus-circle me-1"></i> Registrar Nueva Herramienta / Instrumento</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
@@ -651,6 +723,11 @@
|
||||
<label class="form-label small fw-bold">Observaciones / Especificaciones</label>
|
||||
<textarea name="notas" class="form-control" rows="2" placeholder="Detalles de calibración, accesorios incluidos o precauciones"></textarea>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label small fw-bold"><i class="fas fa-camera text-primary me-1"></i> Fotografía del Instrumento / Placa (Opcional)</label>
|
||||
<input type="file" name="foto" accept="image/*" class="form-control">
|
||||
<small class="text-muted" style="font-size: 0.72rem;">Sube una foto del equipo o su número de serie para reconocimiento visual en bodega y campo (JPG, PNG o WEBP).</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
@@ -666,7 +743,7 @@
|
||||
<div class="modal fade" id="modalNuevoSet" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content rounded-3 border-0 shadow">
|
||||
<form action="/admin/herramientas/sets/create" method="POST">
|
||||
<form action="/admin/herramientas/sets/create" method="POST" enctype="multipart/form-data">
|
||||
<div class="modal-header bg-warning text-dark">
|
||||
<h5 class="modal-title fw-bold"><i class="fas fa-layer-group me-1"></i> Crear Set / Kit de Herramientas</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
@@ -695,6 +772,11 @@
|
||||
<label class="form-label small fw-bold">Descripción del Kit</label>
|
||||
<input type="text" name="descripcion" class="form-control" placeholder="Ej: Kit completo para instalación y certificación en campo">
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label small fw-bold"><i class="fas fa-camera text-warning me-1"></i> Fotografía del Set / Maletín (Opcional)</label>
|
||||
<input type="file" name="foto" accept="image/*" class="form-control">
|
||||
<small class="text-muted" style="font-size: 0.72rem;">Foto general del kit o maletín con sus componentes organizados.</small>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label small fw-bold mb-1">Seleccionar Herramientas a Integrar en este Set</label>
|
||||
<div class="border rounded p-2.5 bg-light" style="max-height: 220px; overflow-y: auto;">
|
||||
@@ -705,7 +787,10 @@
|
||||
<div class="form-check py-1 border-bottom border-light">
|
||||
<input class="form-check-input" type="checkbox" name="herramientas_ids" value="<%= h.id %>" id="checkNewSet_<%= h.id %>">
|
||||
<label class="form-check-label small d-flex align-items-center justify-content-between" for="checkNewSet_<%= h.id %>">
|
||||
<span>
|
||||
<span class="d-flex align-items-center gap-1.5">
|
||||
<% if (h.foto_url) { %>
|
||||
<img src="<%= h.foto_url %>" alt="Foto" class="rounded" style="width: 22px; height: 22px; object-fit: cover;">
|
||||
<% } %>
|
||||
<strong><%= h.nombre %></strong>
|
||||
<% if (h.marca) { %><span class="text-muted">(<%= h.marca %>)</span><% } %>
|
||||
</span>
|
||||
@@ -733,7 +818,7 @@
|
||||
<div class="modal fade" id="modalAsignar" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content rounded-3 border-0 shadow">
|
||||
<form action="/admin/herramientas/asignar" method="POST">
|
||||
<form action="/admin/herramientas/asignar" method="POST" enctype="multipart/form-data">
|
||||
<div class="modal-header bg-primary text-white">
|
||||
<h5 class="modal-title fw-bold"><i class="fas fa-user-tag me-1"></i> Asignar Set de Herramientas a Técnico</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
@@ -768,6 +853,11 @@
|
||||
<label class="form-label small fw-bold">Observaciones de Entrega</label>
|
||||
<textarea name="observaciones_entrega" class="form-control" rows="2" placeholder="Ej: Entregado maletín completo con precintos y cargadores"></textarea>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small fw-bold"><i class="fas fa-camera text-primary me-1"></i> Foto de Evidencia / Entrega (Opcional)</label>
|
||||
<input type="file" name="foto_entrega" accept="image/*" class="form-control">
|
||||
<small class="text-muted" style="font-size: 0.72rem;">Respaldo fotográfico del estado del kit entregado al técnico.</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-light border" data-bs-dismiss="modal">Cancelar</button>
|
||||
|
||||
Reference in New Issue
Block a user