diff --git a/nextjs-app/components/SchoolDetailView.tsx b/nextjs-app/components/SchoolDetailView.tsx index e8bc83b..99782dd 100644 --- a/nextjs-app/components/SchoolDetailView.tsx +++ b/nextjs-app/components/SchoolDetailView.tsx @@ -82,42 +82,6 @@ export function SchoolDetailView({ const isSecondary = phase.toLowerCase().includes('secondary') || phase.toLowerCase() === 'all-through'; const isPrimary = !isSecondary; - // Track active section as user scrolls - useEffect(() => { - const ids = navItems.map(n => n.id); - if (!ids.length) return; - - const observers: IntersectionObserver[] = []; - - // We keep a map of how much each section is visible so we can pick the - // most-visible one when multiple overlap the viewport. - const ratioMap: Record = {}; - - const pickActive = () => { - const top = Object.entries(ratioMap).sort((a, b) => b[1] - a[1])[0]; - setActiveSection(top?.[1] > 0 ? top[0] : ''); - }; - - ids.forEach(id => { - const el = document.getElementById(id); - if (!el) return; - ratioMap[id] = 0; - const obs = new IntersectionObserver( - ([entry]) => { - ratioMap[id] = entry.intersectionRatio; - pickActive(); - }, - { threshold: [0, 0.1, 0.25, 0.5, 0.75, 1.0], rootMargin: '-56px 0px 0px 0px' }, - ); - obs.observe(el); - observers.push(obs); - }); - - return () => observers.forEach(o => o.disconnect()); - // navItems identity is stable per render — eslint-disable is intentional - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [navItems.map(n => n.id).join(',')]); - // National averages (fetched dynamically so they stay current) const [nationalAvg, setNationalAvg] = useState(null); useEffect(() => { @@ -176,6 +140,38 @@ export function SchoolDetailView({ if (hasFinance) navItems.push({ id: 'finances', label: 'Finances' }); if (yearlyData.length > 0) navItems.push({ id: 'history', label: 'History' }); + // Track active section as user scrolls + useEffect(() => { + const ids = navItems.map(n => n.id); + if (!ids.length) return; + + const observers: IntersectionObserver[] = []; + const ratioMap: Record = {}; + + const pickActive = () => { + const top = Object.entries(ratioMap).sort((a, b) => b[1] - a[1])[0]; + setActiveSection(top?.[1] > 0 ? top[0] : ''); + }; + + ids.forEach(id => { + const el = document.getElementById(id); + if (!el) return; + ratioMap[id] = 0; + const obs = new IntersectionObserver( + ([entry]) => { + ratioMap[id] = entry.intersectionRatio; + pickActive(); + }, + { threshold: [0, 0.1, 0.25, 0.5, 0.75, 1.0], rootMargin: '-56px 0px 0px 0px' }, + ); + obs.observe(el); + observers.push(obs); + }); + + return () => observers.forEach(o => o.disconnect()); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [navItems.map(n => n.id).join(',')]); + // ── Ofsted: detect if all OEIF sub-grades match the overall ─────────── const oeifAllSameGrade = (() => { if (!ofsted || ofsted.framework === 'ReportCard') return false;