// 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);