Overview
The results display system transforms validated vehicle inspection data into a professional, visually appealing presentation. It includes customer information, itemized cost breakdowns, ITV status indicators, and vehicle observations, all presented in a responsive, card-based layout.
Results are displayed in a responsive grid layout with smooth animations and professional styling, optimized for both desktop and mobile viewing.
Display Architecture
The results section is structured into multiple information cards:
Customer Information Name, surname, company, and vehicle count
Total Cost Itemized breakdown and grand total
ITV Status Pass/fail status for each vehicle
Observations Detailed notes for each vehicle (full-width)
HTML Structure
The results section container (index.html:68-105):
< section id = "muestra" class = "results-section" >
<!-- Tarjeta con información del cliente -->
< div class = "info-card" >
< div class = "informacion" id = "informacion" >
< h3 > 👤 Información del Cliente </ h3 >
</ div >
</ div >
<!-- Tarjeta con el total a pagar -->
< div class = "info-card" >
< div class = "total" >
< h3 > 💰 Total a Pagar </ h3 >
< div class = "total-amount" >
< span id = "total" > €0 </ span >
</ div >
</ div >
</ div >
<!-- Tarjeta con el estado de la ITV -->
< div class = "info-card" >
< div id = "resultados" class = "resultados" >
< h3 > ✅ Estado ITV </ h3 >
< div class = "status-content" >
< span id = "raprobado" ></ span >
</ div >
</ div >
</ div >
<!-- Tarjeta con observaciones (ancho completo) -->
< div class = "info-card full-width" >
< div class = "observacion" >
< h3 > 📝 Observaciones </ h3 >
< div class = "observations-content" >
< span id = "robservaciones" ></ span >
</ div >
</ div >
</ div >
</ section >
The results section is initially hidden and revealed with animations after calculation completes.
Display Functions
Main Orchestration: calcular()
The calcular() function (script.js:119) coordinates all display operations:
Customer Data Display
mostrarInformacionCliente() renders customer details
ITV Status Display
mostrarEstadosITV() shows pass/fail status for each vehicle
Observations Display
mostrarObservaciones() displays vehicle-specific notes
Cost Display
calcularYMostrarTotal() shows itemized costs and total
The mostrarInformacionCliente() function (script.js:210-218) renders customer data:
function mostrarInformacionCliente ( datos ) {
document . getElementById ( "informacion" ). innerHTML = `
<h3>👤 Información del Cliente</h3>
<div>Nombre: <span> ${ datos . nombre } </span></div>
<div>Apellidos: <span> ${ datos . apellidos } </span></div>
<div>Razón Social: <span> ${ datos . razonSocial } </span></div>
<div>Nº de Vehículos: <span> ${ datos . nAutos } </span></div>
` ;
}
Customer data comes from obtenerDatosCliente() (script.js:154-161): function obtenerDatosCliente () {
return {
nombre: document . getElementById ( "nombre" ). value . trim (),
apellidos: document . getElementById ( "apellidos" ). value . trim (),
razonSocial: document . getElementById ( "razonSocial" ). value . trim (),
nAutos: numeroAutos
};
}
Information rows are styled with blue accent bars (styles.css:348-359): .informacion div {
display : flex ;
justify-content : space-between ;
align-items : center ;
padding : 0.75 rem ;
margin : 0.5 rem 0 ;
background : rgba ( 37 , 99 , 235 , 0.05 );
border-radius : 0.5 rem ;
border-left : 3 px solid #2563eb ;
font-weight : 500 ;
}
ITV Status Display
The mostrarEstadosITV() function (script.js:223-239) displays vehicle inspection results:
function mostrarEstadosITV () {
let estadosHTML = "" ;
vehiculosData . forEach ( vehiculo => {
const emoji = vehiculo . estadoITV === "Aprobo" ? "✅" : "❌" ;
const estado = vehiculo . estadoITV === "Aprobo" ? "Aprobado" : "No Aprobado" ;
const clase = vehiculo . estadoITV === "Aprobo" ? "aprobado" : "no-aprobado" ;
estadosHTML += `
<div class="estado-vehiculo ${ clase } ">
${ emoji } Vehículo Nº ${ vehiculo . numero } : ${ estado }
</div>
` ;
});
document . getElementById ( "raprobado" ). innerHTML = estadosHTML ;
}
Status Styling
Vehicle status items have conditional styling (styles.css:638-656):
Base Styles
Approved Status
Failed Status
.estado-vehiculo {
padding : 0.75 rem ;
margin : 0.5 rem 0 ;
border-radius : 0.5 rem ;
font-weight : 600 ;
background : rgba ( 37 , 99 , 235 , 0.05 );
border-left : 4 px solid #2563eb ;
}
.estado-vehiculo.aprobado {
background : rgba ( 16 , 185 , 129 , 0.1 );
border-left-color : #10b981 ;
color : #10b981 ;
}
.estado-vehiculo.no-aprobado {
background : rgba ( 239 , 68 , 68 , 0.1 );
border-left-color : #ef4444 ;
color : #ef4444 ;
}
Color Coding:
✅ Green for approved vehicles
❌ Red for failed vehicles
Visual indicators for at-a-glance status recognition
Observations Display
The mostrarObservaciones() function (script.js:244-263) renders vehicle notes:
function mostrarObservaciones () {
let observacionesHTML = "" ;
vehiculosData . forEach ( vehiculo => {
if ( vehiculo . observaciones ) {
observacionesHTML += `
<div class="observacion-vehiculo">
<strong>🚗 Vehículo Nº ${ vehiculo . numero } :</strong><br>
<div class="caja-texto"> ${ vehiculo . observaciones } </div>
</div>
` ;
}
});
if ( observacionesHTML === "" ) {
observacionesHTML = "<em>Sin observaciones registradas</em>" ;
}
document . getElementById ( "robservaciones" ). innerHTML = observacionesHTML ;
}
Smart Display Logic:
Only vehicles with observations are shown
Empty state message displayed if no observations exist
Each observation is clearly labeled with vehicle number
Cost Display
See the Cost Calculation page for detailed information about the calcularYMostrarTotal() function.
Animation System
The ocultarCaja() function (script.js:339-355) handles the transition:
function ocultarCaja () {
const formularios = document . getElementById ( "formularios" );
const formSection = document . querySelector ( ".form-section" );
const resultados = document . getElementById ( "muestra" );
// Animación de salida para formularios dinámicos y sección principal
formularios . style . opacity = "0" ;
formularios . style . transform = "translateY(-20px)" ;
formSection . style . opacity = "0" ;
formSection . style . transform = "translateY(-20px)" ;
setTimeout (() => {
formularios . style . display = "none" ;
formSection . style . display = "none" ;
mostrarResultados ();
}, 300 );
}
Show Results Animation
The mostrarResultados() function (script.js:360-375) animates results in:
function mostrarResultados () {
const resultados = document . getElementById ( "muestra" );
resultados . classList . add ( "show" );
// Animación de entrada
setTimeout (() => {
resultados . style . opacity = "1" ;
resultados . style . transform = "translateY(0)" ;
}, 100 );
// Scroll suave hacia los resultados
resultados . scrollIntoView ({
behavior: "smooth" ,
block: "start"
});
}
Animation Sequence:
Forms fade out and slide up (300ms)
Forms are hidden (display: none)
Results section is revealed
Results fade in and slide down (smooth)
Page scrolls to results section
The agregarBotonesAccion() function (script.js:578) adds utility buttons to results:
View Action Buttons Implementation
Available Actions
Print 🖨️ imprimirResultados() Formats results for printing (script.js:551-573)
Export 📥 exportarResultados() Exports data as JSON file (script.js:529-548)
Reset 🔄 reiniciarFormulario() Reloads page for new inspection (script.js:522-526)
Export Functionality
The export function creates a JSON file with complete inspection data:
function exportarResultados () {
const datosExportacion = {
cliente: obtenerDatosCliente (),
vehiculos: vehiculosData ,
fecha: new Date (). toLocaleDateString ( 'es-ES' ),
hora: new Date (). toLocaleTimeString ( 'es-ES' )
};
const jsonStr = JSON . stringify ( datosExportacion , null , 2 );
const blob = new Blob ([ jsonStr ], { type: 'application/json' });
const url = URL . createObjectURL ( blob );
const a = document . createElement ( 'a' );
a . href = url ;
a . download = `ITV_ ${ datosExportacion . cliente . apellidos } _ ${ Date . now () } .json` ;
document . body . appendChild ( a );
a . click ();
document . body . removeChild ( a );
URL . revokeObjectURL ( url );
}
Export Structure
Filename Format
{
"cliente" : {
"nombre" : "Juan" ,
"apellidos" : "García" ,
"razonSocial" : "AutoFleet SL" ,
"nAutos" : 3
},
"vehiculos" : [
{
"numero" : 1 ,
"motorizacion" : "Diesel" ,
"estadoITV" : "Aprobo" ,
"observaciones" : "Vehículo en perfecto estado"
},
// ... more vehicles
],
"fecha" : "07/03/2026" ,
"hora" : "14:35:22"
}
ITV_[APELLIDOS]_[TIMESTAMP].json
Example: ITV_García_1736251522847.json
Print Functionality
The print function (script.js:551-573) formats results for printing:
function imprimirResultados () {
const contenidoOriginal = document . body . innerHTML ;
const resultados = document . getElementById ( "muestra" ). outerHTML ;
const informacionCliente = document . getElementById ( "informacion" ). outerHTML ;
document . body . innerHTML = `
<div style="padding: 20px; font-family: Arial, sans-serif;">
<h1 style="text-align: center; color: #2563eb;">Concesionario de Coches - Resultados ITV</h1>
<hr style="margin: 20px 0;">
${ informacionCliente }
${ resultados }
<div style="margin-top: 30px; text-align: center; font-size: 12px; color: #666;">
Impreso el ${ new Date (). toLocaleDateString ( 'es-ES' ) } a las ${ new Date (). toLocaleTimeString ( 'es-ES' ) }
</div>
</div>
` ;
window . print ();
document . body . innerHTML = contenidoOriginal ;
inicializarEventos ();
}
Print Features:
Clean, print-optimized layout
Includes timestamp footer
Restores page after printing
Re-initializes events after restoration
Responsive Design
Results section adapts to different screen sizes (styles.css:290-304, 448-456):
Desktop Layout
Tablet Layout
Mobile Layout
.results-section {
display : none ;
grid-template-columns : repeat ( auto-fit , minmax ( 300 px , 1 fr ));
gap : 1.5 rem ;
margin-top : 2 rem ;
padding : 2 rem ;
background : linear-gradient ( 135 deg , #f8fafc 0 % , #f1f5f9 100 % );
border-radius : 0.75 rem ;
border : 1 px solid #e5e7eb ;
}
.results-section.show {
display : grid ;
}
@media ( max-width : 768 px ) {
.results-section {
grid-template-columns : 1 fr ;
gap : 1 rem ;
padding : 1 rem ;
}
}
.info-card.full-width {
grid-column : 1 ;
}
On mobile, all cards stack vertically
Card Styling
Information cards have consistent, elevated styling (styles.css:306-322):
.info-card {
background : #ffffff ;
border-radius : 0.75 rem ;
box-shadow : 0 4 px 6 px -1 px rgb ( 0 0 0 / 0.1 ), 0 2 px 4 px -2 px rgb ( 0 0 0 / 0.1 );
border : 1 px solid #e5e7eb ;
overflow : hidden ;
transition : all 0.3 s ease ;
}
.info-card:hover {
transform : translateY ( -2 px );
box-shadow : 0 10 px 15 px -3 px rgb ( 0 0 0 / 0.1 ), 0 4 px 6 px -4 px rgb ( 0 0 0 / 0.1 );
}
.info-card.full-width {
grid-column : 1 / -1 ;
}
Visual Polish
Subtle shadows for depth
Rounded corners (0.75rem)
Smooth hover transitions
Gradient backgrounds in headers
Interaction
Hover lift effect (-2px translateY)
Enhanced shadows on hover
300ms transition timing
Smooth, professional animations
Initialization
Results section is prepared on page load (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" ;
});
The results section must be hidden on initial page load to enable the slide-in animation when results are calculated.
Next Steps
Dynamic Forms Learn how forms are generated before results
Data Validation Understand validation that ensures data quality