correcciones finales
This commit is contained in:
Vendored
BIN
Binary file not shown.
@@ -16,7 +16,8 @@ app.secret_key = 'clave-secreta-navbar-app'
|
|||||||
# Límite máximo de subida: 5 MiB
|
# Límite máximo de subida: 5 MiB
|
||||||
# app.config['MAX_CONTENT_LENGTH'] = 5 * 1024 * 1024
|
# app.config['MAX_CONTENT_LENGTH'] = 5 * 1024 * 1024
|
||||||
|
|
||||||
DATABASE = 'database/pyfleet.db'
|
# DATABASE = 'database/pyfleet.db'
|
||||||
|
DATABASE = 'database/auto.db'
|
||||||
|
|
||||||
PASSWORD_HASH = generate_password_hash('123')
|
PASSWORD_HASH = generate_password_hash('123')
|
||||||
|
|
||||||
@@ -236,7 +237,7 @@ def vehiculos_list():
|
|||||||
NORM(modelo) LIKE ? OR
|
NORM(modelo) LIKE ? OR
|
||||||
NORM(poblacion) LIKE ? OR
|
NORM(poblacion) LIKE ? OR
|
||||||
NORM(unidad) LIKE ? OR
|
NORM(unidad) LIKE ? OR
|
||||||
NORM(denominacion) LIKE ? OR
|
NORM(tipo) LIKE ? OR
|
||||||
NORM(situacion) LIKE ?
|
NORM(situacion) LIKE ?
|
||||||
)''')
|
)''')
|
||||||
params.extend([like] * 9)
|
params.extend([like] * 9)
|
||||||
@@ -245,7 +246,7 @@ def vehiculos_list():
|
|||||||
|
|
||||||
rows = db.execute(
|
rows = db.execute(
|
||||||
f'''SELECT id, m_oficial, m_reservada, marca, modelo, poblacion, unidad,
|
f'''SELECT id, m_oficial, m_reservada, marca, modelo, poblacion, unidad,
|
||||||
denominacion, tipo, situacion, lanzadestellos
|
tipo, situacion, lanzadestellos
|
||||||
FROM vehiculos
|
FROM vehiculos
|
||||||
WHERE {where} {filtro_bajas}
|
WHERE {where} {filtro_bajas}
|
||||||
ORDER BY id''',
|
ORDER BY id''',
|
||||||
@@ -409,12 +410,20 @@ def vehiculos_eliminar(id):
|
|||||||
return redirect(url_for('vehiculos_list', q=q) if q else url_for('vehiculos_list'))
|
return redirect(url_for('vehiculos_list', q=q) if q else url_for('vehiculos_list'))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/vehiculos/<int:vid>/historial/nuevo', methods=['POST'])
|
@app.route('/vehiculos/<int:vid>/historial/nuevo', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def historial_nuevo(vid):
|
def historial_nuevo(vid):
|
||||||
q = request.form.get('_q', '')
|
|
||||||
db = get_db()
|
db = get_db()
|
||||||
|
|
||||||
|
# Recoger TODOS los parámetros de navegación del POST
|
||||||
|
q = request.form.get('_q', '')
|
||||||
|
desde = request.form.get('_desde', '')
|
||||||
|
hasta = request.form.get('_hasta', '')
|
||||||
|
q_itv = request.form.get('_q_itv', '')
|
||||||
|
origen = request.form.get('_origen', '')
|
||||||
|
q_viat = request.form.get('_q_viat', '') # ← POST no GET
|
||||||
|
|
||||||
|
# Datos del historial
|
||||||
h_fecha = request.form.get('h_fecha') or None
|
h_fecha = request.form.get('h_fecha') or None
|
||||||
h_vehiculo_id = request.form.get('h_vehiculo_id', '').strip()
|
h_vehiculo_id = request.form.get('h_vehiculo_id', '').strip()
|
||||||
h_matricula = request.form.get('h_matricula', '').strip()
|
h_matricula = request.form.get('h_matricula', '').strip()
|
||||||
@@ -424,11 +433,7 @@ def historial_nuevo(vid):
|
|||||||
h_grupo = request.form.get('h_grupo', '').strip()
|
h_grupo = request.form.get('h_grupo', '').strip()
|
||||||
h_observaciones = request.form.get('h_observaciones', '').strip()
|
h_observaciones = request.form.get('h_observaciones', '').strip()
|
||||||
|
|
||||||
desde = request.form.get('_desde', '')
|
# Obtener nombre de población
|
||||||
hasta = request.form.get('_hasta', '')
|
|
||||||
q_itv = request.form.get('_q_itv', '')
|
|
||||||
|
|
||||||
# Obtener el NOMBRE de la población a partir del id
|
|
||||||
poblacion_nombre = ''
|
poblacion_nombre = ''
|
||||||
if h_poblacion_id:
|
if h_poblacion_id:
|
||||||
row = db.execute('SELECT poblacion FROM poblaciones WHERE id=?', (h_poblacion_id,)).fetchone()
|
row = db.execute('SELECT poblacion FROM poblaciones WHERE id=?', (h_poblacion_id,)).fetchone()
|
||||||
@@ -440,32 +445,47 @@ def historial_nuevo(vid):
|
|||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
''', (h_fecha, h_vehiculo_id, h_matricula, h_situacion, poblacion_nombre, h_unidad, h_grupo, h_observaciones))
|
''', (h_fecha, h_vehiculo_id, h_matricula, h_situacion, poblacion_nombre, h_unidad, h_grupo, h_observaciones))
|
||||||
|
|
||||||
# Si la unidad es BAJA, actualizar situacion del vehiculo
|
# Actualizar situacion del vehiculo
|
||||||
if h_situacion.upper() == 'BAJA':
|
if h_situacion.upper() == 'BAJA':
|
||||||
db.execute("UPDATE vehiculos SET situacion='BAJA' WHERE id=?", (vid,))
|
db.execute("UPDATE vehiculos SET situacion='BAJA', poblacion='', unidad='' WHERE id=?", (vid,))
|
||||||
else:
|
else:
|
||||||
db.execute("UPDATE vehiculos SET situacion=?, poblacion=?, unidad=?, grupo=? WHERE id=?", (h_situacion, poblacion_nombre, h_unidad, h_grupo, vid,))
|
db.execute(
|
||||||
|
"UPDATE vehiculos SET situacion=?, poblacion=?, unidad=?, grupo=? WHERE id=?",
|
||||||
|
(h_situacion, poblacion_nombre, h_unidad, h_grupo, vid)
|
||||||
|
)
|
||||||
|
|
||||||
db.commit()
|
db.commit()
|
||||||
flash('Entrada añadida al historial.', 'ok')
|
flash('Entrada añadida al historial.', 'ok')
|
||||||
|
|
||||||
# Volver a ITV si venía de ahí, si no al formulario del vehículo
|
# Redirect según origen
|
||||||
|
if origen == 'viat':
|
||||||
|
return redirect(f'/vehiculos/{vid}/editar?origen=viat&q_viat={q_viat}')
|
||||||
if desde or hasta or q_itv:
|
if desde or hasta or q_itv:
|
||||||
return redirect(f'/vehiculos/{vid}/editar?desde={desde}&hasta={hasta}&q_itv={q_itv}')
|
return redirect(f'/vehiculos/{vid}/editar?desde={desde}&hasta={hasta}&q_itv={q_itv}')
|
||||||
# return redirect(f'/vehiculos/{vid}/editar?q={q}')
|
|
||||||
return redirect(url_for('vehiculos_editar', id=vid, q=q))
|
return redirect(url_for('vehiculos_editar', id=vid, q=q))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/vehiculos/<int:vid>/historial/<int:hid>/eliminar', methods=['POST'])
|
@app.route('/vehiculos/<int:vid>/historial/<int:hid>/eliminar', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def historial_eliminar(vid, hid):
|
def historial_eliminar(vid, hid):
|
||||||
q = request.form.get('_q', '')
|
q = request.form.get('_q', '')
|
||||||
desde = request.form.get('_desde', '')
|
desde = request.form.get('_desde', '')
|
||||||
hasta = request.form.get('_hasta', '')
|
hasta = request.form.get('_hasta', '')
|
||||||
unidad_itv = request.form.get('_unidad_itv', '')
|
|
||||||
|
|
||||||
db = get_db()
|
db = get_db()
|
||||||
|
|
||||||
|
# Recoger parámetros de navegación
|
||||||
|
q = request.form.get('_q', '')
|
||||||
|
desde = request.form.get('_desde', '')
|
||||||
|
hasta = request.form.get('_hasta', '')
|
||||||
|
q_itv = request.form.get('_q_itv', '')
|
||||||
|
origen = request.form.get('_origen', '')
|
||||||
|
q_viat = request.form.get('_q_viat', '') # ← POST no GET
|
||||||
|
|
||||||
|
|
||||||
# 1. Comprobar que el vehículo existe
|
# 1. Comprobar que el vehículo existe
|
||||||
vehiculo = db.execute('''
|
vehiculo = db.execute('''
|
||||||
SELECT id, m_oficial
|
SELECT id, m_oficial
|
||||||
@@ -541,15 +561,15 @@ def historial_eliminar(vid, hid):
|
|||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
''', (vid,))
|
''', (vid,))
|
||||||
|
|
||||||
# 7. Confirmar cambios
|
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
flash('Entrada eliminada del historial.', 'ok')
|
flash('Entrada eliminada del historial.', 'ok')
|
||||||
|
|
||||||
# Volver a ITV si venía de ahí
|
# Redirect según origen
|
||||||
if desde or hasta or unidad_itv:
|
if origen == 'viat':
|
||||||
return redirect(f'/vehiculos/{vid}/editar?desde={desde}&hasta={hasta}&unidad_itv={unidad_itv}')
|
return redirect(f'/vehiculos/{vid}/editar?origen=viat&q_viat={q_viat}')
|
||||||
# return redirect(f'/vehiculos/{vid}/editar?q={q}')
|
if desde or hasta or q_itv:
|
||||||
|
return redirect(f'/vehiculos/{vid}/editar?desde={desde}&hasta={hasta}&q_itv={q_itv}')
|
||||||
|
|
||||||
url = f'/vehiculos/{vid}/editar'
|
url = f'/vehiculos/{vid}/editar'
|
||||||
if q:
|
if q:
|
||||||
@@ -625,7 +645,7 @@ def vehiculos_exportar():
|
|||||||
ws = wb.active
|
ws = wb.active
|
||||||
ws.title = 'Vehículos'
|
ws.title = 'Vehículos'
|
||||||
|
|
||||||
headers = ['M. Oficial', 'M. Civil', 'Marca', 'Modelo',
|
headers = ['M. Oficial', 'M. Reservada', 'Marca', 'Modelo',
|
||||||
'Poblacion', 'Unidad', 'Grupo', 'Denominación', 'Situación' ]
|
'Poblacion', 'Unidad', 'Grupo', 'Denominación', 'Situación' ]
|
||||||
header_fill = PatternFill('solid', fgColor='5C6EF8')
|
header_fill = PatternFill('solid', fgColor='5C6EF8')
|
||||||
header_font = Font(bold=True, color='FFFFFF', size=11)
|
header_font = Font(bold=True, color='FFFFFF', size=11)
|
||||||
@@ -684,7 +704,8 @@ def documentos_upload(id):
|
|||||||
q_itv = request.form.get('_q_itv', '')
|
q_itv = request.form.get('_q_itv', '')
|
||||||
origen = request.form.get('_origen', '')
|
origen = request.form.get('_origen', '')
|
||||||
q_viat = request.form.get('_q_viat', '')
|
q_viat = request.form.get('_q_viat', '')
|
||||||
nombre = request.form.get('nombre_doc', '').strip()
|
nombre = request.form.get('nombre_doc', '').strip() + '.pdf'
|
||||||
|
|
||||||
|
|
||||||
if 'pdf' not in request.files:
|
if 'pdf' not in request.files:
|
||||||
flash('No se seleccionó ningún archivo.', 'error')
|
flash('No se seleccionó ningún archivo.', 'error')
|
||||||
@@ -757,7 +778,7 @@ def documentos_descargar(doc_id):
|
|||||||
return send_from_directory(UPLOAD_FOLDER, doc['filename'],
|
return send_from_directory(UPLOAD_FOLDER, doc['filename'],
|
||||||
as_attachment=True,
|
as_attachment=True,
|
||||||
download_name=doc['nombre'])
|
download_name=doc['nombre'])
|
||||||
# download_name=doc['nombre'] + '.pdf')
|
# download_name=doc['nombre'] + '.pdf'
|
||||||
|
|
||||||
@app.route('/vehiculos/documentos/<int:doc_id>/eliminar', methods=['POST'])
|
@app.route('/vehiculos/documentos/<int:doc_id>/eliminar', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@@ -781,85 +802,6 @@ def documentos_eliminar(doc_id):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# @app.route('/vehiculos/<int:id>/upload', methods=['POST'])
|
|
||||||
# @login_required
|
|
||||||
# def vehiculos_upload(id):
|
|
||||||
# q = request.form.get('_q', '')
|
|
||||||
# incl_bajas = request.form.get('_incl_bajas', '0')
|
|
||||||
# desde = request.form.get('_desde', '')
|
|
||||||
# hasta = request.form.get('_hasta', '')
|
|
||||||
# q_itv = request.form.get('_q_itv', '')
|
|
||||||
# origen = request.form.get('_origen', '')
|
|
||||||
# q_viat = request.form.get('_q_viat', '')
|
|
||||||
|
|
||||||
# if 'pdf' not in request.files:
|
|
||||||
# flash('No se seleccionó ningún archivo.', 'error')
|
|
||||||
# return redirect(f'/vehiculos/{id}/editar?q={q}&incl_bajas={incl_bajas}')
|
|
||||||
|
|
||||||
# file = request.files['pdf']
|
|
||||||
# if file.filename == '':
|
|
||||||
# flash('No se seleccionó ningún archivo.', 'error')
|
|
||||||
# return redirect(f'/vehiculos/{id}/editar?q={q}&incl_bajas={incl_bajas}')
|
|
||||||
|
|
||||||
# if file and allowed_file(file.filename):
|
|
||||||
# # Guardar con nombre único basado en id del vehículo
|
|
||||||
# os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
|
||||||
# filename = f'ficha_tecnica_id_{id}.pdf'
|
|
||||||
# filepath = os.path.join(UPLOAD_FOLDER, filename)
|
|
||||||
# file.save(filepath)
|
|
||||||
|
|
||||||
# # Guardar referencia en BD
|
|
||||||
# db = get_db()
|
|
||||||
# db.execute('UPDATE vehiculos SET pdf=? WHERE id=?', (filename, id))
|
|
||||||
# db.commit()
|
|
||||||
# flash('Documento PDF subido correctamente.', 'ok')
|
|
||||||
# else:
|
|
||||||
# flash('Solo se permiten archivos PDF.', 'error')
|
|
||||||
|
|
||||||
# url = f'/vehiculos/{id}/editar?q={q}&incl_bajas={incl_bajas}'
|
|
||||||
# if origen == 'viat':
|
|
||||||
# url = f'/vehiculos/{id}/editar?origen=viat&q_viat={q_viat}'
|
|
||||||
# elif desde or hasta or q_itv:
|
|
||||||
# url = f'/vehiculos/{id}/editar?desde={desde}&hasta={hasta}&q_itv={q_itv}'
|
|
||||||
# return redirect(url)
|
|
||||||
|
|
||||||
|
|
||||||
# @app.route('/vehiculos/<int:id>/pdf')
|
|
||||||
# @login_required
|
|
||||||
# def vehiculos_pdf(id):
|
|
||||||
# from flask import send_from_directory
|
|
||||||
# db = get_db()
|
|
||||||
# vehiculo = db.execute('SELECT pdf FROM vehiculos WHERE id=?', (id,)).fetchone()
|
|
||||||
# if not vehiculo or not vehiculo['pdf']:
|
|
||||||
# flash('No hay documento PDF para este vehículo.', 'error')
|
|
||||||
# return redirect(f'/vehiculos/{id}/editar')
|
|
||||||
# return send_from_directory(UPLOAD_FOLDER, vehiculo['pdf'], as_attachment=False)
|
|
||||||
|
|
||||||
|
|
||||||
# @app.route('/vehiculos/<int:id>/pdf/eliminar', methods=['POST'])
|
|
||||||
# @login_required
|
|
||||||
# def vehiculos_pdf_eliminar(id):
|
|
||||||
# q = request.form.get('_q', '')
|
|
||||||
# incl_bajas = request.form.get('_incl_bajas', '0')
|
|
||||||
# db = get_db()
|
|
||||||
# vehiculo = db.execute('SELECT pdf FROM vehiculos WHERE id=?', (id,)).fetchone()
|
|
||||||
# if vehiculo and vehiculo['pdf']:
|
|
||||||
# filepath = os.path.join(UPLOAD_FOLDER, vehiculo['pdf'])
|
|
||||||
# if os.path.exists(filepath):
|
|
||||||
# os.remove(filepath)
|
|
||||||
# db.execute('UPDATE vehiculos SET pdf=NULL WHERE id=?', (id,))
|
|
||||||
# db.commit()
|
|
||||||
# flash('Documento PDF eliminado.', 'ok')
|
|
||||||
# return redirect(f'/vehiculos/{id}/editar?q={q}&incl_bajas={incl_bajas}')
|
|
||||||
|
|
||||||
|
|
||||||
# Ruta API que devuelve unidades según población
|
# Ruta API que devuelve unidades según población
|
||||||
@app.route('/api/unidades/<int:poblacion_id>')
|
@app.route('/api/unidades/<int:poblacion_id>')
|
||||||
@login_required
|
@login_required
|
||||||
@@ -978,7 +920,7 @@ def itv_exportar():
|
|||||||
ws = wb.active
|
ws = wb.active
|
||||||
ws.title = 'ITV'
|
ws.title = 'ITV'
|
||||||
|
|
||||||
headers = ['M. Oficial', 'M. Civil', 'Marca', 'Modelo',
|
headers = ['M. Oficial', 'M. Reservada', 'Marca', 'Modelo',
|
||||||
'Denominación', 'Tipo', 'Unidad', 'Población', 'Fecha ITV']
|
'Denominación', 'Tipo', 'Unidad', 'Población', 'Fecha ITV']
|
||||||
header_fill = PatternFill('solid', fgColor='5C6EF8')
|
header_fill = PatternFill('solid', fgColor='5C6EF8')
|
||||||
header_font = Font(bold=True, color='FFFFFF', size=11)
|
header_font = Font(bold=True, color='FFFFFF', size=11)
|
||||||
@@ -1432,7 +1374,7 @@ def viat_exportar():
|
|||||||
ws = wb.active
|
ws = wb.active
|
||||||
ws.title = 'Via-T'
|
ws.title = 'Via-T'
|
||||||
|
|
||||||
headers = ['Via-T', 'M. Oficial', 'M. Civil', 'Marca',
|
headers = ['Via-T', 'M. Oficial', 'M. Reservada', 'Marca',
|
||||||
'Modelo', 'Población', 'Unidad', 'Tipo']
|
'Modelo', 'Población', 'Unidad', 'Tipo']
|
||||||
header_fill = PatternFill('solid', fgColor='5C6EF8')
|
header_fill = PatternFill('solid', fgColor='5C6EF8')
|
||||||
header_font = Font(bold=True, color='FFFFFF', size=11)
|
header_font = Font(bold=True, color='FFFFFF', size=11)
|
||||||
|
|||||||
Executable
BIN
Binary file not shown.
Binary file not shown.
@@ -238,8 +238,14 @@ CREATE TABLE "unidades" (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Actualización vial
|
||||||
|
UPDATE vehiculos
|
||||||
|
SET viat = substr(
|
||||||
|
notas,
|
||||||
|
instr(lower(notas), 'viat '),
|
||||||
|
24
|
||||||
|
)
|
||||||
|
WHERE instr(lower(notas), 'viat ') > 0;
|
||||||
|
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
CONSULTAR TIPOS DE VEHICULO
|
CONSULTAR TIPOS DE VEHICULO
|
||||||
|
|||||||
Executable
+247
@@ -0,0 +1,247 @@
|
|||||||
|
DROP TABLE IF EXISTS ACCIDENTES;
|
||||||
|
DROP TABLE IF EXISTS "CAMBIOS DE ACEITE";
|
||||||
|
DROP TABLE IF EXISTS CONTRATO;
|
||||||
|
DROP TABLE IF EXISTS "DEFINICIÓN DE TIPOS";
|
||||||
|
DROP TABLE IF EXISTS Denominación;
|
||||||
|
DROP TABLE IF EXISTS "Errores de pegado";
|
||||||
|
DROP TABLE IF EXISTS "Estado Seguro";
|
||||||
|
DROP TABLE IF EXISTS FACTURAS;
|
||||||
|
DROP TABLE IF EXISTS FUNCIONARIOS;
|
||||||
|
DROP TABLE IF EXISTS "Grupo Asignado";
|
||||||
|
DROP TABLE IF EXISTS HERRAMIENTAS;
|
||||||
|
DROP TABLE IF EXISTS "Historico destino";
|
||||||
|
DROP TABLE IF EXISTS Hoja1;
|
||||||
|
DROP TABLE IF EXISTS ITV;
|
||||||
|
DROP TABLE IF EXISTS Incidencias;
|
||||||
|
DROP TABLE IF EXISTS KILOMETROS;
|
||||||
|
DROP TABLE IF EXISTS LIQUIDACION;
|
||||||
|
DROP TABLE IF EXISTS MAQUINARIA;
|
||||||
|
DROP TABLE IF EXISTS Marcas;
|
||||||
|
DROP TABLE IF EXISTS Matriculas;
|
||||||
|
DROP TABLE IF EXISTS Modelo;
|
||||||
|
DROP TABLE IF EXISTS Multas;
|
||||||
|
DROP TABLE IF EXISTS Neumaticos;
|
||||||
|
DROP TABLE IF EXISTS Piezas;
|
||||||
|
DROP TABLE IF EXISTS POBLACIONES;
|
||||||
|
DROP TABLE IF EXISTS PROVEEDORES;
|
||||||
|
DROP TABLE IF EXISTS Peticiones;
|
||||||
|
DROP TABLE IF EXISTS Plantilla;
|
||||||
|
DROP TABLE IF EXISTS RECIBO;
|
||||||
|
DROP TABLE IF EXISTS REPARACIONES;
|
||||||
|
DROP TABLE IF EXISTS REPUESTOS;
|
||||||
|
DROP TABLE IF EXISTS "Situación Vehículo";
|
||||||
|
DROP TABLE IF EXISTS "T_RESUMEN VEHICULOS COMISARIA PROVINCIAL";
|
||||||
|
DROP TABLE IF EXISTS "T_RESUMEN VEHICULOS COMISARIAS LOCALES";
|
||||||
|
DROP TABLE IF EXISTS Tipo;
|
||||||
|
DROP TABLE IF EXISTS Unidades;
|
||||||
|
DROP TABLE IF EXISTS VACACIONES;
|
||||||
|
DROP TABLE IF EXISTS "VEHICULOS 10-01-10";
|
||||||
|
DROP TABLE IF EXISTS "VEHICULOS 28-04-10";
|
||||||
|
DROP TABLE IF EXISTS VEHICULOS_PTE;
|
||||||
|
|
||||||
|
ALTER TABLE VEHICULOS RENAME TO "vehiculos_tmp";
|
||||||
|
ALTER TABLE "vehiculos_tmp" RENAME TO vehiculos;
|
||||||
|
|
||||||
|
ALTER TABLE vehiculos DROP COLUMN "Número de Identificación";
|
||||||
|
ALTER TABLE vehiculos DROP COLUMN "Nº Cilindros/Cilindrada";
|
||||||
|
ALTER TABLE vehiculos DROP COLUMN Potencia;
|
||||||
|
ALTER TABLE vehiculos DROP COLUMN "Medidas neumaticos";
|
||||||
|
ALTER TABLE vehiculos DROP COLUMN "Fecha Destino/Situación";
|
||||||
|
ALTER TABLE vehiculos DROP COLUMN Seguro;
|
||||||
|
ALTER TABLE vehiculos DROP COLUMN Denominación;
|
||||||
|
ALTER TABLE vehiculos DROP COLUMN Grupo;
|
||||||
|
ALTER TABLE vehiculos DROP COLUMN Foto_asignada;
|
||||||
|
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN "Matrícula Oficial (DGP)" TO m_oficial;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN "Nº ficha" TO legajo;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN "Matrícula Civil" TO m_reservada;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN PMM TO m_propia;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN Población TO poblacion;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN Marca TO marca;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN Modelo TO modelo;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN Tipo TO tipo;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN Color TO color;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN "Número de bastidor" TO VIN;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN "Fecha de Alta" TO f_alta;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN "Fecha de Baja" TO f_baja;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN "Situación veh" TO situacion;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN Kilometros TO km;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN "Kilometros a dia 1" TO km_1;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN "Tipo de Combustible" TO combustible;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN "Número de plazas" TO plazas;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN "Ultima ITV" TO itv_ultima;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN "Tipo ITV" TO itv;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN Departamento TO unidad;
|
||||||
|
ALTER TABLE vehiculos RENAME COLUMN "Número de Poliza" TO poliza;
|
||||||
|
|
||||||
|
ALTER TABLE vehiculos ADD COLUMN id INTEGER;
|
||||||
|
ALTER TABLE vehiculos ADD COLUMN lanzadestellos INTEGER;
|
||||||
|
ALTER TABLE vehiculos ADD COLUMN grupo TEXT;
|
||||||
|
ALTER TABLE vehiculos ADD COLUMN viat TEXT;
|
||||||
|
ALTER TABLE vehiculos ADD COLUMN int_operacion TEXT;
|
||||||
|
ALTER TABLE vehiculos ADD COLUMN int_grupo TEXT;
|
||||||
|
ALTER TABLE vehiculos ADD COLUMN int_juzgado TEXT;
|
||||||
|
ALTER TABLE vehiculos ADD COLUMN int_procedimiento TEXT;
|
||||||
|
ALTER TABLE vehiculos ADD COLUMN notas TEXT;
|
||||||
|
|
||||||
|
UPDATE vehiculos SET notas = TRIM(COALESCE(observaciones, '') || ' ' || COALESCE(historial, ''));
|
||||||
|
|
||||||
|
ALTER TABLE vehiculos DROP COLUMN observaciones;
|
||||||
|
ALTER TABLE vehiculos DROP COLUMN historial;
|
||||||
|
|
||||||
|
UPDATE vehiculos
|
||||||
|
SET lanzadestellos = 1
|
||||||
|
WHERE notas LIKE '%SAMCO%';
|
||||||
|
|
||||||
|
UPDATE vehiculos SET f_alta = substr(f_alta, 1, 10);
|
||||||
|
UPDATE vehiculos SET f_baja = substr(f_baja, 1, 10);
|
||||||
|
|
||||||
|
UPDATE vehiculos
|
||||||
|
SET situacion = CASE
|
||||||
|
WHEN f_baja IS NULL OR f_baja = '' THEN 'ACTIVO'
|
||||||
|
ELSE 'BAJA'
|
||||||
|
END;
|
||||||
|
|
||||||
|
UPDATE vehiculos
|
||||||
|
SET viat = substr(
|
||||||
|
notas,
|
||||||
|
instr(lower(notas), 'viat '),
|
||||||
|
24
|
||||||
|
)
|
||||||
|
WHERE instr(lower(notas), 'viat ') > 0;
|
||||||
|
|
||||||
|
|
||||||
|
UPDATE vehiculos SET unidad = 'BPEF' WHERE unidad = 'B.P.E. y F.';
|
||||||
|
UPDATE vehiculos SET unidad = 'BPI' WHERE unidad = 'B.P.I.';
|
||||||
|
UPDATE vehiculos SET unidad = 'BPPC' WHERE unidad = 'B.P.P.C.';
|
||||||
|
UPDATE vehiculos SET unidad = 'BPSC' WHERE unidad = 'B.P.S.C.';
|
||||||
|
UPDATE vehiculos SET unidad = 'BPSC' WHERE unidad = 'Seg. Ciudadana' AND poblacion = 'MALAGA';
|
||||||
|
UPDATE vehiculos SET unidad = 'BLSC' WHERE unidad = 'Seg. Ciudadana' AND poblacion != 'MALAGA';
|
||||||
|
UPDATE vehiculos SET unidad = 'BPSC' WHERE unidad = 'SEG. CIUDADANA';
|
||||||
|
UPDATE vehiculos SET unidad = 'BPSC' WHERE unidad = 'B.P.S.C. K';
|
||||||
|
UPDATE vehiculos SET unidad = 'DISTRITO CENTRO' WHERE unidad = 'DTO. CENTRO';
|
||||||
|
UPDATE vehiculos SET unidad = 'DISTRITO ESTE' WHERE unidad = 'DTO. ESTE';
|
||||||
|
UPDATE vehiculos SET unidad = 'DISTRITO NORTE' WHERE unidad = 'DTO. NORTE';
|
||||||
|
UPDATE vehiculos SET unidad = 'DISTRITO OESTE' WHERE unidad = 'DTO. OESTE';
|
||||||
|
UPDATE vehiculos SET unidad = 'UCOP - GOES' WHERE unidad = 'G.O.E.S.';
|
||||||
|
UPDATE vehiculos SET unidad = 'UDEF - IPLA' WHERE unidad = 'I.P.L.A.';
|
||||||
|
UPDATE vehiculos SET unidad = 'SECRETARIA GENERAL - NUCLEO RESERVA' WHERE unidad = 'NUCLEO DE RESERVA';
|
||||||
|
UPDATE vehiculos SET unidad = 'SECRETARIA GENERAL' WHERE unidad = 'SECRETARIA G.';
|
||||||
|
UPDATE vehiculos SET unidad = '' WHERE unidad = 'SUSTITUCION';
|
||||||
|
UPDATE vehiculos SET unidad = 'AUTOMOCION' WHERE unidad = 'TALLER AUTOMOCION';
|
||||||
|
UPDATE vehiculos SET unidad = 'UCOP - GABINETE TECNICO' WHERE unidad = 'U.C.O.P. - GABINETE TÉCNICO';
|
||||||
|
UPDATE vehiculos SET unidad = 'UCOP - GOTHAM' WHERE unidad = 'U.C.O.P. - GOTHAM';
|
||||||
|
UPDATE vehiculos SET unidad = 'UCOP - HELICOPTEROS' WHERE unidad = 'U.C.O.P. - HELICOPTEROS';
|
||||||
|
UPDATE vehiculos SET unidad = 'UCOP' WHERE unidad = 'U.C.O.P. - JEFES';
|
||||||
|
UPDATE vehiculos SET unidad = 'UCOP - OMEGA' WHERE unidad = 'U.C.O.P. - OMEGA';
|
||||||
|
UPDATE vehiculos SET unidad = 'UCOP - SISTEMAS ESPECIALES' WHERE unidad = 'U.C.O.P. - SISTEMAS';
|
||||||
|
UPDATE vehiculos SET unidad = 'UCOP - UVAO' WHERE unidad = 'U.C.O.P. - UVAO';
|
||||||
|
UPDATE vehiculos SET unidad = 'UDEF' WHERE unidad = 'U.D.E.F.';
|
||||||
|
UPDATE vehiculos SET unidad = 'BPPJ - UDEV ' WHERE unidad = 'U.D.E.V.' AND poblacion = 'MALAGA';
|
||||||
|
UPDATE vehiculos SET unidad = 'BLPJ - UDEV' WHERE unidad = 'U.D.E.V.' AND poblacion != 'MALAGA';
|
||||||
|
UPDATE vehiculos SET unidad = 'UIP' WHERE unidad = 'U.I.P.';
|
||||||
|
UPDATE vehiculos SET unidad = 'BPSC - UPR' WHERE unidad = 'U.P.R.' AND poblacion = 'MALAGA';
|
||||||
|
UPDATE vehiculos SET unidad = 'BLSC - UPR' WHERE unidad = 'U.P.R.' AND poblacion != 'MALAGA';
|
||||||
|
UPDATE vehiculos SET unidad = 'BPSC - UPR 1' WHERE unidad = 'U.P.R.-1';
|
||||||
|
UPDATE vehiculos SET unidad = 'BPSC - UPR 2' WHERE unidad = 'U.P.R.-2';
|
||||||
|
UPDATE vehiculos SET unidad = 'UDYCO' WHERE unidad = 'udyco - Costa del Sol';
|
||||||
|
UPDATE vehiculos SET unidad = 'BLSC' WHERE unidad = 'B.L.S.C.';
|
||||||
|
UPDATE vehiculos SET unidad = 'BLPJ' WHERE unidad = 'B.L.P.J.';
|
||||||
|
UPDATE vehiculos SET unidad = 'BLI' WHERE unidad = 'B.L.I.';
|
||||||
|
UPDATE vehiculos SET unidad = 'BLPC' WHERE unidad = 'B.L.P.C.';
|
||||||
|
UPDATE vehiculos SET unidad = 'BLEF' WHERE unidad = 'B.L.E. y F.';
|
||||||
|
UPDATE vehiculos SET unidad = 'UCOL' WHERE unidad = 'U.C.O.L.';
|
||||||
|
UPDATE vehiculos SET unidad = 'JEFATURA COMISARIA' WHERE unidad = 'JEFE COMISARÍA';
|
||||||
|
UPDATE vehiculos SET unidad = 'UDYCO' WHERE unidad = 'udyco - Costa del Sol' AND poblacion != 'MALAGA';
|
||||||
|
UPDATE vehiculos SET unidad = '' WHERE unidad = 'BAJA';
|
||||||
|
UPDATE vehiculos SET unidad = '' WHERE unidad = 'ENAJ. DIRECTA MARZO 2025 BAJA ASIA';
|
||||||
|
UPDATE vehiculos SET unidad = '' WHERE unidad = 'ENAJ. COCHES';
|
||||||
|
UPDATE vehiculos SET unidad = '' WHERE unidad = 'DESTRUIDO' OR unidad = 'DESTRUCCION';
|
||||||
|
UPDATE vehiculos SET unidad = '' WHERE unidad = 'BAJA EN ASIA' OR unidad = 'BAJA TEMPORAL' OR unidad = 'BANCO DE VEHCULOS' OR unidad = 'BAJA DEFINITIVA' OR unidad = 'BAJA ASIA Enaj. MOTOS' OR unidad = 'BAJA ASIA Enaj. COCHES';
|
||||||
|
UPDATE vehiculos SET unidad = '' WHERE unidad LIKE '%CURSO%';
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE documentos (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
vehiculo_id INTEGER NOT NULL REFERENCES vehiculos(id) ON DELETE CASCADE,
|
||||||
|
nombre TEXT,
|
||||||
|
filename TEXT NOT NULL,
|
||||||
|
fecha DATETIME DEFAULT (datetime('now','localtime'))
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE mensajes (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
texto TEXT NOT NULL,
|
||||||
|
autor TEXT,
|
||||||
|
fecha DATETIME DEFAULT (datetime('now','localtime'))
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
ALTER TABLE "Historial" RENAME TO "historial_tmp";
|
||||||
|
ALTER TABLE "historial_tmp" RENAME TO "historial";
|
||||||
|
|
||||||
|
ALTER TABLE historial RENAME COLUMN Matricula TO matricula;
|
||||||
|
ALTER TABLE historial RENAME COLUMN Unidad TO unidad;
|
||||||
|
ALTER TABLE historial RENAME COLUMN Cuando TO fecha;
|
||||||
|
ALTER TABLE historial RENAME COLUMN Observaciones TO observaciones;
|
||||||
|
ALTER TABLE historial ADD COLUMN id INTEGER;
|
||||||
|
ALTER TABLE historial ADD COLUMN vehiculo_id INTEGER;
|
||||||
|
ALTER TABLE historial ADD COLUMN situacion TEXT;
|
||||||
|
ALTER TABLE historial ADD COLUMN poblacion TEXT;
|
||||||
|
ALTER TABLE historial ADD COLUMN grupo TEXT;
|
||||||
|
|
||||||
|
UPDATE historial SET fecha = substr(fecha, 1, 10);
|
||||||
|
|
||||||
|
UPDATE vehiculos
|
||||||
|
SET
|
||||||
|
m_oficial = NULLIF(m_oficial, 'none'),
|
||||||
|
m_reservada = NULLIF(m_reservada, 'none'),
|
||||||
|
m_propia = NULLIF(m_propia, 'none'),
|
||||||
|
VIN = NULLIF(VIN, 'none'),
|
||||||
|
poliza = NULLIF(poliza, 'none'),
|
||||||
|
viat = NULLIF(viat, 'none'),
|
||||||
|
legajo = NULLIF(legajo, 'none'),
|
||||||
|
marca = NULLIF(marca, 'none'),
|
||||||
|
modelo = NULLIF(modelo, 'none'),
|
||||||
|
tipo = NULLIF(tipo, 'none'),
|
||||||
|
color = NULLIF(color, 'none'),
|
||||||
|
combustible = NULLIF(combustible, 'none'),
|
||||||
|
plazas = NULLIF(plazas, 'none'),
|
||||||
|
situacion = NULLIF(situacion, 'none'),
|
||||||
|
poblacion = NULLIF(poblacion, 'none'),
|
||||||
|
unidad = NULLIF(unidad, 'none'),
|
||||||
|
grupo = NULLIF(grupo, 'none'),
|
||||||
|
int_operacion = NULLIF(int_operacion, 'none'),
|
||||||
|
int_grupo = NULLIF(int_grupo, 'none'),
|
||||||
|
int_juzgado = NULLIF(int_juzgado, 'none'),
|
||||||
|
int_procedimiento = NULLIF(int_procedimiento, 'none'),
|
||||||
|
f_alta = NULLIF(f_alta, 'none'),
|
||||||
|
f_baja = NULLIF(f_baja, 'none'),
|
||||||
|
km = NULLIF(km, 'none'),
|
||||||
|
km_1 = NULLIF(km_1, 'none'),
|
||||||
|
itv_ultima = NULLIF(itv_ultima, 'none'),
|
||||||
|
itv = NULLIF(itv, 'none'),
|
||||||
|
notas = NULLIF(notas, 'none');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
————————————————————————
|
||||||
|
Después:
|
||||||
|
1- Poner id autoincremental en tabla vehículos
|
||||||
|
2. Poner id autoincremental en tabla historial
|
||||||
|
|
||||||
|
3- Hacer el update:
|
||||||
|
UPDATE historial
|
||||||
|
SET vehiculo_id = (
|
||||||
|
SELECT id
|
||||||
|
FROM vehiculos
|
||||||
|
WHERE vehiculos.m_oficial = historial.matricula
|
||||||
|
);
|
||||||
|
|
||||||
|
4- Ordenar los campos de las tablas, con este orden:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Executable
+4
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#currentColor" viewBox="0 0 16 16">
|
||||||
|
<path d="M4 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0m10 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0M6 8a1 1 0 0 0 0 2h4a1 1 0 1 0 0-2zM4.862 4.276 3.906 6.19a.51.51 0 0 0 .497.731c.91-.073 2.35-.17 3.597-.17s2.688.097 3.597.17a.51.51 0 0 0 .497-.731l-.956-1.913A.5.5 0 0 0 10.691 4H5.309a.5.5 0 0 0-.447.276"/>
|
||||||
|
<path d="M2.52 3.515A2.5 2.5 0 0 1 4.82 2h6.362c1 0 1.904.596 2.298 1.515l.792 1.848c.075.175.21.319.38.404.5.25.855.715.965 1.262l.335 1.679q.05.242.049.49v.413c0 .814-.39 1.543-1 1.997V13.5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-1.338c-1.292.048-2.745.088-4 .088s-2.708-.04-4-.088V13.5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-1.892c-.61-.454-1-1.183-1-1.997v-.413a2.5 2.5 0 0 1 .049-.49l.335-1.68c.11-.546.465-1.012.964-1.261a.8.8 0 0 0 .381-.404l.792-1.848ZM4.82 3a1.5 1.5 0 0 0-1.379.91l-.792 1.847a1.8 1.8 0 0 1-.853.904.8.8 0 0 0-.43.564L1.03 8.904a1.5 1.5 0 0 0-.03.294v.413c0 .796.62 1.448 1.408 1.484 1.555.07 3.786.155 5.592.155s4.037-.084 5.592-.155A1.48 1.48 0 0 0 15 9.611v-.413q0-.148-.03-.294l-.335-1.68a.8.8 0 0 0-.43-.563 1.8 1.8 0 0 1-.853-.904l-.792-1.848A1.5 1.5 0 0 0 11.18 3z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
Executable
+55
@@ -0,0 +1,55 @@
|
|||||||
|
id,tipo,denominacion
|
||||||
|
1,AUTOCAR 21 A 40 PAX,
|
||||||
|
2,AUTOCAR > 40 PAX,
|
||||||
|
3,FURGON,
|
||||||
|
4,"CAMION < 3,5 TM",
|
||||||
|
5,"CAMION > 3,5 TM",
|
||||||
|
6,CANIOB DE CABALLOS,
|
||||||
|
7,CELULAR,
|
||||||
|
8,CICLOMOTOR,
|
||||||
|
9,CTRL. MOVIL FRONTERA,
|
||||||
|
10,EMBARCACION,
|
||||||
|
11,ESTACIONES ITV,
|
||||||
|
12,FURGON APOLO,
|
||||||
|
13,FURGON EDEX,
|
||||||
|
14,FURGON G.CANINOS,
|
||||||
|
15,FURGON GOES,
|
||||||
|
16,FURGON MINI APOLO,
|
||||||
|
17,FURGON U.P.R.,
|
||||||
|
18,FURGON UNIPOL F-8,
|
||||||
|
19,FURGONETA COMBI,
|
||||||
|
20,FURGONETA DE CARGA,
|
||||||
|
21,FURGONETA DNI,
|
||||||
|
22,FURGONETA DNI RURAL,
|
||||||
|
23,FURGONETA IZ,
|
||||||
|
24,FURGONETA LABORATORIO DE DOCUMENTOS FALSOS,
|
||||||
|
25,FURGONETA MIXTA,
|
||||||
|
26,FURGONETA P.CIENTIFICA,
|
||||||
|
27,FURGONETA SUBSUELO,
|
||||||
|
28,GRUA,
|
||||||
|
29,GRUPO ELECTROGENO,
|
||||||
|
30,LANZA-AGUA,
|
||||||
|
31,MAXI-Z,
|
||||||
|
32,MICROBUS 10 A 20 PAX,
|
||||||
|
33,MOTOCICLETA TIPO K,
|
||||||
|
34,MOTOCICLETA TIPO Q,
|
||||||
|
35,MOTOCICLETA UNIFORMADA,
|
||||||
|
36,POLICIA TECN.ESPECIALIDAD,
|
||||||
|
37,PUESTO DE MANDO AVANZADO,
|
||||||
|
38,REMOLQUE <750 KG,
|
||||||
|
39,REMOLQUE >750 KG,
|
||||||
|
40,TANQUETA,
|
||||||
|
41,TODO CAMINO,
|
||||||
|
42,TODO TERRENO,
|
||||||
|
43,TRACTOR TIPO EINSA,
|
||||||
|
44,TRANSPORTE SANITARIO,
|
||||||
|
45,TRASLADO EXTRANJEROS,
|
||||||
|
46,TURISMO K,
|
||||||
|
47,TURISMO Q,
|
||||||
|
48,TURISMO Z,
|
||||||
|
49,TURISMO Z COORDINACION,
|
||||||
|
50,UNIDAD MOVIL DE DOCUMENTACION (VIDOC),
|
||||||
|
51,UNIDAD MOVIL FRONTERAS,
|
||||||
|
52,VARIOS SIN CLASIFICAR,
|
||||||
|
53,VEHICULO ELECTRICO NO HOMOLOGADO,
|
||||||
|
54,VEHICULO ELECTRICO UNIF. HOMOLOGADO,
|
||||||
|
@@ -1,55 +0,0 @@
|
|||||||
tipo,denominacion
|
|
||||||
AUTOCAR 21 A 40 PAX,
|
|
||||||
AUTOCAR > 40 PAX,
|
|
||||||
FURGON,
|
|
||||||
"CAMION < 3,5 TM",
|
|
||||||
"CAMION > 3,5 TM",
|
|
||||||
CANIOB DE CABALLOS,
|
|
||||||
CELULAR,
|
|
||||||
CICLOMOTOR,
|
|
||||||
CTRL. MOVIL FRONTERA,
|
|
||||||
EMBARCACION,
|
|
||||||
ESTACIONES ITV,
|
|
||||||
FURGON APOLO,
|
|
||||||
FURGON EDEX,
|
|
||||||
FURGON G.CANINOS,
|
|
||||||
FURGON GOES,
|
|
||||||
FURGON MINI APOLO,
|
|
||||||
FURGON U.P.R.,
|
|
||||||
FURGON UNIPOL F-8,
|
|
||||||
FURGONETA COMBI,
|
|
||||||
FURGONETA DE CARGA,
|
|
||||||
FURGONETA DNI,
|
|
||||||
FURGONETA DNI RURAL,
|
|
||||||
FURGONETA IZ,
|
|
||||||
FURGONETA LABORATORIO DE DOCUMENTOS FALSOS,
|
|
||||||
FURGONETA MIXTA,
|
|
||||||
FURGONETA P.CIENTIFICA,
|
|
||||||
FURGONETA SUBSUELO,
|
|
||||||
GRUA,
|
|
||||||
GRUPO ELECTROGENO,
|
|
||||||
LANZA-AGUA,
|
|
||||||
MAXI-Z,
|
|
||||||
MICROBUS 10 A 20 PAX,
|
|
||||||
MOTOCICLETA TIPO K,
|
|
||||||
MOTOCICLETA TIPO Q,
|
|
||||||
MOTOCICLETA UNIFORMADA,
|
|
||||||
POLICIA TECN.ESPECIALIDAD,
|
|
||||||
PUESTO DE MANDO AVANZADO,
|
|
||||||
REMOLQUE <750 KG,
|
|
||||||
REMOLQUE >750 KG,
|
|
||||||
TANQUETA,
|
|
||||||
TODO CAMINO,
|
|
||||||
TODO TERRENO,
|
|
||||||
TRACTOR TIPO EINSA,
|
|
||||||
TRANSPORTE SANITARIO,
|
|
||||||
TRASLADO EXTRANJEROS,
|
|
||||||
TURISMO K,
|
|
||||||
TURISMO Q,
|
|
||||||
TURISMO Z,
|
|
||||||
TURISMO Z COORDINACION,
|
|
||||||
UNIDAD MOVIL DE DOCUMENTACION (VIDOC),
|
|
||||||
UNIDAD MOVIL FRONTERAS,
|
|
||||||
VARIOS SIN CLASIFICAR ,
|
|
||||||
VEHICULO ELECTRICO NO HOMOLOGADO ,
|
|
||||||
VEHICULO ELECTRICO UNIF. HOMOLOGADO
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
id,unidad,poblacion_id
|
id,unidad,poblacion_id
|
||||||
1,AEROPUERTO,1
|
1,AEROPUERTO,1
|
||||||
2,AUTOMOCION,1
|
2,AUTOMOCION,1
|
||||||
32,BPEF,1
|
32,BPEF,1
|
||||||
@@ -19,14 +19,15 @@ id,unidad,poblacion_id
|
|||||||
47,BPI - TEDAX NRBQ,1
|
47,BPI - TEDAX NRBQ,1
|
||||||
48,BPPC,1
|
48,BPPC,1
|
||||||
49,BPPJ,1
|
49,BPPJ,1
|
||||||
|
313,BPPJ - UDEV,1
|
||||||
50,BPPJ - UDEV ATRACOS,1
|
50,BPPJ - UDEV ATRACOS,1
|
||||||
51,BPPJ - UDEV AUDIENCIA PROVINCIAL,1
|
51,BPPJ - UDEV AUDIENCIA PROVINCIAL,1
|
||||||
52,BPPJ - UDEV CIBERDELINCUENCIA 1,1
|
52,BPPJ - UDEV CIBERDELINCUENCIA 1,1
|
||||||
53,BPPJ - UDEV CIBERDELINCUENCIA 2,1
|
53,BPPJ - UDEV CIBERDELINCUENCIA 2,1
|
||||||
54,BPPJ - UDEV HOMICIDIOS,1
|
54,BPPJ - UDEV HOMICIDIOS,1
|
||||||
55,BPPJ - UDEV HURTOS,1
|
55,BPPJ - UDEV HURTOS,1
|
||||||
56,BPPJ - UDEV JEFE,1
|
56,BPPJ - UDEV JEFATURA,1
|
||||||
57,BPPJ - UDEV JEFE SECCION,1
|
57,BPPJ - UDEV JEFATURA SECCION,1
|
||||||
58,BPPJ - UDEV ROBOS 1,1
|
58,BPPJ - UDEV ROBOS 1,1
|
||||||
59,BPPJ - UDEV ROBOS 2,1
|
59,BPPJ - UDEV ROBOS 2,1
|
||||||
60,BPPJ - UDEV UFAM GRUME,1
|
60,BPPJ - UDEV UFAM GRUME,1
|
||||||
@@ -61,7 +62,7 @@ id,unidad,poblacion_id
|
|||||||
89,SECRETARIA GENERAL - INSTALACIONES,1
|
89,SECRETARIA GENERAL - INSTALACIONES,1
|
||||||
90,SECRETARIA GENERAL - MATERIAL,1
|
90,SECRETARIA GENERAL - MATERIAL,1
|
||||||
91,SECRETARIA GENERAL - TELECOMUNICACIONES,1
|
91,SECRETARIA GENERAL - TELECOMUNICACIONES,1
|
||||||
92,SECRETARIA GENERAL- NUCLEO RESERVA,1
|
92,SECRETARIA GENERAL - NUCLEO RESERVA,1
|
||||||
96,UCOP,1
|
96,UCOP,1
|
||||||
97,UCOP - GABINETE TECNICO,1
|
97,UCOP - GABINETE TECNICO,1
|
||||||
98,UCOP - GOES,1
|
98,UCOP - GOES,1
|
||||||
@@ -103,7 +104,6 @@ id,unidad,poblacion_id
|
|||||||
157,BLPJ - HURTOS,2
|
157,BLPJ - HURTOS,2
|
||||||
158,BLPJ - INFORMES,2
|
158,BLPJ - INFORMES,2
|
||||||
159,BLPJ - JEFATURA,2
|
159,BLPJ - JEFATURA,2
|
||||||
160,BLPJ - PATRIMONIO,2
|
|
||||||
161,BLPJ - PEQUEÑO TRAFICO,2
|
161,BLPJ - PEQUEÑO TRAFICO,2
|
||||||
162,BLPJ - PERSONAS,2
|
162,BLPJ - PERSONAS,2
|
||||||
163,BLPJ - ROBOS,2
|
163,BLPJ - ROBOS,2
|
||||||
@@ -118,7 +118,6 @@ id,unidad,poblacion_id
|
|||||||
176,BLI,3
|
176,BLI,3
|
||||||
177,BLPC,3
|
177,BLPC,3
|
||||||
178,BLPJ,3
|
178,BLPJ,3
|
||||||
179,BLPJ - PATRIMONIO,3
|
|
||||||
180,BLPJ - DELINCUENCIA ECONOMICA,3
|
180,BLPJ - DELINCUENCIA ECONOMICA,3
|
||||||
181,BLPJ - DELINCUENCIA URBANA,3
|
181,BLPJ - DELINCUENCIA URBANA,3
|
||||||
183,BLPJ - FRAUDES,3
|
183,BLPJ - FRAUDES,3
|
||||||
@@ -140,7 +139,6 @@ id,unidad,poblacion_id
|
|||||||
199,BLI,4
|
199,BLI,4
|
||||||
200,BLPC,4
|
200,BLPC,4
|
||||||
201,BLPJ,4
|
201,BLPJ,4
|
||||||
202,BLPJ - PATRIMONIO,4
|
|
||||||
203,BLPJ - DELINCUENCIA ECONOMICA,4
|
203,BLPJ - DELINCUENCIA ECONOMICA,4
|
||||||
205,BLPJ - DELINCUENCIA URBANA,4
|
205,BLPJ - DELINCUENCIA URBANA,4
|
||||||
206,BLPJ - FRAUDES,4
|
206,BLPJ - FRAUDES,4
|
||||||
@@ -162,7 +160,6 @@ id,unidad,poblacion_id
|
|||||||
222,BLI,5
|
222,BLI,5
|
||||||
223,BLPC,5
|
223,BLPC,5
|
||||||
224,BLPJ,5
|
224,BLPJ,5
|
||||||
225,BLPJ - PATRIMONIO,5
|
|
||||||
226,BLPJ - DELINCUENCIA ECONOMICA,5
|
226,BLPJ - DELINCUENCIA ECONOMICA,5
|
||||||
228,BLPJ - DELINCUENCIA URBANA,5
|
228,BLPJ - DELINCUENCIA URBANA,5
|
||||||
229,BLPJ - FRAUDES,5
|
229,BLPJ - FRAUDES,5
|
||||||
@@ -184,7 +181,6 @@ id,unidad,poblacion_id
|
|||||||
245,BLI,6
|
245,BLI,6
|
||||||
246,BLPC,6
|
246,BLPC,6
|
||||||
247,BLPJ,6
|
247,BLPJ,6
|
||||||
248,BLPJ - PATRIMONIO,6
|
|
||||||
249,BLPJ - DELINCUENCIA ECONOMICA,6
|
249,BLPJ - DELINCUENCIA ECONOMICA,6
|
||||||
251,BLPJ - DELINCUENCIA URBANA,6
|
251,BLPJ - DELINCUENCIA URBANA,6
|
||||||
252,BLPJ - FRAUDES,6
|
252,BLPJ - FRAUDES,6
|
||||||
@@ -206,7 +202,6 @@ id,unidad,poblacion_id
|
|||||||
268,BLI,7
|
268,BLI,7
|
||||||
269,BLPC,7
|
269,BLPC,7
|
||||||
270,BLPJ,7
|
270,BLPJ,7
|
||||||
271,BLPJ - PATRIMONIO,7
|
|
||||||
272,BLPJ - DELINCUENCIA ECONOMICA,7
|
272,BLPJ - DELINCUENCIA ECONOMICA,7
|
||||||
274,BLPJ - DELINCUENCIA URBANA,7
|
274,BLPJ - DELINCUENCIA URBANA,7
|
||||||
275,BLPJ - FRAUDES,7
|
275,BLPJ - FRAUDES,7
|
||||||
@@ -228,7 +223,6 @@ id,unidad,poblacion_id
|
|||||||
291,BLI,8
|
291,BLI,8
|
||||||
292,BLPC,8
|
292,BLPC,8
|
||||||
293,BLPJ,8
|
293,BLPJ,8
|
||||||
294,BLPJ - PATRIMONIO,8
|
|
||||||
295,BLPJ - DELINCUENCIA ECONOMICA,8
|
295,BLPJ - DELINCUENCIA ECONOMICA,8
|
||||||
297,BLPJ - DELINCUENCIA URBANA,8
|
297,BLPJ - DELINCUENCIA URBANA,8
|
||||||
298,BLPJ - FRAUDES,8
|
298,BLPJ - FRAUDES,8
|
||||||
|
|||||||
|
+81
-16
@@ -10,6 +10,7 @@
|
|||||||
document.documentElement.setAttribute('data-theme', theme);
|
document.documentElement.setAttribute('data-theme', theme);
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
<link rel="icon" type="image/svg+xml" href="{{ url_for('static', filename='car-front.svg') }}">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=Space+Grotesk:wght@400;600;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=Space+Grotesk:wght@400;600;700&display=swap" rel="stylesheet">
|
||||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/animate.min.css') }}">
|
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/animate.min.css') }}">
|
||||||
@@ -18,17 +19,19 @@
|
|||||||
<style>
|
<style>
|
||||||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
|
||||||
|
|
||||||
|
/* original */
|
||||||
:root {
|
:root {
|
||||||
--bg: #0d0f14;
|
--bg: #0a111f;
|
||||||
--surface: #13161e;
|
--surface: #101a2e;
|
||||||
--nav-bg: #0a0c10;
|
--nav-bg: #080e19;
|
||||||
--border: #1e2230;
|
--border: #1d2b45;
|
||||||
--accent: #5c6ef8;
|
--accent: #3b82f6;
|
||||||
--accent2: #8b5cf6;
|
--accent2: #06b6d4;
|
||||||
--text: #e2e6f0;
|
--text: #e8f0ff;
|
||||||
--muted: #5a607a;
|
--muted: #71819c;
|
||||||
--pill-bg: #1a1f2e;
|
--pill-bg: #17243a;
|
||||||
--success: #34d399;
|
--success: #22c7e8;
|
||||||
--nav-w: 220px;
|
--nav-w: 220px;
|
||||||
--radius: 12px;
|
--radius: 12px;
|
||||||
}
|
}
|
||||||
@@ -38,14 +41,73 @@
|
|||||||
--surface: #ffffff;
|
--surface: #ffffff;
|
||||||
--nav-bg: #ffffff;
|
--nav-bg: #ffffff;
|
||||||
--border: #e3e6ef;
|
--border: #e3e6ef;
|
||||||
--accent: #5c6ef8;
|
--accent: #2563eb;
|
||||||
--accent2: #8b5cf6;
|
--accent2: #4f8df7;
|
||||||
--text: #1a1d29;
|
--text: #1a1d29;
|
||||||
--muted: #8a8fa3;
|
--muted: #8a8fa3;
|
||||||
--pill-bg: #eef0f8;
|
--pill-bg: #eef0f8;
|
||||||
--success: #10b981;
|
--success: #159dcc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* azul profundo + azul eléctrico + cyan */
|
||||||
|
/* :root {
|
||||||
|
--bg: #0d0f14;
|
||||||
|
--surface: #13161e;
|
||||||
|
--nav-bg: #0a0c10;
|
||||||
|
--border: #1e2230;
|
||||||
|
--accent: #3b82f6;
|
||||||
|
--accent2: #06b6d4;
|
||||||
|
--text: #e2e6f0;
|
||||||
|
--muted: #5a607a;
|
||||||
|
--pill-bg: #1a1f2e;
|
||||||
|
--success: #34b9e8;
|
||||||
|
--nav-w: 220px;
|
||||||
|
--radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="light"] {
|
||||||
|
--bg: #f4f8fd;
|
||||||
|
--surface: #ffffff;
|
||||||
|
--nav-bg: #ffffff;
|
||||||
|
--border: #dce6f2;
|
||||||
|
--accent: #2563eb;
|
||||||
|
--accent2: #0891b2;
|
||||||
|
--text: #172033;
|
||||||
|
--muted: #718096;
|
||||||
|
--pill-bg: #eaf2fc;
|
||||||
|
--success: #0891b2;
|
||||||
|
} */
|
||||||
|
|
||||||
|
/* Ambar + coral */
|
||||||
|
/* :root {
|
||||||
|
--bg: #12110f;
|
||||||
|
--surface: #1b1916;
|
||||||
|
--nav-bg: #0e0d0b;
|
||||||
|
--border: #302b25;
|
||||||
|
--accent: #f59e0b;
|
||||||
|
--accent2: #f97316;
|
||||||
|
--text: #f3eee6;
|
||||||
|
--muted: #8e877d;
|
||||||
|
--pill-bg: #28231d;
|
||||||
|
--success: #34d399;
|
||||||
|
--nav-w: 220px;
|
||||||
|
--radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="light"] {
|
||||||
|
--bg: #faf8f4;
|
||||||
|
--surface: #ffffff;
|
||||||
|
--nav-bg: #ffffff;
|
||||||
|
--border: #e8e1d7;
|
||||||
|
--accent: #d97706;
|
||||||
|
--accent2: #ea580c;
|
||||||
|
--text: #29251f;
|
||||||
|
--muted: #8a8278;
|
||||||
|
--pill-bg: #f6eee1;
|
||||||
|
--success: #059669;
|
||||||
|
} */
|
||||||
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background: var(--bg);
|
background: var(--bg);
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
@@ -132,7 +194,10 @@
|
|||||||
}
|
}
|
||||||
.nav-links a:hover { background: var(--border); color: var(--text); }
|
.nav-links a:hover { background: var(--border); color: var(--text); }
|
||||||
.nav-links a.active {
|
.nav-links a.active {
|
||||||
background: linear-gradient(135deg, rgba(92,110,248,.18), rgba(139,92,246,.1));
|
background: linear-gradient(135deg, rgba(30, 144, 255, 0.08), rgba(0, 51, 204, 0.25));
|
||||||
|
/* background: linear-gradient(135deg, rgba(92,110,248,.18), rgba(139,92,246,.1)); */
|
||||||
|
/* background: linear-gradient(135deg, rgba(30, 144, 255, 0.25), rgba(0, 51, 204, 0.75)); */
|
||||||
|
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
border: 1px solid rgba(92,110,248,.25);
|
border: 1px solid rgba(92,110,248,.25);
|
||||||
}
|
}
|
||||||
@@ -645,7 +710,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="nav-logo">
|
<div class="nav-logo">
|
||||||
<span></span><h3>PyFleet</h3>
|
<span></span>PyFleet
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="theme-switch-row">
|
<div class="theme-switch-row">
|
||||||
@@ -683,7 +748,7 @@
|
|||||||
{% if session.get('mensaje') and page == 'contacto' %}<span class="msg-badge">!</span>{% endif %}
|
{% if session.get('mensaje') and page == 'contacto' %}<span class="msg-badge">!</span>{% endif %}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="nav-submenu" style="margin-top: 100px;">
|
<div class="nav-submenu">
|
||||||
<hr style="opacity: 0.5;margin-bottom: 5px;">
|
<hr style="opacity: 0.5;margin-bottom: 5px;">
|
||||||
<button class="nav-submenu-toggle {% if page in ['poblaciones','unidades','tipo'] %}active{% endif %}"
|
<button class="nav-submenu-toggle {% if page in ['poblaciones','unidades','tipo'] %}active{% endif %}"
|
||||||
onclick="toggleSubmenu(this)">
|
onclick="toggleSubmenu(this)">
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
--bg: #f5f6fa;
|
--bg: #f5f6fa;
|
||||||
--surface: #ffffff;
|
--surface: #ffffff;
|
||||||
--border: #e3e6ef;
|
--border: #e3e6ef;
|
||||||
--accent: #5c6ef8;
|
--accent: #2563eb;
|
||||||
--text: #1a1d29;
|
--text: #1a1d29;
|
||||||
--muted: #8a8fa3;
|
--muted: #8a8fa3;
|
||||||
--error-bg: rgba(248,113,113,.1);
|
--error-bg: rgba(248,113,113,.1);
|
||||||
|
|||||||
@@ -333,17 +333,17 @@
|
|||||||
|
|
||||||
<div class="form-actions" style="margin-top:28px">
|
<div class="form-actions" style="margin-top:28px">
|
||||||
<button type="submit" class="btn btn-primary"> <i class="bi bi-floppy" style="font-size: 1rem;"></i>
|
<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' }}
|
{{ 'GUARDAR CAMBIOS' if vehiculo else ' Registrar vehículo' }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{# Cancelar #}
|
{# Cancelar #}
|
||||||
|
|
||||||
{% if origen == 'viat' %}
|
{% if origen == 'viat' %}
|
||||||
<a href="/viat?q={{ q_viat }}" class="btn btn-ghost">Cancelar</a>
|
<a href="/viat?q={{ q_viat }}" class="btn btn-ghost" style="background-color: gray; color: white;"><i class="bi bi-x-lg"></i>CANCELAR</a>
|
||||||
{% elif desde or hasta or q_itv %}
|
{% elif desde or hasta or q_itv %}
|
||||||
<a href="/itv?desde={{ desde }}&hasta={{ hasta }}&q_itv={{ q_itv }}" class="btn btn-ghost">Cancelar</a>
|
<a href="/itv?desde={{ desde }}&hasta={{ hasta }}&q_itv={{ q_itv }}" class="btn btn-ghost" style="background-color: gray; color: white;"><i class="bi bi-x-lg"></i>CANCELAR</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ url_for('vehiculos_list', q=q) if q else url_for('vehiculos_list') }}" class="btn btn-ghost">Cancelar</a>
|
<a href="{{ url_for('vehiculos_list', q=q) if q else url_for('vehiculos_list') }}" class="btn btn-ghost" style="background-color: gray; color: white;"><i class="bi bi-x-lg"></i>CANCELAR</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- <div style="display:flex;justify-content:space-between;align-items:center;margin-top:12px;"> -->
|
<!-- <div style="display:flex;justify-content:space-between;align-items:center;margin-top:12px;"> -->
|
||||||
@@ -412,7 +412,9 @@
|
|||||||
<input type="hidden" name="_q" value="{{ q|default('') }}">
|
<input type="hidden" name="_q" value="{{ q|default('') }}">
|
||||||
<input type="hidden" name="_desde" value="{{ desde|default('') }}">
|
<input type="hidden" name="_desde" value="{{ desde|default('') }}">
|
||||||
<input type="hidden" name="_hasta" value="{{ hasta|default('') }}">
|
<input type="hidden" name="_hasta" value="{{ hasta|default('') }}">
|
||||||
<input type="hidden" name="_unidad_itv" value="{{ unidad_itv|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('') }}">
|
||||||
<button type="button" class="btn btn-danger btn-sm"
|
<button type="button" class="btn btn-danger btn-sm"
|
||||||
onclick="confirmarEliminar(this)">Eliminar</button>
|
onclick="confirmarEliminar(this)">Eliminar</button>
|
||||||
</form>
|
</form>
|
||||||
@@ -438,6 +440,8 @@
|
|||||||
<input type="hidden" name="_desde" value="{{ desde|default('') }}">
|
<input type="hidden" name="_desde" value="{{ desde|default('') }}">
|
||||||
<input type="hidden" name="_hasta" value="{{ hasta|default('') }}">
|
<input type="hidden" name="_hasta" value="{{ hasta|default('') }}">
|
||||||
<input type="hidden" name="_unidad_itv" value="{{ unidad_itv|default('') }}">
|
<input type="hidden" name="_unidad_itv" value="{{ unidad_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-grid" style="margin-bottom:12px;">
|
||||||
<div class="form-group" style="margin-bottom:0">
|
<div class="form-group" style="margin-bottom:0">
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<div class="page-eyebrow">Base de datos</div>
|
<div class="page-eyebrow">Base de datos</div>
|
||||||
<div class="page-title"><i class="bi bi-taxi-front"></i> Vehículos</div>
|
<div class="page-title"><i class="bi bi-taxi-front"></i> Vehículos</div>
|
||||||
<div class="page-subtitle">Gestión del parque móvil. Búsqueda por m.oficial, m.reservada, VIN, marca, modelo, poblacion, unidad, denominación, tipo, operacion, situacion, lanzadestellos.</div>
|
<div class="page-subtitle">Gestión del parque móvil. Búsqueda por m.oficial, m.reservada, VIN, marca, modelo, poblacion, unidad, tipo, situacion, lanzadestellos.</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="crud-toolbar">
|
<div class="crud-toolbar">
|
||||||
|
|||||||
Executable
+880
@@ -0,0 +1,880 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="es">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
|
<title>{% block title %}App{% endblock %} · PyFleet</title>
|
||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
var theme = localStorage.getItem('nexus-theme') || 'light';
|
||||||
|
document.documentElement.setAttribute('data-theme', theme);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<link rel="icon" type="image/svg+xml" href="{{ url_for('static', filename='car-front.svg') }}">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=Space+Grotesk:wght@400;600;700&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/animate.min.css') }}">
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='bootstrap-icons-1.13.1/bootstrap-icons.css') }}">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
|
||||||
|
|
||||||
|
/* original */
|
||||||
|
:root {
|
||||||
|
--bg: #0a111f;
|
||||||
|
--surface: #101a2e;
|
||||||
|
--nav-bg: #080e19;
|
||||||
|
--border: #1d2b45;
|
||||||
|
--accent: #3b82f6;
|
||||||
|
--accent2: #06b6d4;
|
||||||
|
--text: #e8f0ff;
|
||||||
|
--muted: #71819c;
|
||||||
|
--pill-bg: #17243a;
|
||||||
|
--success: #22c7e8;
|
||||||
|
--nav-w: 220px;
|
||||||
|
--radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="light"] {
|
||||||
|
--bg: #f5f6fa;
|
||||||
|
--surface: #ffffff;
|
||||||
|
--nav-bg: #ffffff;
|
||||||
|
--border: #e3e6ef;
|
||||||
|
--accent: #2563eb;
|
||||||
|
--accent2: #4f8df7;
|
||||||
|
--text: #1a1d29;
|
||||||
|
--muted: #8a8fa3;
|
||||||
|
--pill-bg: #eef0f8;
|
||||||
|
--success: #159dcc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* azul profundo + azul eléctrico + cyan */
|
||||||
|
/* :root {
|
||||||
|
--bg: #0d0f14;
|
||||||
|
--surface: #13161e;
|
||||||
|
--nav-bg: #0a0c10;
|
||||||
|
--border: #1e2230;
|
||||||
|
--accent: #3b82f6;
|
||||||
|
--accent2: #06b6d4;
|
||||||
|
--text: #e2e6f0;
|
||||||
|
--muted: #5a607a;
|
||||||
|
--pill-bg: #1a1f2e;
|
||||||
|
--success: #34b9e8;
|
||||||
|
--nav-w: 220px;
|
||||||
|
--radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="light"] {
|
||||||
|
--bg: #f4f8fd;
|
||||||
|
--surface: #ffffff;
|
||||||
|
--nav-bg: #ffffff;
|
||||||
|
--border: #dce6f2;
|
||||||
|
--accent: #2563eb;
|
||||||
|
--accent2: #0891b2;
|
||||||
|
--text: #172033;
|
||||||
|
--muted: #718096;
|
||||||
|
--pill-bg: #eaf2fc;
|
||||||
|
--success: #0891b2;
|
||||||
|
} */
|
||||||
|
|
||||||
|
/* Ambar + coral */
|
||||||
|
/* :root {
|
||||||
|
--bg: #12110f;
|
||||||
|
--surface: #1b1916;
|
||||||
|
--nav-bg: #0e0d0b;
|
||||||
|
--border: #302b25;
|
||||||
|
--accent: #f59e0b;
|
||||||
|
--accent2: #f97316;
|
||||||
|
--text: #f3eee6;
|
||||||
|
--muted: #8e877d;
|
||||||
|
--pill-bg: #28231d;
|
||||||
|
--success: #34d399;
|
||||||
|
--nav-w: 220px;
|
||||||
|
--radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="light"] {
|
||||||
|
--bg: #faf8f4;
|
||||||
|
--surface: #ffffff;
|
||||||
|
--nav-bg: #ffffff;
|
||||||
|
--border: #e8e1d7;
|
||||||
|
--accent: #d97706;
|
||||||
|
--accent2: #ea580c;
|
||||||
|
--text: #29251f;
|
||||||
|
--muted: #8a8278;
|
||||||
|
--pill-bg: #f6eee1;
|
||||||
|
--success: #059669;
|
||||||
|
} */
|
||||||
|
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: var(--bg);
|
||||||
|
color: var(--text);
|
||||||
|
font-family: 'Inter', sans-serif;
|
||||||
|
font-size: 15px;
|
||||||
|
display: flex;
|
||||||
|
min-height: 100vh;
|
||||||
|
transition: background .2s ease, color .2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-disabled-look {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
color: #6c757d;
|
||||||
|
border: 1px solid #ced4da;
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 0.7;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav, .card, .msg-banner, .msg-form input, .nav-links a {
|
||||||
|
transition: background .2s ease, border-color .2s ease, color .2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── NAVBAR ── */
|
||||||
|
nav {
|
||||||
|
width: var(--nav-w);
|
||||||
|
background: var(--nav-bg);
|
||||||
|
border-right: 1px solid var(--border);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 28px 16px 24px;
|
||||||
|
position: fixed;
|
||||||
|
top: 0; left: 0; bottom: 0;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-logo {
|
||||||
|
font-family: 'Space Grotesk', sans-serif;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text);
|
||||||
|
letter-spacing: -0.5px;
|
||||||
|
padding: 0 8px 28px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-logo span.dot {
|
||||||
|
width: 8px; height: 8px;
|
||||||
|
background: var(--accent);
|
||||||
|
border-radius: 50%;
|
||||||
|
display: inline-block;
|
||||||
|
box-shadow: 0 0 8px var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-section-label {
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 1.2px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--muted);
|
||||||
|
padding: 0 8px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-links {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-links a {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--muted);
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: background 0.15s, color 0.15s;
|
||||||
|
}
|
||||||
|
.nav-links a:hover { background: var(--border); color: var(--text); }
|
||||||
|
.nav-links a.active {
|
||||||
|
background: linear-gradient(135deg, rgba(30, 144, 255, 0.08), rgba(0, 51, 204, 0.25));
|
||||||
|
/* background: linear-gradient(135deg, rgba(92,110,248,.18), rgba(139,92,246,.1)); */
|
||||||
|
/* background: linear-gradient(135deg, rgba(30, 144, 255, 0.25), rgba(0, 51, 204, 0.75)); */
|
||||||
|
|
||||||
|
color: var(--text);
|
||||||
|
border: 1px solid rgba(92,110,248,.25);
|
||||||
|
}
|
||||||
|
.nav-links a .icon {
|
||||||
|
width: 18px; height: 18px;
|
||||||
|
opacity: .6;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.nav-links a.active .icon { opacity: 1; }
|
||||||
|
|
||||||
|
/* indicator bar */
|
||||||
|
.nav-links a.active::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 16px;
|
||||||
|
width: 3px; height: 18px;
|
||||||
|
background: var(--accent);
|
||||||
|
border-radius: 2px;
|
||||||
|
margin-left: -12px;
|
||||||
|
}
|
||||||
|
.nav-links a { position: relative; }
|
||||||
|
|
||||||
|
/* message badge in nav */
|
||||||
|
.msg-badge {
|
||||||
|
margin-left: auto;
|
||||||
|
background: var(--accent);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 2px 7px;
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-footer {
|
||||||
|
padding-top: 16px;
|
||||||
|
border-top: 1px solid var(--border);
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--muted);
|
||||||
|
padding-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── THEME SWITCH ── */
|
||||||
|
.theme-switch-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 8px 8px 16px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
.theme-switch-label {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--muted);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
.theme-toggle {
|
||||||
|
position: relative;
|
||||||
|
width: 42px;
|
||||||
|
height: 23px;
|
||||||
|
background: var(--pill-bg);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
flex-shrink: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.theme-toggle::after {
|
||||||
|
content: '☾';
|
||||||
|
position: absolute;
|
||||||
|
top: 1px; left: 1px;
|
||||||
|
width: 17px; height: 17px;
|
||||||
|
background: var(--accent);
|
||||||
|
border-radius: 50%;
|
||||||
|
transition: transform .25s cubic-bezier(.4,0,.2,1), background .2s;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 10px;
|
||||||
|
line-height: 1;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
[data-theme="light"] .theme-toggle::after {
|
||||||
|
content: '☀';
|
||||||
|
transform: translateX(19px);
|
||||||
|
background: #f59e0b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── MAIN CONTENT ── */
|
||||||
|
main {
|
||||||
|
margin-left: var(--nav-w);
|
||||||
|
flex: 1;
|
||||||
|
padding: 40px 48px;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header {
|
||||||
|
margin-bottom: 36px;
|
||||||
|
}
|
||||||
|
.page-eyebrow {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 1.4px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--accent);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
.page-title {
|
||||||
|
font-family: 'Space Grotesk', sans-serif;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text);
|
||||||
|
letter-spacing: -0.5px;
|
||||||
|
}
|
||||||
|
.page-subtitle {
|
||||||
|
margin-top: 6px;
|
||||||
|
color: var(--muted);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── MENSAJES MÚLTIPLES ── */
|
||||||
|
.msg-banner-wrap {
|
||||||
|
background: linear-gradient(135deg, rgba(92,110,248,.1), rgba(139,92,246,.06));
|
||||||
|
border: 1px solid rgba(92,110,248,.25);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
margin-bottom: 24px;
|
||||||
|
overflow: hidden;
|
||||||
|
animation: slideIn .25s ease;
|
||||||
|
}
|
||||||
|
.msg-banner-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 16px;
|
||||||
|
border-bottom: 1px solid rgba(92,110,248,.15);
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: .7px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
.msg-clear-all {
|
||||||
|
background: none;
|
||||||
|
border: 1px solid rgba(92,110,248,.3);
|
||||||
|
border-radius: 6px;
|
||||||
|
color: var(--muted);
|
||||||
|
font-size: 11px;
|
||||||
|
padding: 3px 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color .15s, border-color .15s;
|
||||||
|
}
|
||||||
|
.msg-clear-all:hover { color: var(--text); border-color: var(--muted); }
|
||||||
|
.msg-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 16px;
|
||||||
|
border-bottom: 1px solid rgba(92,110,248,.08);
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
.msg-item:last-child { border-bottom: none; }
|
||||||
|
.msg-fecha {
|
||||||
|
font-size: 10px;
|
||||||
|
color: var(--muted);
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
.msg-texto { font-size: 13px; color: var(--text); }
|
||||||
|
.msg-del-btn {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: var(--muted);
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 13px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 6px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
transition: color .15s, background .15s;
|
||||||
|
}
|
||||||
|
.msg-del-btn:hover { color: #f87171; background: rgba(248,113,113,.1); }
|
||||||
|
|
||||||
|
|
||||||
|
/* ── MESSAGE BANNER ── */
|
||||||
|
.msg-banner {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 16px;
|
||||||
|
background: linear-gradient(135deg, rgba(92,110,248,.12), rgba(139,92,246,.08));
|
||||||
|
border: 1px solid rgba(92,110,248,.3);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
padding: 14px 18px;
|
||||||
|
margin-bottom: 28px;
|
||||||
|
animation: slideIn .25s ease;
|
||||||
|
}
|
||||||
|
@keyframes slideIn {
|
||||||
|
from { opacity:0; transform: translateY(-6px); }
|
||||||
|
to { opacity:1; transform: translateY(0); }
|
||||||
|
}
|
||||||
|
.msg-banner .label {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: .8px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--accent);
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
.msg-banner .text { color: var(--text); font-size: 14px; }
|
||||||
|
.msg-banner a.clear-btn {
|
||||||
|
color: var(--muted);
|
||||||
|
font-size: 12px;
|
||||||
|
text-decoration: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 6px;
|
||||||
|
transition: color .15s, border-color .15s;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.msg-banner a.clear-btn:hover { color: var(--text); border-color: var(--muted); }
|
||||||
|
|
||||||
|
/* ── MESSAGE FORM ── */
|
||||||
|
.msg-form {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 28px;
|
||||||
|
max-width: 560px;
|
||||||
|
}
|
||||||
|
.msg-form input {
|
||||||
|
flex: 1;
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 8px;
|
||||||
|
color: var(--text);
|
||||||
|
font-family: 'Inter', sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
outline: none;
|
||||||
|
transition: border-color .15s;
|
||||||
|
}
|
||||||
|
.msg-form input::placeholder { color: var(--muted); }
|
||||||
|
.msg-form input:focus { border-color: var(--accent); }
|
||||||
|
.msg-form button {
|
||||||
|
background: var(--accent);
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-family: 'Inter', sans-serif;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 10px 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: opacity .15s;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.msg-form button:hover { opacity: .85; }
|
||||||
|
|
||||||
|
/* ── CARDS ── */
|
||||||
|
.card-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
||||||
|
gap: 16px;
|
||||||
|
margin-top: 28px;
|
||||||
|
}
|
||||||
|
.card {
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
padding: 20px;
|
||||||
|
transition: border-color .2s;
|
||||||
|
}
|
||||||
|
.card:hover { border-color: rgba(92,110,248,.35); }
|
||||||
|
.card-icon {
|
||||||
|
font-size: 22px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
.card-title {
|
||||||
|
font-family: 'Space Grotesk', sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
.card-desc { font-size: 13px; color: var(--muted); line-height: 1.5; }
|
||||||
|
|
||||||
|
/* ── SELECT / DROPDOWN ── */
|
||||||
|
.select-wrap {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.form-select {
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
cursor: pointer;
|
||||||
|
padding-right: 38px;
|
||||||
|
}
|
||||||
|
.form-select option {
|
||||||
|
background: var(--surface);
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
.select-arrow {
|
||||||
|
position: absolute;
|
||||||
|
right: 12px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
color: var(--muted);
|
||||||
|
pointer-events: none;
|
||||||
|
transition: transform .2s;
|
||||||
|
}
|
||||||
|
.select-wrap:focus-within .select-arrow {
|
||||||
|
transform: translateY(-50%) rotate(180deg);
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
.form-select:focus {
|
||||||
|
border-color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
{% block extra_css %}{% endblock %}
|
||||||
|
|
||||||
|
thead th {
|
||||||
|
position: relative;
|
||||||
|
transition: background .15s, color .15s;
|
||||||
|
}
|
||||||
|
thead th:hover {
|
||||||
|
background: var(--border);
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
thead th:hover .sort-icon {
|
||||||
|
opacity: .7 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ── CRUD TABLE ── */
|
||||||
|
.crud-toolbar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 16px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-wrap {
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
max-width: 360px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-wrap > svg:first-child {
|
||||||
|
/* .search-wrap svg { */
|
||||||
|
position: absolute;
|
||||||
|
left: 12px; top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 16px; height: 16px;
|
||||||
|
color: var(--muted);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.search-wrap input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 9px 14px 9px 38px;
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 8px;
|
||||||
|
color: var(--text);
|
||||||
|
font-family: 'Inter', sans-serif;
|
||||||
|
font-size: 13px;
|
||||||
|
outline: none;
|
||||||
|
transition: border-color .15s;
|
||||||
|
}
|
||||||
|
.search-wrap input::placeholder { color: var(--muted); }
|
||||||
|
.search-wrap input:focus { border-color: var(--accent); }
|
||||||
|
|
||||||
|
.btn { display: inline-flex; align-items: center; gap: 6px; padding: 9px 18px; border-radius: 8px; font-family: 'Inter', sans-serif; font-size: 13px; font-weight: 600; cursor: pointer; border: none; text-decoration: none; transition: opacity .15s, background .15s; }
|
||||||
|
.btn-primary { background: var(--accent); color: #fff; }
|
||||||
|
.btn-primary:hover { opacity: .85; }
|
||||||
|
.btn-ghost { background: var(--surface); color: var(--text); border: 1px solid var(--border); }
|
||||||
|
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); }
|
||||||
|
.btn-danger { background: transparent; color: #f87171; border: 1px solid rgba(248,113,113,.35); }
|
||||||
|
.btn-danger:hover { background: rgba(248,113,113,.08); }
|
||||||
|
.btn-sm { padding: 5px 12px; font-size: 12px; }
|
||||||
|
|
||||||
|
.table-wrap {
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
table { width: 100%; border-collapse: collapse; }
|
||||||
|
thead tr { background: var(--pill-bg); }
|
||||||
|
th {
|
||||||
|
padding: 12px 16px;
|
||||||
|
text-align: left;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: .8px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
padding: 13px 16px;
|
||||||
|
font-size: 13px;
|
||||||
|
border-top: 1px solid var(--border);
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
tbody tr { transition: background .12s; padding-bottom: }
|
||||||
|
tbody tr:hover { background: var(--pill-bg); }
|
||||||
|
.td-id { font-family: monospace; color: var(--muted); font-size: 12px; }
|
||||||
|
.td-actions { display: flex; gap: 8px; align-items: center; }
|
||||||
|
.empty-state {
|
||||||
|
text-align: center;
|
||||||
|
padding: 48px 24px;
|
||||||
|
color: var(--muted);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.empty-state svg { width: 40px; height: 40px; margin-bottom: 12px; opacity: .3; }
|
||||||
|
|
||||||
|
/* ── FORM ── */
|
||||||
|
.form-card {
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
padding: 32px;
|
||||||
|
max-width: 1560px; /* aqui se establece el ancho de los formularios */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.form-group { margin-bottom: 5px; }
|
||||||
|
.form-label {
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: .5px;
|
||||||
|
color: var(--muted);
|
||||||
|
margin-bottom: 7px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
.form-input {
|
||||||
|
width: 100%;
|
||||||
|
background: var(--bg);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 8px;
|
||||||
|
color: var(--text);
|
||||||
|
font-family: 'Inter', sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
outline: none;
|
||||||
|
transition: border-color .15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-submenu-toggle {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: var(--muted);
|
||||||
|
font-family: 'Inter', sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background .15s, color .15s;
|
||||||
|
}
|
||||||
|
.nav-submenu-toggle:hover,
|
||||||
|
.nav-submenu-toggle.active { background: var(--border); color: var(--text); }
|
||||||
|
.nav-submenu-items {
|
||||||
|
display: none;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
padding-left: 16px;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
.nav-submenu-items.open { display: flex; }
|
||||||
|
.nav-submenu-items a {
|
||||||
|
font-size: 13px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.form-input::placeholder { color: var(--muted); }
|
||||||
|
.form-input:focus { border-color: var(--accent); }
|
||||||
|
.form-input:disabled { opacity: .5; cursor: not-allowed; }
|
||||||
|
.form-actions { display: flex; gap: 10px; margin-top: 28px; }
|
||||||
|
|
||||||
|
/* ── FLASH ── */
|
||||||
|
.flash { padding: 11px 16px; border-radius: 8px; font-size: 13px; margin-bottom: 20px; animation: slideIn .2s ease; }
|
||||||
|
.flash.ok { background: rgba(52,211,153,.12); border: 1px solid rgba(52,211,153,.3); color: #34d399; }
|
||||||
|
.flash.error { background: rgba(248,113,113,.1); border: 1px solid rgba(248,113,113,.3); color: #f87171; }
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- class="animate__animated animate__backInLeft" -->
|
||||||
|
|
||||||
|
<nav id="navbar"
|
||||||
|
{% if session.pop("animate_navbar", None) %}
|
||||||
|
class="animate__animated animate__backInUp"
|
||||||
|
{% endif %}>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="padding: 0 8px 20px; text-align:center;">
|
||||||
|
<img src="{{ url_for('static', filename='img/logo.png') }}"
|
||||||
|
alt="Logo"
|
||||||
|
style="max-width:160px; width:100%; height:auto;">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="nav-logo">
|
||||||
|
<span></span><h3>PyFleet</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="theme-switch-row">
|
||||||
|
<span class="theme-switch-label">Tema</span>
|
||||||
|
<button class="theme-toggle" id="themeToggle" aria-label="Cambiar tema claro/oscuro" type="button"></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="nav-section-label">Navegación</div>
|
||||||
|
|
||||||
|
<div class="nav-links">
|
||||||
|
<a href="{{ url_for('index') }}" class="{% if page == 'inicio' %}active{% endif %}">
|
||||||
|
<i class="bi bi-house"style="font-size: 1rem;"></i>
|
||||||
|
Inicio
|
||||||
|
<!-- {% if session.get('mensaje') and page == 'inicio' %}<span class="msg-badge">!</span>{% endif %} -->
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="{{ url_for('vehiculos_list') }}" class="{% if page == 'vehiculos' %}active{% endif %}">
|
||||||
|
<i class="bi bi-car-front" style="font-size: 1rem;"></i>
|
||||||
|
Vehículos
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="{{ url_for('itv_list') }}" class="{% if page == 'itv' %}active{% endif %}">
|
||||||
|
<i class="bi bi-calendar-check" style="font-size: 1rem;"></i>
|
||||||
|
ITV
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="{{ url_for('viat_list') }}" class="{% if page == 'viat' %}active{% endif %}">
|
||||||
|
<i class="bi bi-broadcast" style="font-size: 1rem;"></i>
|
||||||
|
Via-T
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="{{ url_for('contacto') }}" class="{% if page == 'contacto' %}active{% endif %}">
|
||||||
|
<i class="bi bi-person-vcard" style="font-size: 1rem;"></i>
|
||||||
|
Contacto
|
||||||
|
{% if session.get('mensaje') and page == 'contacto' %}<span class="msg-badge">!</span>{% endif %}
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div class="nav-submenu" style="margin-top: 100px;">
|
||||||
|
<hr style="opacity: 0.5;margin-bottom: 5px;">
|
||||||
|
<button class="nav-submenu-toggle {% if page in ['poblaciones','unidades','tipo'] %}active{% endif %}"
|
||||||
|
onclick="toggleSubmenu(this)">
|
||||||
|
<i class="bi bi-database-check" style="font-size: 1rem;"></i>
|
||||||
|
Configuración
|
||||||
|
<svg class="chevron" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" style="margin-top:10px;margin-left:auto;transition:transform .2s">
|
||||||
|
<polyline points="6 9 12 15 18 9"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div class="nav-submenu-items {% if page in ['poblaciones','unidades','tipo'] %}open{% endif %}">
|
||||||
|
<a href="{{ url_for('unidades_list') }}" class="{% if page == 'unidades' %}active{% endif %}">
|
||||||
|
<i class="bi bi-building"></i>
|
||||||
|
Unidades
|
||||||
|
</a>
|
||||||
|
<a href="{{ url_for('tipo_list') }}" class="{% if page == 'tipo' %}active{% endif %}">
|
||||||
|
<i class="bi bi-bus-front"></i>
|
||||||
|
Tipo vehiculo
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="nav-footer">
|
||||||
|
{% if mensajes %}
|
||||||
|
<a href="{{ url_for('index') }}" style="
|
||||||
|
display:flex;align-items:center;gap:6px;
|
||||||
|
color:var(--accent);text-decoration:none;font-size:12px;
|
||||||
|
padding:6px 8px;border-radius:7px;transition:background .15s;
|
||||||
|
margin-bottom:4px;"
|
||||||
|
onmouseover="this.style.background='var(--border)'"
|
||||||
|
onmouseout="this.style.background=''">
|
||||||
|
💬 {{ mensajes|length }} mensaje{{ 's' if mensajes|length != 1 }} activo{{ 's' if mensajes|length != 1 }}
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
<span style="font-size:12px;padding:6px 8px;display:block;">Sin mensajes</span>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
<a href="{{ url_for('logout') }}" style="
|
||||||
|
display:flex;align-items:center;gap:8px;margin-top:12px;
|
||||||
|
color:var(--muted);font-size:13px;text-decoration:none;
|
||||||
|
padding:7px 8px;border-radius:7px;transition:background .15s,color .15s;
|
||||||
|
" onmouseover="this.style.background='var(--border)';this.style.color='var(--text)'"
|
||||||
|
onmouseout="this.style.background='';this.style.color='var(--muted)'">
|
||||||
|
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
|
<path d="M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4"/>
|
||||||
|
<polyline points="16 17 21 12 16 7"/>
|
||||||
|
<line x1="21" y1="12" x2="9" y2="12"/>
|
||||||
|
</svg>
|
||||||
|
Cerrar sesión
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
|
||||||
|
|
||||||
|
{# Mensajes solo en página de inicio #}
|
||||||
|
{% if page == 'inicio' %}
|
||||||
|
{% if mensajes %}
|
||||||
|
<div class="msg-banner-wrap">
|
||||||
|
<div class="msg-banner-header">
|
||||||
|
<div style="display:flex;align-items:center;gap:8px;">
|
||||||
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
|
<path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z"/>
|
||||||
|
</svg>
|
||||||
|
<span>{{ mensajes|length }} mensaje{{ 's' if mensajes|length != 1 }}</span>
|
||||||
|
</div>
|
||||||
|
<form method="POST" action="{{ url_for('mensajes_eliminar_todos') }}"
|
||||||
|
onsubmit="return confirm('¿Eliminar todos los mensajes?')">
|
||||||
|
<button type="submit" class="msg-clear-all">✕ Eliminar todos</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% for m in mensajes %}
|
||||||
|
<div class="msg-item">
|
||||||
|
<div>
|
||||||
|
<div class="msg-fecha">{{ m['fecha'] | fecha_es_hora }}</div>
|
||||||
|
<div class="msg-texto">{{ m['texto'] }}</div>
|
||||||
|
</div>
|
||||||
|
<form method="POST" action="{{ url_for('mensaje_eliminar', id=m['id']) }}">
|
||||||
|
<button type="submit" class="msg-del-btn" title="Eliminar este mensaje">✕</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||||
|
{% for category, message in messages %}
|
||||||
|
<div class="flash {{ category }}">{{ message }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endwith %}
|
||||||
|
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var toggle = document.getElementById('themeToggle');
|
||||||
|
var html = document.documentElement;
|
||||||
|
|
||||||
|
function applyTheme(theme) {
|
||||||
|
html.setAttribute('data-theme', theme);
|
||||||
|
localStorage.setItem('nexus-theme', theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync button state on load
|
||||||
|
applyTheme(localStorage.getItem('nexus-theme') || 'light');
|
||||||
|
|
||||||
|
toggle.addEventListener('click', function() {
|
||||||
|
var current = html.getAttribute('data-theme') === 'light' ? 'light' : 'dark';
|
||||||
|
var next = current === 'light' ? 'dark' : 'light';
|
||||||
|
applyTheme(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
function toggleSubmenu(btn) {
|
||||||
|
var items = btn.nextElementSibling;
|
||||||
|
items.classList.toggle('open');
|
||||||
|
btn.querySelector('.chevron').style.transform =
|
||||||
|
items.classList.contains('open') ? 'rotate(180deg)' : '';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Binary file not shown.
Executable
BIN
Binary file not shown.
Reference in New Issue
Block a user