// Interactive calendar + partidos results const { useState, useMemo, useEffect: useEffectCal } = React; const DEFAULT_MATCHES = [ { date: "2026-04-26", time: "10:30", cat: "Sub-11", opp: "Náutico Puerto", home: true, venue: "Cancha Norte FCPB", status: "próximo" }, { date: "2026-04-26", time: "12:00", cat: "Sub-9", opp: "Liniers FC", home: true, venue: "Cancha Norte FCPB", status: "próximo" }, { date: "2026-04-27", time: "09:30", cat: "Sub-13", opp: "Dársena Sur", home: false, venue: "Club Dársena Sur", status: "próximo" }, { date: "2026-05-03", time: "10:30", cat: "Sub-15", opp: "Argentino Oeste", home: true, venue: "Cancha Norte FCPB", status: "próximo" }, { date: "2026-05-03", time: "15:00", cat: "Sub-17", opp: "Tiro Federal", home: false, venue: "Predio Tiro Federal", status: "próximo" }, { date: "2026-05-10", time: "11:00", cat: "Sub-7", opp: "Festival de Escuelas", home: true, venue: "Cancha Norte FCPB", status: "próximo" }, { date: "2026-05-10", time: "10:30", cat: "Sub-11", opp: "Bahía Blanca FC", home: false, venue: "Estadio Bahía", status: "próximo" }, // results { date: "2026-04-19", time: "10:30", cat: "Sub-11", opp: "Puerto Nuevo", home: true, result: { us: 3, them: 1 }, status: "finalizado" }, { date: "2026-04-19", time: "12:00", cat: "Sub-9", opp: "La Pampa", home: false, result: { us: 4, them: 2 }, status: "finalizado" }, { date: "2026-04-12", time: "10:00", cat: "Sub-13", opp: "River B.B.", home: true, result: { us: 2, them: 2 }, status: "finalizado" }, ]; const MONTHS_ES = ["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"]; const DAYS_ES = ["Lun","Mar","Mié","Jue","Vie","Sáb","Dom"]; function Calendario() { const [cursor, setCursor] = useState(new Date(2026, 3, 1)); // April 2026 const [selected, setSelected] = useState("2026-04-26"); const [filter, setFilter] = useState("Todas"); const [catsFiltro, setCatsFiltro] = useState(["Todas"].concat(window.FCPB_CATS_DEFAULT || [])); const [matches, setMatches] = useState(DEFAULT_MATCHES); useEffectCal(() => { if (window.fcpbCats) window.fcpbCats().then((n) => setCatsFiltro(["Todas"].concat(n))); // Partidos en vivo desde el panel de administración fetch("api/partidos.php", { headers: { Accept: "application/json" } }) .then((r) => (r.ok ? r.json() : Promise.reject())) .then((j) => { if (!j || !j.ok || !Array.isArray(j.partidos) || !j.partidos.length) return; const ms = j.partidos.map((p) => ({ date: p.fecha, time: p.hora || "—", cat: p.categoria || "FCPB", opp: p.rival, home: !!p.es_local, venue: p.sede || "", status: p.estado === "finalizado" ? "finalizado" : "próximo", result: p.estado === "finalizado" && p.goles_nos != null ? { us: p.goles_nos, them: p.goles_rival } : undefined, })); setMatches(ms); // Posicionar el calendario en el próximo partido (o el último jugado) const hoy = new Date(); const hoyKey = `${hoy.getFullYear()}-${String(hoy.getMonth() + 1).padStart(2, "0")}-${String(hoy.getDate()).padStart(2, "0")}`; const prox = ms.filter((m) => m.date >= hoyKey).sort((a, b) => a.date.localeCompare(b.date))[0] || ms[ms.length - 1]; if (prox) { setCursor(new Date(prox.date + "T12:00")); setSelected(prox.date); } }) .catch(() => {}); }, []); const year = cursor.getFullYear(); const month = cursor.getMonth(); const firstDay = new Date(year, month, 1); const startWeekday = (firstDay.getDay() + 6) % 7; // Mon=0 const daysInMonth = new Date(year, month + 1, 0).getDate(); const matchMap = useMemo(() => { const m = {}; matches.forEach(x => { if (filter !== "Todas" && x.cat !== filter) return; (m[x.date] = m[x.date] || []).push(x); }); return m; }, [filter, matches]); const pad = (n) => String(n).padStart(2, '0'); const dateKey = (d) => `${year}-${pad(month+1)}-${pad(d)}`; const selectedMatches = (matchMap[selected] || []).slice().sort((a,b) => a.time.localeCompare(b.time)); const cells = []; for (let i = 0; i < startWeekday; i++) cells.push(null); for (let d = 1; d <= daysInMonth; d++) cells.push(d); while (cells.length % 7 !== 0) cells.push(null); return (
03 · Partidos

Calendario
y resultados.

{catsFiltro.map(f => ( ))}
{MONTHS_ES[month]} {year}
{DAYS_ES.map(d =>
{d}
)}
{cells.map((d, i) => { if (d === null) return
; const key = dateKey(d); const has = matchMap[key]; const sel = selected === key; return ( ); })}
Día con partido Día seleccionado
Agenda
{new Date(selected + "T12:00").toLocaleDateString("es-AR", { weekday: "long", day: "numeric", month: "long" })}
{selectedMatches.length === 0 ? (
Sin partidos programados este día. ¡Aprovechá para entrenar!
) : (
{selectedMatches.map((m, i) => (
{m.time}
{m.cat}
{m.home ? "FCPB" : m.opp} vs {m.home ? m.opp : "FCPB"}