Compare commits
2
Commits
ec2d12478e
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f961bf7f4 | ||
|
|
803e68970c |
@@ -37,8 +37,9 @@ export function renderSchoolDetail(fixture: any) {
|
||||
return render(
|
||||
withProviders(
|
||||
<SchoolDetailShell
|
||||
{...fixture}
|
||||
nationalAvg={nationalAveragesFixture}
|
||||
schoolInfo={fixture.schoolInfo}
|
||||
yearlyData={fixture.yearlyData}
|
||||
census={fixture.census}
|
||||
navItems={navItems}
|
||||
>
|
||||
<PrimarySchoolSections
|
||||
@@ -62,8 +63,9 @@ export function renderSecondarySchoolDetail(fixture: any) {
|
||||
return render(
|
||||
withProviders(
|
||||
<SchoolDetailShell
|
||||
{...fixture}
|
||||
nationalAvg={nationalAveragesFixture}
|
||||
schoolInfo={fixture.schoolInfo}
|
||||
yearlyData={fixture.yearlyData}
|
||||
census={fixture.census}
|
||||
navItems={navItems}
|
||||
>
|
||||
<SecondarySchoolSections
|
||||
|
||||
@@ -218,14 +218,7 @@ export default async function SchoolPage({ params }: SchoolPageProps) {
|
||||
<SchoolDetailShell
|
||||
schoolInfo={school_info}
|
||||
yearlyData={yearly_data}
|
||||
absenceData={absence_data}
|
||||
ofsted={ofsted ?? null}
|
||||
census={census ?? null}
|
||||
admissions={admissions ?? null}
|
||||
admissionsHistory={admissions_history ?? []}
|
||||
deprivation={deprivation ?? null}
|
||||
finance={finance ?? null}
|
||||
nationalAvg={nationalAvg}
|
||||
navItems={secondaryNavItems}
|
||||
>
|
||||
<SecondarySchoolSections
|
||||
@@ -245,14 +238,7 @@ export default async function SchoolPage({ params }: SchoolPageProps) {
|
||||
<SchoolDetailShell
|
||||
schoolInfo={school_info}
|
||||
yearlyData={yearly_data}
|
||||
absenceData={absence_data}
|
||||
ofsted={ofsted ?? null}
|
||||
census={census ?? null}
|
||||
admissions={admissions ?? null}
|
||||
admissionsHistory={admissions_history ?? []}
|
||||
deprivation={deprivation ?? null}
|
||||
finance={finance ?? null}
|
||||
nationalAvg={nationalAvg}
|
||||
navItems={primaryNavItems}
|
||||
>
|
||||
<PrimarySchoolSections
|
||||
|
||||
@@ -20,34 +20,23 @@ import { useEffect, useRef, useState, type ReactNode } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useComparison } from '@/hooks/useComparison';
|
||||
import { SchoolHeroMap, type SchoolHeroMapHandle } from '../SchoolHeroMap';
|
||||
import type {
|
||||
School, SchoolResult, AbsenceData,
|
||||
OfstedInspection, SchoolCensus,
|
||||
SchoolAdmissions,
|
||||
SchoolDeprivation, SchoolFinance, NationalAverages,
|
||||
} from '@/lib/types';
|
||||
import {
|
||||
formatPercentage, formatProgress, formatAcademicYear, formatAgeRange, isProposedToClose, ofstedLegacyAreas,
|
||||
} from '@/lib/utils';
|
||||
import { computeSchoolFlags, type NavItem } from '@/lib/schoolSections';
|
||||
|
||||
import type { School, SchoolResult, SchoolCensus } from '@/lib/types';
|
||||
import { formatAgeRange, isProposedToClose } from '@/lib/utils';
|
||||
import type { NavItem } from '@/lib/schoolSections';
|
||||
import { track, getNavigationSource } from '@/lib/analytics';
|
||||
import styles from './SchoolDetailShell.module.css';
|
||||
|
||||
|
||||
/**
|
||||
* Only what the chrome itself renders. Everything the sections need — Ofsted,
|
||||
* admissions, deprivation, finance, national averages — goes straight to the
|
||||
* section composers in page.tsx and never reaches the client.
|
||||
*/
|
||||
export interface SchoolDetailShellProps {
|
||||
schoolInfo: School;
|
||||
/** Only for the header's pupil-count fallback. */
|
||||
yearlyData: SchoolResult[];
|
||||
absenceData: AbsenceData | null;
|
||||
ofsted: OfstedInspection | null;
|
||||
census: SchoolCensus | null;
|
||||
admissions: SchoolAdmissions | null;
|
||||
admissionsHistory: SchoolAdmissions[];
|
||||
deprivation: SchoolDeprivation | null;
|
||||
finance: SchoolFinance | null;
|
||||
/** Fetched on the server so the England-comparison deltas are in the
|
||||
* initial HTML; null when the endpoint is unavailable. */
|
||||
nationalAvg: NationalAverages | null;
|
||||
/** Section list for the sticky nav, computed on the server. */
|
||||
navItems: NavItem[];
|
||||
/** The server-rendered sections. */
|
||||
@@ -55,9 +44,7 @@ export interface SchoolDetailShellProps {
|
||||
}
|
||||
|
||||
export function SchoolDetailShell({
|
||||
schoolInfo, yearlyData, absenceData,
|
||||
ofsted, census, admissions, admissionsHistory, deprivation, finance,
|
||||
nationalAvg, navItems, children,
|
||||
schoolInfo, yearlyData, census, navItems, children,
|
||||
}: SchoolDetailShellProps) {
|
||||
const router = useRouter();
|
||||
const { addSchool, removeSchool, isSelected } = useComparison();
|
||||
@@ -135,21 +122,14 @@ export function SchoolDetailShell({
|
||||
return () => 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 ?? '';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user