actualizado 3-sept

This commit is contained in:
2026-09-03 19:40:44 +02:00
parent 89992823b4
commit 5d2912f789
4338 changed files with 350157 additions and 386 deletions
+327 -48
View File
@@ -25,6 +25,8 @@
{% endblock %}
{% block content %}
<div class="page-header">
<div class="page-eyebrow">Vehículos</div>
<div class="page-title">{{ 'Editar vehículo ' ~ vehiculo['m_oficial'] if vehiculo else 'Nuevo vehículo' }}</div>
@@ -55,11 +57,11 @@
</div>
<div class="form-group">
<label class="form-label" for="m_civil">Matrícula civil</label>
<input class="form-input" type="text" id="m_civil" name="m_civil"
<label class="form-label" for="m_reservada">Matrícula reservada</label>
<input class="form-input" type="text" id="m_reservada" name="m_reservada"
placeholder="Ej. 5678XYZ"
oninput="this.value = this.value.toUpperCase();"
value="{{ (vehiculo['m_civil'] or '') if vehiculo else request.form.get('m_civil', '') }}">
value="{{ (vehiculo['m_reservada'] or '') if vehiculo else request.form.get('m_reservada', '') }}">
</div>
<div class="form-group">
@@ -145,19 +147,6 @@
value="{{ (vehiculo['color'] or '') if vehiculo else request.form.get('color', '') }}">
</div>
<div class="form-group">
<label class="form-label" for="cilindrada">Cilindrada</label>
<input class="form-input" type="text" id="cilindrada" name="cilindrada"
placeholder="Ej. 1600cc"
value="{{ (vehiculo['cilindrada'] or '') if vehiculo else request.form.get('cilindrada', '') }}">
</div>
<div class="form-group">
<label class="form-label" for="potencia">Potencia (CV)</label>
<input class="form-input" type="number" id="potencia" name="potencia"
placeholder="Ej. 120"
value="{{ (vehiculo['potencia'] or '') if vehiculo else request.form.get('potencia', '') }}">
</div>
<div class="form-group">
<label class="form-label" for="combustible">Combustible</label>
@@ -166,13 +155,6 @@
value="{{ (vehiculo['combustible'] or '') if vehiculo else request.form.get('combustible', '') }}">
</div>
<div class="form-group">
<label class="form-label" for="neumaticos">Neumáticos</label>
<input class="form-input" type="text" id="neumaticos" name="neumaticos"
placeholder="Ej. 205/55 R16"
value="{{ (vehiculo['neumaticos'] or '') if vehiculo else request.form.get('neumaticos', '') }}">
</div>
<div class="form-group">
<label class="form-label" for="plazas">Plazas</label>
<input class="form-input" type="text" id="plazas" name="plazas"
@@ -180,27 +162,45 @@
value="{{ (vehiculo['plazas'] or '') if vehiculo else request.form.get('plazas', '') }}">
</div>
<div class="form-group" style="width: 280px;">
<label class="form-label"> </label>
<label style="margin-top:22px;display:flex;align-items:center;gap:10px;cursor:pointer;
padding:10px 14px;background:var(--bg);border:1px solid var(--border);
border-radius:8px;transition:border-color .15s;"
onmouseover="this.style.borderColor='var(--accent)'"
onmouseout="this.style.borderColor='var(--border)'">
<input type="checkbox" name="lanzadestellos" value="1"
{% if vehiculo and vehiculo['lanzadestellos'] == 1 %}checked{% endif %}
style="width:16px;height:16px;accent-color:var(--accent);cursor:pointer;">
<span style="font-size:13px;color:var(--text)">Lanzadestellos</span>
<span style="font-size:11px;color:var(--muted);margin-left:4px;">
<div style="display:flex; align-items:center; gap:12px;">
({{ '✓ Con lanzadestellos' if vehiculo and vehiculo['lanzadestellos'] == 1 else '✗ Sin lanzadestellos' }})
</span>
<!-- Caja del checkbox -->
<div class="form-group">
<label class="form-label"></label>
<label style="width: 160px; margin-top:22px; display:flex; align-items:center;
gap:10px;
cursor:pointer;
padding:10px 14px;
background:var(--bg);
border:1px solid var(--border);
border-radius:8px;
transition:border-color .15s;"
onmouseover="this.style.borderColor='var(--accent)'"
onmouseout="this.style.borderColor='var(--border)'">
<input type="checkbox" name="lanzadestellos" id="lanzadestellos" value="1"
{% if vehiculo and vehiculo['lanzadestellos'] == 1 %}checked{% endif %}
style=" width:16px; height:16px; accent-color:var(--accent); cursor:pointer;">
Lanzadestellos
<span
style="font-size:11px;color:var(--muted);margin-left:4px;"
id="texto-lanzadestellos">
<!-- {% if vehiculo and vehiculo['lanzadestellos'] == 1 %}
✓ Con lanzadestellos
{% else %}
✗ Sin lanzadestellos
{% endif %} -->
</span>
</label>
</div>
</div>
<i id="icono-lanzadestellos" class="bi bi-brightness-alt-high-fill" style="font-size:2rem;color:cornflowerblue; {% if not (vehiculo and vehiculo['lanzadestellos'] == 1) %}display:none;{% endif %}"></i>
</div>
</div>
{% if vehiculo %}
{% set sit = vehiculo['situacion'] or '' %}
{% if sit | upper == 'BAJA' %}
@@ -329,12 +329,15 @@
</div>
{% endif %}
<div class="form-actions" style="margin-top:28px">
<button type="submit" class="btn btn-primary">
{{ '💾 GUARDAR CAMBIOS' if vehiculo else '✚ Registrar vehículo' }}
<button type="submit" class="btn btn-primary"> <i class="bi bi-floppy" style="font-size: 1rem;"></i>
{{ 'GUARDAR CAMBIOS' if vehiculo else '✚ Registrar vehículo' }}
</button>
{# Cancelar #}
{% if origen == 'viat' %}
<a href="/viat?q={{ q_viat }}" class="btn btn-ghost">Cancelar</a>
{% elif desde or hasta or q_itv %}
@@ -346,11 +349,7 @@
<!-- <div style="display:flex;justify-content:space-between;align-items:center;margin-top:12px;"> -->
{% if vehiculo %}
<button type="button" class="btn btn-ghost" onclick="imprimirFicha()" title="Imprimir ficha del vehículo">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="6 9 6 2 18 2 18 9"/>
<path d="M6 18H4a2 2 0 01-2-2v-5a2 2 0 012-2h16a2 2 0 012 2v5a2 2 0 01-2 2h-2"/>
<rect x="6" y="14" width="12" height="8"/>
</svg>
<i class="bi bi-printer"></i>
Ficha - Imprimir/PDF
</button>
{% endif %}
@@ -511,10 +510,175 @@
</div>
{% endif %}
{% if vehiculo %}
{# ── DOCUMENTOS PDF ── #}
<div class="section-title" style="margin-top:32px">Documentos PDF</div>
{# Listado de documentos existentes #}
{% if documentos %}
<div class="table-wrap" style="margin-bottom:16px;">
<table>
<thead>
<tr>
<th>Nombre</th>
<th>Fecha</th>
<th style="text-align:right">Acciones</th>
</tr>
</thead>
<tbody>
{% for doc in documentos %}
<tr>
<td>
<div style="display:flex;align-items:center;gap:8px;">
<i class="bi bi-file-earmark-text" style="color: salmon;"></i>
<strong style="font-size:13px;">{{ doc['nombre'] }}</strong>
</div>
</td>
<td style="font-size:12px;color:var(--muted);">{{ doc['fecha'] }}</td>
<td style="text-align:right;">
<div style="display:flex;gap:6px;justify-content:flex-end;">
<a href="{{ url_for('documentos_ver', doc_id=doc['id']) }}"
target="_blank" class="btn btn-ghost btn-sm" title="Ver">
<i class="bi bi-eye"></i>
Ver
</a>
<a href="{{ url_for('documentos_descargar', doc_id=doc['id']) }}"
class="btn btn-ghost btn-sm" title="Descargar">
<i class="bi bi-download"></i>
Descargar
</a>
<form method="POST"
action="{{ url_for('documentos_eliminar', doc_id=doc['id']) }}">
<input type="hidden" name="vid" value="{{ vehiculo['id'] }}">
<input type="hidden" name="_q" value="{{ q|default('') }}">
<input type="hidden" name="_incl_bajas" value="{{ incl_bajas|default('0') }}">
<button type="button" class="btn btn-danger btn-sm"
onclick="if(confirm('¿Eliminar documento «{{ doc['nombre'] }}»?')) this.closest('form').submit()">
Eliminar
</button>
</form>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<p style="color:var(--muted);font-size:13px;margin-bottom:16px;">
No hay documentos adjuntos para este vehículo.
</p>
{% endif %}
{# Formulario subir nuevo documento #}
<div style="background:var(--bg);border:1px solid var(--border);
border-radius:10px;padding:20px;">
<p style="font-size:11px;font-weight:600;letter-spacing:.7px;
text-transform:uppercase;color:var(--muted);margin-bottom:14px;">
Añadir documento <5Mb
</p>
<form method="POST"
action="{{ url_for('documentos_upload', id=vehiculo['id']) }}"
enctype="multipart/form-data">
<input type="hidden" name="_q" value="{{ q|default('') }}">
<input type="hidden" name="_incl_bajas" value="{{ incl_bajas|default('0') }}">
<input type="hidden" name="_desde" value="{{ desde|default('') }}">
<input type="hidden" name="_hasta" value="{{ hasta|default('') }}">
<input type="hidden" name="_q_itv" value="{{ q_itv|default('') }}">
<input type="hidden" name="_origen" value="{{ origen|default('') }}">
<input type="hidden" name="_q_viat" value="{{ q_viat|default('') }}">
<div class="form-grid" style="margin-bottom:12px;">
<div class="form-group" style="margin-bottom:0; width: 300px">
<label class="form-label">Nombre del documento</label>
<input class="form-input" style="background-color: white;" type="text" name="nombre_doc"
placeholder="Ej. Permiso circulación, Seguro, etc…">
</div>
<div class="form-group" style="margin-bottom:0;margin-left: 80px;" >
<label class="form-label">Archivo PDF</label>
<input class="form-control" type="file" name="pdf" id="pdfInput" accept=".pdf"
onchange="mostrarArchivo(this)"
style="font-size:13px;color:var(--text);padding:8px 0;">
</div>
</div>
<!-- style="font-size:13px;color:var(--text);padding:8px 0;" -->
<div id="pdfInfo" style="display:none;margin-bottom:12px;font-size:12px;
color:var(--accent);padding:8px 12px;
background:rgba(92,110,248,.08);border-radius:6px;">
</div>
<button type="submit" id="btnSubir" class="btn btn-primary btn-sm"
style="display:none;">
<i class="bi bi-upload"></i>
Subir documento
</button>
</form>
</div>
{% endif %}
</div> {# ← cierre de form-card #}
<script>
function mostrarArchivo(input) {
var info = document.getElementById('pdfInfo');
var btnSubir = document.getElementById('btnSubir');
if (input.files && input.files[0]) {
var f = input.files[0];
var size = (f.size / 1024).toFixed(1) + ' KB';
info.textContent = '📄 ' + f.name + ' (' + size + ')';
info.style.display = 'block';
btnSubir.style.display = 'inline-flex';
}
}
// mostrar archivo solo unico documento ficha tecnica.pdf
// function mostrarArchivo(input) {
// var nombre = document.getElementById('pdfNombre');
// var btnSubir = document.getElementById('btnSubir');
// if (input.files && input.files[0]) {
// nombre.textContent = '📄 ' + input.files[0].name;
// nombre.style.display = 'block';
// if (btnSubir) btnSubir.style.display = 'inline-flex';
// }
// }
function handleDrop(e) {
e.preventDefault();
document.getElementById('dropZone').style.borderColor = 'var(--border)';
var files = e.dataTransfer.files;
if (files.length && files[0].type === 'application/pdf') {
var input = document.getElementById('pdfInput');
input.files = files;
mostrarArchivo(input);
} else {
alert('Solo se permiten archivos PDF.');
}
}
</script>
<script>
const checkbox = document.getElementById('lanzadestellos');
const icono = document.getElementById('icono-lanzadestellos');
const texto = document.getElementById('texto-lanzadestellos');
checkbox.addEventListener('change', function () {
if (this.checked) {
icono.style.display = 'inline';
// texto.textContent = '✓ Con lanzadestellos';
} else {
icono.style.display = 'none';
// texto.textContent = '✗ Sin lanzadestellos';
}
});
</script>
<script>
@@ -524,6 +688,7 @@
}
}
function formatFecha(f) {
if (!f) return '';
// Si ya está en formato DD-MM-YYYY lo devuelve tal cual
@@ -613,7 +778,7 @@ function imprimirFicha() {
var v = {
id: '{{ vehiculo["id"] }}',
m_oficial: '{{ vehiculo["m_oficial"] or "" }}',
m_civil: '{{ vehiculo["m_civil"] or "" }}',
m_reservada: '{{ vehiculo["m_reservada"] or "" }}',
m_propia: '{{ vehiculo["m_propìa"] or "" }}',
denominacion: '{{ vehiculo["denominacion"] or "" }}',
marca: '{{ vehiculo["marca"] or "" }}',
@@ -740,7 +905,7 @@ function imprimirFicha() {
<div class="section-title">Identificación</div>
<table class="data-table">
${fila('M. oficial', v.m_oficial)}
${fila('M. civil', v.m_civil)}
${fila('M. reservada', v.m_reservada)}
${fila('M. propia', v.m_propia)}
${fila('VIN', v.VIN)}
${fila('Denominación', v.denominacion)}
@@ -803,3 +968,117 @@ function imprimirFicha() {
{% endblock %}
<!-- OPCION CARGAR SOLO PDF FICHA TECNICA -->
<!-- {% if vehiculo %}
{# ── DOCUMENTO PDF ── #}
<div class="section-title" style="margin-top:32px;">Ficha técnica PDF</div>
<div style="background:var(--surface);border:1px solid var(--border);
border-radius:var(--radius);padding:24px;margin-bottom:20px;">
{% if vehiculo['pdf'] %}
{# PDF existente #}
<div style="display:flex;align-items:center;justify-content:space-between;
flex-wrap:wrap;gap:12px;">
<div style="display:flex;align-items:center;gap:12px;">
<i class="bi bi-file-earmark-text" style="font-size: 2rem; color: salmon;"></i>
<div>
<div style="font-size:13px;font-weight:600;color:var(--text)">
{{ vehiculo['pdf'] }}
</div>
<div style="font-size:11px;color:var(--muted);margin-top:2px;">
Documento adjunto
</div>
</div>
</div>
<div style="display:flex;gap:8px;">
<a href="{{ url_for('vehiculos_pdf', id=vehiculo['id']) }}"
target="_blank" class="btn btn-ghost btn-sm">
<i class="bi bi-eye"></i>
Ver PDF
</a>
<a href="{{ url_for('vehiculos_pdf', id=vehiculo['id']) }}"
download class="btn btn-ghost btn-sm">
<i class="bi bi-download"></i>
Descargar
</a>
<form method="POST"
action="{{ url_for('vehiculos_pdf_eliminar', id=vehiculo['id']) }}">
<input type="hidden" name="_q" value="{{ q|default('') }}">
<input type="hidden" name="_incl_bajas" value="{{ incl_bajas|default('0') }}">
<button type="button" class="btn btn-danger btn-sm"
onclick="if(confirm('¿Eliminar el documento PDF?')) this.closest('form').submit()">
Eliminar PDF
</button>
</form>
</div>
</div>
{# Reemplazar PDF existente #}
<div style="margin-top:16px;padding-top:16px;border-top:1px solid var(--border);">
<p style="font-size:11px;color:var(--muted);margin-bottom:10px;">
Reemplazar documento actual:
</p>
<form method="POST"
action="{{ url_for('vehiculos_upload', id=vehiculo['id']) }}"
enctype="multipart/form-data"
style="display:flex;gap:10px;align-items:center;flex-wrap:wrap;">
<input type="hidden" name="_q" value="{{ q|default('') }}">
<input type="hidden" name="_incl_bajas" value="{{ incl_bajas|default('0') }}">
<input type="hidden" name="_desde" value="{{ desde|default('') }}">
<input type="hidden" name="_hasta" value="{{ hasta|default('') }}">
<input type="hidden" name="_q_itv" value="{{ q_itv|default('') }}">
<input type="hidden" name="_origen" value="{{ origen|default('') }}">
<input type="hidden" name="_q_viat" value="{{ q_viat|default('') }}">
<input type="file" name="pdf" accept=".pdf"
style="font-size:13px;color:var(--text);">
<button type="submit" class="btn btn-ghost btn-sm">
<i class="bi bi-upload"></i>
Reemplazar
</button>
</form>
</div>
{% else %}
{# Sin PDF - formulario de subida #}
<form method="POST"
action="{{ url_for('vehiculos_upload', id=vehiculo['id']) }}"
enctype="multipart/form-data">
<input type="hidden" name="_q" value="{{ q|default('') }}">
<input type="hidden" name="_incl_bajas" value="{{ incl_bajas|default('0') }}">
<input type="hidden" name="_desde" value="{{ desde|default('') }}">
<input type="hidden" name="_hasta" value="{{ hasta|default('') }}">
<input type="hidden" name="_q_itv" value="{{ q_itv|default('') }}">
<input type="hidden" name="_origen" value="{{ origen|default('') }}">
<input type="hidden" name="_q_viat" value="{{ q_viat|default('') }}">
<div style="border:2px dashed var(--border);border-radius:10px;padding:32px;
text-align:center;transition:border-color .2s;"
id="dropZone"
ondragover="event.preventDefault();this.style.borderColor='var(--accent)'"
ondragleave="this.style.borderColor='var(--border)'"
ondrop="handleDrop(event)">
<i class="bi bi-file-earmark-arrow-down" style="font-size: 2rem; color: gray;"></i>
<p style="font-size:13px;color:var(--muted);margin-bottom:12px;">
Arrastra un PDF aquí o pulsa para seleccionar
</p>
<input type="file" name="pdf" id="pdfInput" accept=".pdf"
style="display:none;" onchange="mostrarArchivo(this)">
<label for="pdfInput" class="btn btn-ghost" style="cursor:pointer;">
Seleccionar PDF
</label>
<p id="pdfNombre" style="margin-top:10px;font-size:12px;color:var(--accent);display:none;"></p>
</div>
<button type="submit" id="btnSubir" class="btn btn-primary"
style="margin-top:14px;display:none;">
<i class="bi bi-upload"></i>
Subir PDF
</button>
</form>
{% endif %}
</div>
{% endif %} -->