// Pro Dashboard v2 — Team Development Focus function ProDashboard({ onNavigate, onPlayerSelect }) { const { team, games, players, upcomingEvents } = window.TData; const { physicalData, tasks, completions, computeDevScore } = window.TDataExt; const lastGame = games[games.length-1]; const avgPts = (games.reduce((s,g)=>s+g.scoreUs,0)/games.length).toFixed(1); const teamAtt = Math.round(players.reduce((s,p)=>s+p.attendancePct,0)/players.length); const teamTaskPct = Math.round(players.reduce((s,p)=>{ const done = tasks.filter(t=>completions[p.id]?.[t.id]).length; return s + (tasks.length ? done/tasks.length*100 : 0); },0)/players.length); // Dev scores const devScores = players.map(p=>({...p, dev: computeDevScore(p.id)})); const topDev = [...devScores].sort((a,b)=>b.dev-a.dev).slice(0,5); const needsAtt = [...devScores].sort((a,b)=>a.dev-b.dev).filter(p=>p.dev<60).slice(0,4); const teamDevAvg = Math.round(devScores.reduce((s,p)=>s+p.dev,0)/players.length); // Physical team trend (sprint avg across evals) const evalDates = window.TDataExt.evalDates; const sprintByEval = evalDates.map((_,ei)=> +(players.reduce((s,p)=>{ const d = physicalData[p.id]; return s + (d&&d[ei] ? d[ei].sprint : 3.35); },0)/players.length).toFixed(2) ); const saltoByEval = evalDates.map((_,ei)=> +(players.reduce((s,p)=>{ const d = physicalData[p.id]; return s + (d&&d[ei] ? d[ei].salto : 38); },0)/players.length).toFixed(1) ); // Game score trend const scoreTrend = games.map(g=>g.scoreUs); const gameLabels = games.map(g=>g.rival.slice(0,4)); // Most improved (sprint delta) const mostImproved = [...players].map(p=>{ const d = physicalData[p.id]; const sprintDelta = d ? +(d[0].sprint - d[d.length-1].sprint).toFixed(2) : 0; return {...p, sprintDelta}; }).sort((a,b)=>b.sprintDelta-a.sprintDelta).slice(0,3); const devColor = v => v>=80?T.green:v>=60?T.yellow:T.red; return (
{/* Header */}

Panel de Desarrollo

Visión integral del equipo · Temporada 2025–26

Récord
{team.wins}–{team.losses}
{/* KPI row */}
{[ {l:"Índice de Desarrollo", v:`${teamDevAvg}`, c:devColor(teamDevAvg), sub:"/100 promedio"}, {l:"Asistencia a Entrenos", v:`${teamAtt}%`, c:teamAtt>=80?T.green:T.yellow, sub:"promedio equipo"}, {l:"Tareas Completadas", v:`${teamTaskPct}%`, c:teamTaskPct>=70?T.green:T.yellow, sub:"cumplimiento"}, {l:"Pts Promedio", v:avgPts, c:T.accent, sub:"por partido"}, {l:"Racha", v:team.streak, c:T.green, sub:"victorias consecutivas"}, {l:"Sprint Equipo", v:`${sprintByEval[sprintByEval.length-1]}"`, c:T.text, sub:"↓ mejorando"}, ].map(s=>)}
{/* Row 2: development chart + alerts */}
{/* Rendimiento en cancha */} onNavigate("partidos")} /> {/* Físico: velocidad */} onNavigate("fisico")} /> d.slice(5))} color={T.green} height={130} />

Segundos — menor es mejor

{/* Alerts */} {needsAtt.length === 0 ? (
Todo el equipo bien
) : needsAtt.map(p=>(
{p.name}
Asist. {p.attendancePct}% · Dev. {p.dev}/100
{p.dev}
))}
{/* Row 3: dev rankings + tasks + physical + upcoming */}
{/* Top development */} onNavigate("jugadoras")} />
{topDev.map((p,i)=>{ const dc = devColor(p.dev); return (
onPlayerSelect(p)} style={{ display:"flex",alignItems:"center",gap:10,padding:"9px 10px", borderRadius:6,cursor:"pointer",transition:"background 0.1s" }} onMouseEnter={e=>e.currentTarget.style.background=T.stripe} onMouseLeave={e=>e.currentTarget.style.background=""} > {i+1}
{p.name}
{p.dev}/100
); })}
{/* Most improved physically */} onNavigate("fisico")} />
{mostImproved.map((p,i)=>(
onPlayerSelect(p)} style={{ display:"flex",alignItems:"center",gap:12,padding:"9px 10px", borderRadius:6,cursor:"pointer",transition:"background 0.1s" }} onMouseEnter={e=>e.currentTarget.style.background=T.stripe} onMouseLeave={e=>e.currentTarget.style.background=""} > {i+1}
{p.name}
Sprint mejora
−{p.sprintDelta}"
))}
Salto vertical equipo d.slice(5))} color={T.accent} height={80} />
{/* Tasks + next event */}
onNavigate("tareas")} /> {tasks.slice(0,3).map(t=>{ const done = players.filter(p=>completions[p.id]?.[t.id]).length; const pct = Math.round(done/players.length*100); const catColor = {Técnica:T.accent,Físico:T.red,Táctica:"#7c3aed",Recuperación:T.green}[t.category]||T.accent; return (
{t.title} =75?T.green:pct>=50?T.yellow:T.red}}>{pct}%
=75?T.green:pct>=50?T.yellow:T.red} height={4} />
); })}
onNavigate("agenda")} /> {upcomingEvents.slice(0,3).map(ev=>(
{ev.type==="partido"?`vs ${ev.rival}`:ev.title}
{ev.date} · {ev.time}
))}
); } window.ProDashboard = ProDashboard;