// components/Dashboard.jsx
const { useMemo: useMemoD } = React;
function Dashboard({ stickers, onNavigate }) {
const { ALL_STICKERS, TEAMS, teamStickers, flagUrl } = ALBUM_DATA;
const stats = useMemoD(() => {
let tengo = 0, repetidas = 0, faltan = 0;
ALL_STICKERS.forEach(s => {
const q = stickers[s.id] || 0;
if (q >= 1) tengo++;
if (q >= 2) repetidas += (q - 1);
if (q === 0) faltan++;
});
return { tengo, repetidas, faltan, total: ALL_STICKERS.length, pct: Math.round(tengo / ALL_STICKERS.length * 100) };
}, [stickers]);
const teamProgress = useMemoD(() =>
TEAMS.map(t => {
const sl = teamStickers[t.id] || [];
const owned = sl.filter(s => (stickers[s.id]||0) >= 1).length;
const dups = sl.reduce((a,s) => a + Math.max(0,(stickers[s.id]||0)-1), 0);
return { ...t, owned, dups, total: sl.length, pct: Math.round(owned/sl.length*100) };
}).sort((a,b) => b.pct - a.pct)
, [stickers]);
const nearComplete = teamProgress.filter(t => t.pct >= 50 && t.pct < 100).slice(0,4);
const topTeams = teamProgress.slice(0, 6);
return (
Mi Colección
{/* Progress bar */}
Progreso del álbum
{stats.pct}%
{stats.tengo} de {stats.total} láminas
{/* Stats */}
{nearComplete.length > 0 && (
⚡ Casi completos
{nearComplete.map(t => (
))}
)}
🏅 Equipos más completos
{topTeams.map(t => (
))}
{stats.tengo === 0 && (
📖
¡Empieza marcando tus láminas en el álbum!
)}
);
}
function StatCard({ label, value, sub, color, icon }) {
return (
{icon}
{value}
{label}
{sub}
);
}
const dCSS = {
page: { padding:'28px 24px', maxWidth:900, margin:'0 auto' },
heading: { fontSize:22, fontWeight:700, color:'var(--text)', marginBottom:20 },
progressCard:{ background:'var(--surface)', borderRadius:14, padding:'20px 24px', marginBottom:20, border:'1px solid var(--border)' },
pRow: { display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:10 },
pLabel: { color:'var(--text-muted)', fontSize:13, fontWeight:600, textTransform:'uppercase', letterSpacing:'0.06em' },
pPct: { fontSize:22, fontWeight:800 },
bar: { height:10, background:'var(--border)', borderRadius:99, overflow:'hidden' },
barFill: { height:'100%', background:'linear-gradient(90deg, var(--green), #00d46a)', borderRadius:99, transition:'width .6s ease' },
pSub: { color:'var(--text-dim)', fontSize:12, marginTop:8 },
grid3: { display:'grid', gridTemplateColumns:'repeat(3,1fr)', gap:14, marginBottom:28 },
statCard: { background:'var(--surface)', borderRadius:12, padding:'18px 16px', border:'1px solid var(--border)', textAlign:'center' },
secTitle: { fontSize:12, fontWeight:700, color:'var(--text-muted)', marginBottom:12, textTransform:'uppercase', letterSpacing:'0.07em' },
grid2: { display:'grid', gridTemplateColumns:'repeat(2,1fr)', gap:10, marginBottom:28 },
teamCard: { display:'flex', alignItems:'center', gap:12, background:'var(--surface)', border:'1px solid var(--border)', borderRadius:12, padding:'14px 16px', cursor:'pointer', textAlign:'left' },
teamName: { color:'var(--text)', fontSize:14, fontWeight:600, marginBottom:6 },
miniBarWrap:{ height:4, background:'var(--border)', borderRadius:99, overflow:'hidden' },
miniBarFill:{ height:'100%', background:'var(--green)', borderRadius:99, transition:'width .4s' },
grid3col: { display:'grid', gridTemplateColumns:'repeat(3,1fr)', gap:10, marginBottom:28 },
topCard: { background:'var(--surface)', border:'1px solid var(--border)', borderRadius:12, padding:'16px 14px', cursor:'pointer', textAlign:'center' },
topName: { color:'var(--text)', fontSize:12, fontWeight:600, marginBottom:4, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' },
topCount: { color:'var(--text-dim)', fontSize:11, marginBottom:6 },
empty: { textAlign:'center', padding:'40px 20px' },
startBtn: { marginTop:16, padding:'10px 24px', background:'var(--green)', border:'none', borderRadius:8, color:'#fff', fontWeight:700, fontSize:14, cursor:'pointer' },
};
Object.assign(window, { Dashboard, StatCard });