From 803e68970cdc21ef75624e8f8043d167b1d85b8b Mon Sep 17 00:00:00 2001 From: Tudor Date: Sun, 2 Aug 2026 21:54:59 +0100 Subject: [PATCH] refactor(detail): drop dead derived state from the shell Leftover from the mechanical extraction: the shell still called computeSchoolFlags() and derived isReportCard / ofstedInspectedDate / oeifAreas / oeifAllSameGrade / deprivationDesc / primaryAvg / secondaryAvg on every render, duplicating work page.tsx already does. None of those values were referenced in its JSX anymore -- that logic moved to the section composers. The chrome needs only four locally-derived values (latestResults, phase, isAllThrough, hasLocation), all one-liners over props it already owns. Removing them made seven props dead, which TypeScript caught at both call sites: absenceData, ofsted, admissions, admissionsHistory, deprivation, finance and nationalAvg now go straight to the section composers and never reach the client component. The shell's surface is down to schoolInfo, yearlyData, census, navItems and children. No behaviour change: 155 tests pass and the characterization tests remain byte-identical to the commit that introduced them. Co-Authored-By: Claude Opus 5 --- .../__tests__/support/renderSchoolDetail.tsx | 10 ++- nextjs-app/app/school/[slug]/page.tsx | 14 ---- .../components/school/SchoolDetailShell.tsx | 84 ++++--------------- 3 files changed, 23 insertions(+), 85 deletions(-) diff --git a/nextjs-app/__tests__/support/renderSchoolDetail.tsx b/nextjs-app/__tests__/support/renderSchoolDetail.tsx index f8ca675..72deca2 100644 --- a/nextjs-app/__tests__/support/renderSchoolDetail.tsx +++ b/nextjs-app/__tests__/support/renderSchoolDetail.tsx @@ -37,8 +37,9 @@ export function renderSchoolDetail(fixture: any) { return render( withProviders( window.removeEventListener('keydown', onKey); }, [sectionsOpen]); - // Derived data-shape logic lives in lib/schoolSections so the server route - // can compute the section list without importing this client component. - const flags = computeSchoolFlags({ - schoolInfo, yearlyData, absenceData, census, deprivation, finance, - }); - const { - latestResults, isAllThrough, isSecondary, isPrimary, - hasGenderSplit, hasInclusionData, hasSchoolLife, hasDeprivation, - hasFinance, hasLocation, hasKS2Results, hasKS4Results, hasAnyResults, - isSpecial, ks2Placeholder, suppressKs2Comparison, suppressKs4Comparison, - } = flags; + // The chrome needs only these four. The section-shape flags are computed + // once on the server (lib/schoolSections) and consumed by the section + // composers; recomputing them here would duplicate that work for values + // this component never renders. + const latestResults = yearlyData.length > 0 ? yearlyData[yearlyData.length - 1] : null; const phase = schoolInfo.phase ?? ''; - - const primaryAvg = nationalAvg?.primary ?? {}; - const secondaryAvg = nationalAvg?.secondary ?? {}; + const isAllThrough = phase.toLowerCase() === 'all-through'; + const hasLocation = schoolInfo.latitude != null && schoolInfo.longitude != null; const handleComparisonToggle = () => { if (isInComparison) { @@ -172,13 +152,6 @@ export function SchoolDetailShell({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [schoolInfo.urn]); - const deprivationDesc = (decile: number) => { - if (decile <= 3) return `This school is in one of England's most deprived areas (decile ${decile}/10). Many pupils may face additional challenges at home.`; - if (decile <= 7) return `This school is in an area with average levels of deprivation (decile ${decile}/10).`; - return `This school is in one of England's less deprived areas (decile ${decile}/10).`; - }; - - // Track active section as user scrolls useEffect(() => { const ids = navItems.map(n => n.id); @@ -211,29 +184,6 @@ export function SchoolDetailShell({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [navItems.map(n => n.id).join(',')]); - // A report card is identified by the presence of report-card area - // judgements, NOT by `framework` — the API sets `framework` to the raw - // event grouping (e.g. "Schools - S5") even for report-card schools, so - // the old `framework === 'ReportCard'` test never matched and report cards - // were rendered as legacy ratings dated to a pre-Nov-2025 inspection. - const isReportCard = !!( - ofsted?.report_card && Object.keys(ofsted.report_card).length > 0 - ); - // A report card is dated by its own inspection (rc_inspection_date); the - // legacy inspection_date belongs to an older inspection and must never - // date a report card (report cards exist only from Nov 2025). - const ofstedInspectedDate = isReportCard - ? ofsted?.rc_inspection_date ?? null - : ofsted?.inspection_date ?? null; - - // ── Ofsted: detect if all OEIF sub-grades match the overall ─────────── - const oeifAreas = ofsted ? ofstedLegacyAreas(ofsted) : []; - const oeifAllSameGrade = - !!ofsted && - !isReportCard && - oeifAreas.length >= 3 && - oeifAreas.every((a) => a.value === ofsted.overall_effectiveness); - // Label shown in the mobile "section" menu button — the section in view. const activeNavLabel = (navItems.find((n) => n.id === activeSection) ?? navItems[0])?.label ?? '';