// Base API
const API = '/f1/api';
// ─── Tabs ─────────────────────────────────────────────────────
document.querySelectorAll('.tab-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
btn.classList.add('active');
document.getElementById('tab-' + btn.dataset.tab).classList.add('active');
});
});
// ─── Cuenta atrás próxima carrera (Ergast/Jolpi API) ──────────
async function initCuentaAtras() {
try {
const res = await fetch('https://api.jolpi.ca/ergast/f1/2026.json');
const data = await res.json();
const carreras = data.MRData.RaceTable.Races;
const ahora = new Date();
const proxima = carreras.find(c => new Date(`${c.date}T${c.time || '12:00:00Z'}`) > ahora);
if (!proxima) {
document.getElementById('nombre-proxima-carrera').textContent = 'Temporada terminada';
document.getElementById('countdown').textContent = '—';
return;
}
const fechaProxima = new Date(`${proxima.date}T${proxima.time || '12:00:00Z'}`);
document.getElementById('nombre-proxima-carrera').textContent =
`⏱️ Cuenta atrás — ${proxima.raceName}`;
function tick() {
const diff = fechaProxima - new Date();
if (diff <= 0) { document.getElementById('countdown').textContent = '🏁 ¡Carrera en curso!'; return; }
const d = Math.floor(diff / 86400000);
const h = Math.floor((diff % 86400000) / 3600000);
const m = Math.floor((diff % 3600000) / 60000);
const s = Math.floor((diff % 60000) / 1000);
document.getElementById('countdown').textContent = `${d}d ${h}h ${m}m ${s}s`;
}
tick();
setInterval(tick, 1000);
} catch (e) {
document.getElementById('countdown').textContent = '—';
}
}
// ─── Clasificación ────────────────────────────────────────────
async function cargarClasificacionPilotos() {
const res = await fetch(`${API}/resultados/clasificacion/pilotos?temporada=2025`);
return res.json();
}
async function cargarClasificacionConstructores() {
const res = await fetch(`${API}/resultados/clasificacion/constructores?temporada=2025`);
return res.json();
}
function renderClasificacionPilotos(data, tablaId, maxRows = 999) {
const tbody = document.querySelector(`#${tablaId} tbody`);
tbody.innerHTML = '';
const esCompleta = tablaId.includes('clasificacion');
data.slice(0, maxRows).forEach((p, i) => {
const tr = document.createElement('tr');
if (i === 0) tr.classList.add('campeon');
tr.innerHTML = `
${i + 1} |
${p.nombre} ${p.apellido} |
${p.equipo} |
${p.puntos} |
${p.victorias} |
${esCompleta ? `${p.podios} | ${p.vueltasRapidas} | ` : ''}
`;
tbody.appendChild(tr);
});
}
function renderClasificacionConstructores(data, tablaId, maxRows = 999) {
const tbody = document.querySelector(`#${tablaId} tbody`);
tbody.innerHTML = '';
const esCompleta = tablaId.includes('clasificacion');
data.slice(0, maxRows).forEach((c, i) => {
const tr = document.createElement('tr');
if (i === 0) tr.classList.add('campeon');
tr.innerHTML = `
${i + 1} |
${c.nombre} |
${c.puntos} |
${c.victorias} |
${esCompleta ? `${c.podios} | ` : ''}
`;
tbody.appendChild(tr);
});
}
// ─── Calendario ───────────────────────────────────────────────
async function cargarCalendario() {
const res = await fetch(`${API}/gp?temporada=2025`);
return res.json();
}
function renderCalendario(gps) {
const cont = document.getElementById('lista-gp');
const hoy = new Date();
cont.innerHTML = '';
gps.forEach((gp, i) => {
const fecha = new Date(gp.fecha);
const pasado = fecha < hoy;
const card = document.createElement('div');
card.className = 'gp-card ' + (pasado ? 'pasado' : 'proximo');
card.innerHTML = `
${String(i + 1).padStart(2, '0')}
${gp.nombre}
${gp.circuito}
${gp.ciudad}, ${gp.pais}
${fecha.toLocaleDateString('es-ES', {day:'numeric',month:'long',year:'numeric'})}
${gp.numVueltas} vueltas · ${gp.distanciaKm} km
${pasado
? ``
: 'Próxima'}
`;
cont.appendChild(card);
});
}
function renderUltimasCarreras(gps) {
const hoy = new Date();
const pasados = gps.filter(g => new Date(g.fecha) < hoy).slice(-3).reverse();
const cont = document.getElementById('ultimas-carreras');
cont.innerHTML = '';
pasados.forEach(gp => {
const div = document.createElement('div');
div.className = 'carrera-mini';
div.innerHTML = `${gp.nombre}
`;
cont.appendChild(div);
});
}
// ─── Modal resultados ─────────────────────────────────────────
async function abrirResultados(gpId, nombre) {
document.getElementById('modal-titulo').textContent = nombre;
document.querySelector('#modal-resultados tbody').innerHTML = '| Cargando... |
';
document.getElementById('modal-carrera').classList.remove('hidden');
const res = await fetch(`${API}/resultados/gp/${gpId}`);
const data = await res.json();
const tbody = document.querySelector('#modal-resultados tbody');
tbody.innerHTML = '';
data.forEach(r => {
const tr = document.createElement('tr');
if (r.posicion === 1) tr.classList.add('ganador');
tr.innerHTML = `
${r.posicion ?? 'DNF'} |
${r.piloto.nombre} ${r.piloto.apellido}${r.vueltaRapida ? ' ⚡' : ''} |
${r.escuderia.nombre} |
${r.puntos} |
${r.estado} |
`;
tbody.appendChild(tr);
});
}
function cerrarModal() {
document.getElementById('modal-carrera').classList.add('hidden');
}
document.getElementById('modal-carrera').addEventListener('click', e => {
if (e.target === e.currentTarget) cerrarModal();
});
// ─── Pilotos ───────────────────────────────────────────────────
async function cargarPilotos() {
const res = await fetch(`${API}/pilotos`);
const pilotos = await res.json();
const tbody = document.querySelector('#pilotos-table tbody');
tbody.innerHTML = '';
pilotos.forEach(p => {
const tr = document.createElement('tr');
tr.innerHTML = `
${p.numero} |
${p.codigo} |
${p.nombre} |
${p.apellido} |
— |
${p.nacionalidad} |
`;
tbody.appendChild(tr);
});
}
// ─── Escuderías ───────────────────────────────────────────────
async function cargarEscuderias() {
const res = await fetch(`${API}/escuderias`);
const data = await res.json();
const tbody = document.querySelector('#escuderias-table tbody');
tbody.innerHTML = '';
data.forEach((e, i) => {
const tr = document.createElement('tr');
tr.innerHTML = `${i + 1} | ${e.nombre} | ${e.pais} | ${e.motor} | `;
tbody.appendChild(tr);
});
}
// ─── INIT ──────────────────────────────────────────────────────
async function init() {
initCuentaAtras();
const [clasificPilotos, clasificConst, gps] = await Promise.all([
cargarClasificacionPilotos(),
cargarClasificacionConstructores(),
cargarCalendario()
]);
renderClasificacionPilotos(clasificPilotos, 'tabla-top-pilotos', 5);
renderClasificacionConstructores(clasificConst, 'tabla-top-constructores', 5);
renderUltimasCarreras(gps);
renderClasificacionPilotos(clasificPilotos, 'tabla-clasificacion-pilotos');
renderClasificacionConstructores(clasificConst, 'tabla-clasificacion-constructores');
renderCalendario(gps);
cargarPilotos();
cargarEscuderias();
}
document.addEventListener('DOMContentLoaded', init);