Skip to main content

Overview

ITV Gestion Concesionario implements a robust, multi-layer validation system that ensures data integrity at every stage of the inspection process. The validation architecture includes input-level checks, form-level validation, and pre-calculation verification.
The system uses three validation layers: real-time input validation, submission validation, and pre-calculation verification.

Validation Layers

1

Input-Level Validation

Real-time validation as users type, preventing invalid data entry before submission
2

Form Submission Validation

Comprehensive checks when generating vehicle forms, validating completeness and format
3

Pre-Calculation Validation

Final verification before processing data, ensuring all required fields are complete

Layer 1: Real-Time Input Validation

Vehicle Count Validation

The system validates the number of vehicles in real-time (script.js:489-499):
const nAutosInput = document.getElementById("nAutos");
nAutosInput.addEventListener("input", function() {
    const valor = parseInt(this.value);
    if (valor > 50) {
        this.value = 50;
        mostrarError("El número máximo de vehículos es 50.");
    }
    if (valor < 0) {
        this.value = "";
    }
});
Validation Rules:
  • Maximum: 50 vehicles
  • Minimum: 1 vehicle
  • Type: Integer only
  • Auto-correction: Values exceeding 50 are automatically set to 50

Numeric Input Enforcement

Keypress validation ensures only numeric input (script.js:502-506):
script.js:502-506
nAutosInput.addEventListener("keypress", function(e) {
    if (!/[0-9]/.test(e.key) && !['Backspace', 'Delete', 'Tab', 'Enter'].includes(e.key)) {
        e.preventDefault();
    }
});
  • Digits: 0-9
  • Backspace
  • Delete
  • Tab
  • Enter

Text Field Auto-Formatting

Name and company fields are automatically capitalized (script.js:509-516):
script.js:509-516
const camposTexto = ['nombre', 'apellidos', 'razonSocial'];
camposTexto.forEach(campo => {
    const input = document.getElementById(campo);
    input.addEventListener("input", function() {
        this.value = this.value.charAt(0).toUpperCase() + this.value.slice(1);
    });
});
Auto-Formatting:
  • First character is automatically capitalized
  • Improves data consistency
  • Applies to: nombre, apellidos, razonSocial

Layer 2: Form Submission Validation

Main Validation Function: enviar()

The enviar() function (script.js:8) performs comprehensive validation before form generation:
function enviar() {
    // Validar campos obligatorios
    const nombre = document.getElementById("nombre").value.trim();
    const apellidos = document.getElementById("apellidos").value.trim();
    const razonSocial = document.getElementById("razonSocial").value.trim();
    const nAutosInput = document.getElementById("nAutos").value.trim();

    // Validaciones básicas
    if (!nombre || !apellidos || !razonSocial || !nAutosInput) {
        mostrarError("Por favor, complete todos los campos obligatorios.");
        return;
    }

    numeroAutos = parseInt(nAutosInput);
    if (isNaN(numeroAutos) || numeroAutos <= 0 || numeroAutos > 50) {
        mostrarError("Por favor, ingrese un número válido de vehículos (1-50).");
        return;
    }
    
    // ... continue with form generation
}

Validation Checks Performed

Fields Checked:
  • nombre (Name)
  • apellidos (Surname)
  • razonSocial (Company Name)
  • nAutos (Number of Vehicles)
Method:
  • Uses .trim() to remove whitespace
  • Checks for empty strings
  • Displays error if any field is empty
Validations:
  • isNaN() check for non-numeric values
  • <= 0 check for zero or negative values
  • > 50 check for values exceeding maximum
Error Message: “Por favor, ingrese un número válido de vehículos (1-50).”
Process:
  1. Input value is parsed using parseInt()
  2. Result is checked with isNaN()
  3. If parsing fails, error is displayed
Handles:
  • Text input in numeric field
  • Special characters
  • Empty strings

Layer 3: Pre-Calculation Validation

Vehicle Form Validation: validarFormulariosVehiculos()

Before calculations, all vehicle forms are validated (script.js:167-184):
function validarFormulariosVehiculos() {
    for (let i = 1; i <= numeroAutos; i++) {
        // Verificar motorización
        const motorizacionSeleccionada = document.querySelector(`input[name="motorizacion${i}"]:checked`);
        if (!motorizacionSeleccionada) {
            mostrarError(`Por favor, seleccione la motorización para el vehículo ${i}.`);
            return false;
        }

        // Verificar estado ITV
        const itvSeleccionado = document.querySelector(`input[name="aprobados${i}"]:checked`);
        if (!itvSeleccionado) {
            mostrarError(`Por favor, seleccione el estado ITV para el vehículo ${i}.`);
            return false;
        }
    }
    return true;
}
Validation Logic:
  • Iterates through all vehicle forms (1 to numeroAutos)
  • Checks each vehicle has motorization selected
  • Checks each vehicle has ITV status selected
  • Returns false on first validation failure
  • Returns true only if all vehicles are complete

Required Fields per Vehicle

Motorization

RequiredOne of:
  • Diesel
  • Gasoline
  • Hybrid
  • Electric

ITV Status

RequiredOne of:
  • Approved
  • Not Approved

Observations

OptionalFree text field with 250-character limit

Vehicle Number

AutomaticAuto-assigned during form generation

Validation Integration

The validation system is integrated throughout the workflow:

Main Calculation Flow

Validation is called in the calcular() function (script.js:119-148):
script.js:119-148
function calcular() {
    try {
        // Obtener datos del cliente
        const datosCliente = obtenerDatosCliente();

        // Validar que todos los vehículos tengan datos completos
        if (!validarFormulariosVehiculos()) {
            return;  // Stop execution if validation fails
        }

        // Procesar datos de vehículos
        procesarDatosVehiculos();

        // ... continue with display functions
    } catch (error) {
        console.error("Error en el cálculo:", error);
        mostrarError("Ha ocurrido un error al procesar los datos. Por favor, verifique la información ingresada.");
    }
}

Calculate and Display Wrapper

The calcularYMostrar() function (script.js:693) validates before proceeding:
script.js:693-704
function calcularYMostrar() {
    // Validar que todos los vehículos tengan datos completos
    if (!validarFormulariosVehiculos()) {
        return; // Detener la ejecución si hay errores
    }
    // Si la validación es exitosa, calcular y mostrar resultados
    calcular();
    ocultarCaja();
    setTimeout(() => {
        agregarBotonesAccion();
    }, 500);
}
Critical: Early Return PatternAll validation functions use early returns to stop execution immediately upon detecting invalid data. This prevents partially validated data from being processed.

Error Display System

The validation system uses a sophisticated error notification function (script.js:381-464):
script.js:381-464
function mostrarError(mensaje) {
    // Remover alertas anteriores
    const alertaAnterior = document.querySelector(".alert-error");
    if (alertaAnterior) {
        alertaAnterior.remove();
    }

    // Crear nueva alerta
    const alerta = document.createElement("div");
    alerta.className = "alert-error";
    alerta.innerHTML = `
        <div class="alert-content">
            <span class="alert-icon">⚠️</span>
            <span class="alert-message">${mensaje}</span>
            <button class="alert-close" onclick="this.parentElement.parentElement.remove()">×</button>
        </div>
    `;

    // Agregar estilos dinámicamente si no existen
    if (!document.querySelector("#alert-styles")) {
        const estilos = document.createElement("style");
        estilos.id = "alert-styles";
        estilos.textContent = `
            .alert-error {
                position: fixed;
                top: 20px;
                right: 20px;
                background: linear-gradient(135deg, #fef2f2 0%, #fee2e2 100%);
                border: 2px solid #ef4444;
                border-radius: 0.75rem;
                padding: 1rem;
                box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);
                z-index: 1000;
                max-width: 400px;
                animation: slideIn 0.3s ease-out;
            }
            /* ... additional styles ... */
        `;
        document.head.appendChild(estilos);
    }

    document.body.appendChild(alerta);

    // Auto-remover después de 5 segundos
    setTimeout(() => {
        if (alerta.parentElement) {
            alerta.style.animation = "slideIn 0.3s ease-out reverse";
            setTimeout(() => alerta.remove(), 300);
        }
    }, 5000);
}

Error Alert Features

Auto-Dismiss

Alerts automatically disappear after 5 seconds

Manual Close

Users can manually dismiss alerts with the × button

Fixed Position

Alerts appear in top-right corner, not blocking content

Slide Animation

Smooth slide-in and slide-out animations

Single Instance

Previous alerts are removed before showing new ones

High z-index

z-index: 1000 ensures alerts appear above all content

HTML Validation Attributes

The HTML form includes native validation attributes (index.html:34-50):
index.html:34-50
<div class="input-group">
    <label for="nombre">Nombre</label>
    <input type="text" id="nombre" placeholder="Ingrese su nombre" required>
</div>
<div class="input-group">
    <label for="apellidos">Apellidos</label>
    <input type="text" id="apellidos" placeholder="Ingrese sus apellidos" required>
</div>
<div class="input-group">
    <label for="razonSocial">Razón Social</label>
    <input type="text" id="razonSocial" placeholder="Empresa o particular" required>
</div>
<div class="input-group">
    <label for="nAutos">Nº de Vehículos</label>
    <input type="text" id="nAutos" placeholder="Cantidad de vehículos" required>
</div>
The required attribute provides browser-level validation as a first line of defense, complementing JavaScript validation.

Accessibility Features

The validation system includes accessibility enhancements (styles.css:482-491):
styles.css:482-491
input[type="radio"]:focus,
input[type="checkbox"]:focus {
    outline: 2px solid #2563eb;
    outline-offset: 2px;
}

button:focus {
    outline: 2px solid #2563eb;
    outline-offset: 2px;
}
Accessibility Benefits:
  • Clear focus indicators for keyboard navigation
  • WCAG 2.1 compliant focus states
  • Visible outlines with proper offset
  • Consistent focus styling across all interactive elements

Validation Event Initialization

All validation events are initialized on DOM load (script.js:706-715):
script.js:706-715
document.addEventListener("DOMContentLoaded", function() {
    inicializarEventos();

    // Ocultar resultados inicialmente
    const muestra = document.getElementById("muestra");
    muestra.style.opacity = "0";
    muestra.style.transform = "translateY(20px)";
    muestra.style.transition = "all 0.3s ease";
});

Best Practices Implemented

  • HTML5 required attributes provide baseline validation
  • JavaScript adds enhanced validation and UX improvements
  • System remains functional even with JavaScript disabled (basic validation)
  • Validation stops at first error
  • Specific error messages guide users to the exact problem
  • Early returns prevent cascading validation failures
  • Clear, contextual error messages in Spanish
  • Vehicle-specific error messages (“vehículo 3”)
  • Visual indicators with icons (⚠️)
  • Non-intrusive positioning
  • .trim() removes leading/trailing whitespace
  • parseInt() ensures numeric values are integers
  • Auto-capitalization maintains consistency

Next Steps

Dynamic Forms

See how validated data generates vehicle forms

Cost Calculation

Learn how validated data powers cost calculations

Build docs developers (and LLMs) love