// Home screen — greeting, streak, latest materials, subjects grid.
function Home({ onOpenMaterial, onNav }) {
const { MATERIALS, SUBJECTS, LEVELS } = window.ECC_DATA;
const latest = MATERIALS.slice(0, 4);
return (
{/* INTRO */}
Apuntes y ejercicios · Matemáticas 4º ESO
Apuntes y ejercicios de la ESO, para estudiar en casa.
Explicaciones claras y actividades que se corrigen solas, organizadas por unidades. Una ayuda para que padres e hijos repasen juntos y lleven el curso al día.
{[
{ icon: 'lock', text: 'Gratis y sin registro' },
{ icon: 'check', text: 'Se corrige solo, al instante' },
{ icon: 'book', text: 'Explicado paso a paso' },
].map(t => (
{t.text}
))}
{/* LATEST */}
onNav('library') }} />
{latest.map(m => onOpenMaterial(m.id)} />)}
{/* COURSES */}
{LEVELS.length > 1 && (
{LEVELS.map(lv => {
const count = MATERIALS.filter(m => m.level === lv.id).length;
return (
onNav('library', { level: lv.id })} style={{
background: 'var(--bg-surface)',
border: '1px solid var(--line)',
borderRadius: 'var(--r-lg)',
padding: '18px 20px',
textAlign: 'left',
cursor: 'pointer',
transition: 'all var(--t-fast) var(--ease)',
display: 'flex', alignItems: 'center', gap: 14,
}}
onMouseEnter={e => { e.currentTarget.style.borderColor = 'var(--ink-3)'; e.currentTarget.style.boxShadow = 'var(--shadow-hover)'; }}
onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--line)'; e.currentTarget.style.boxShadow = 'none'; }}>
{lv.id === '4eso' ? '4º' : '3º'}
{lv.label}
{count} {count === 1 ? 'material' : 'materiales'}
);
})}
)}
{/* SUBJECTS */}
{SUBJECTS.filter(s => MATERIALS.some(m => m.subject === s.id)).map(s => {
const count = MATERIALS.filter(m => m.subject === s.id).length;
return (
onNav('library', { subject: s.id })} style={{
background: 'var(--bg-surface)',
border: '1px solid var(--line)',
borderLeft: `4px solid ${s.color}`,
borderRadius: 'var(--r-lg)',
padding: '16px 18px',
textAlign: 'left',
cursor: 'pointer',
transition: 'all var(--t-fast) var(--ease)',
display: 'flex', flexDirection: 'column', gap: 4,
}}
onMouseEnter={e => { e.currentTarget.style.borderColor = 'var(--ink-3)'; e.currentTarget.style.borderLeftColor = s.color; e.currentTarget.style.boxShadow = 'var(--shadow-hover)'; }}
onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--line)'; e.currentTarget.style.borderLeftColor = s.color; e.currentTarget.style.boxShadow = 'none'; }}>
{s.label}
{count} {count === 1 ? 'material' : 'materiales'}
);
})}
{/* HOW IT WORKS */}
);
}
function SectionHeader({ title, action }) {
return (
{title}
{action && (
{action.label}
)}
);
}
function StreakCard() {
const dots = [1,1,1,1,1,1,1,0,0,0];
return (
{dots.map((on, i) => (
))}
¡Sigue así! 3 días más para tu próximo logro.
);
}
function MaterialCard({ m, onClick }) {
const { SUBJECTS, KINDS } = window.ECC_DATA;
const s = SUBJECTS.find(x => x.id === m.subject);
const k = KINDS[m.kind];
const cardProps = m.href
? { as: 'a', href: m.href }
: { as: 'article', onClick };
const sharedStyle = {
background: 'var(--bg-surface)',
border: '1px solid var(--line)',
borderRadius: 'var(--r-lg)',
padding: '18px 20px',
display: 'flex', flexDirection: 'column', gap: 8,
cursor: 'pointer',
transition: 'all var(--t-fast) var(--ease)',
textDecoration: 'none',
color: 'inherit',
};
const inner = (
<>
{m.status === 'new' && nuevo }
{m.title}
{m.desc}
{k.label}
{m.pages && <>· {m.pages} págs >}
{m.time && <>· {m.time} >}
·
{m.updated}
>
);
const hoverHandlers = {
onMouseEnter: e => { e.currentTarget.style.borderColor = 'var(--ink-3)'; e.currentTarget.style.boxShadow = 'var(--shadow-hover)'; },
onMouseLeave: e => { e.currentTarget.style.borderColor = 'var(--line)'; e.currentTarget.style.boxShadow = 'none'; },
};
if (m.href) {
const isPdf = /\.pdf$/i.test(m.href);
return (
{inner}
);
}
return (
{inner}
);
}
function ContinueRow({ material: m, onClick }) {
if (!m) return null;
const progress = m.progress || 0.25;
return (
{ e.currentTarget.style.borderColor = 'var(--ink-3)'; e.currentTarget.style.boxShadow = 'var(--shadow-hover)'; }}
onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--line)'; e.currentTarget.style.boxShadow = 'none'; }}>
{m.chapter}
{m.title}
{Math.round(progress * 100)}% completado · 3 de 12 ejercicios
);
}
Object.assign(window, { Home, MaterialCard, SectionHeader });
function HowItem({ icon, title, desc }) {
return (
);
}