From de943ded19b170cd26c8d0008460222bc27670c7 Mon Sep 17 00:00:00 2001 From: Tudor Date: Mon, 20 Jul 2026 21:58:13 +0100 Subject: [PATCH] fix(review): don't suppress a genuine mainstream 0 in the rows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review feedback: the rankings/search rows treated any exactly-0 attainment as not comparable regardless of school type, so a genuine 0 at a mainstream school rendered as "—" (looks like missing data) and dropped its delta — stricter and inconsistent with SchoolDetailView's placeholder check. - SchoolRow: match SchoolDetailView's ks2Placeholder signature — suppress only when ALL of RWM + reading + writing + maths are 0 (special/suppressed signature), not on a bare rwm === 0. A genuine 0% combined (some pupils met individual subjects but not all three) is not all-zero, so it stays comparable and shows its real figure + trend. - SecondarySchoolRow: Attainment 8 is a single 0–80 score with no subject breakdown to form an all-zero signature, so key off establishment type only (drop the bare att8 === 0 guard). A genuine (if extreme) 0.0 shows its value + LA delta. - For consistency, apply the same to the detail views: drop the bare attainment_8_score === 0 guard (KS4 keys off isSpecial only); KS2 keeps the all-four-subjects-zero placeholder signature. Special schools / PRUs / AP are still handled via isSpecialSchool everywhere. tsc clean; 108/108 unit. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_0146VHeLAWjDVE2B5uU67jCB --- nextjs-app/components/SchoolDetailView.tsx | 13 ++++++++----- nextjs-app/components/SchoolRow.tsx | 16 +++++++++++----- .../components/SecondarySchoolDetailView.tsx | 8 +++++--- nextjs-app/components/SecondarySchoolRow.tsx | 7 +++++-- 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/nextjs-app/components/SchoolDetailView.tsx b/nextjs-app/components/SchoolDetailView.tsx index be5f501..99f7788 100644 --- a/nextjs-app/components/SchoolDetailView.tsx +++ b/nextjs-app/components/SchoolDetailView.tsx @@ -237,19 +237,22 @@ export function SchoolDetailView({ // reach the mainstream "expected standard", so a 0% headline and an England // comparison portray them as failing against a benchmark that doesn't fit. const isSpecial = isSpecialSchool(schoolInfo); - // Belt-and-braces: a whole-row zero attainment (special or suppressed cohort) - // is a placeholder, not a real mainstream result — suppress its comparison - // too. A single 0 (e.g. 0% exceeding at a normal school) stays comparable. + // Belt-and-braces for KS2: a whole-row zero attainment (every subject 0 — a + // special/suppressed signature) is a placeholder, not a real result. This + // needs ALL of RWM + reading + writing + maths to be 0, so a genuine 0% + // combined (some pupils met individual subjects but not all three) stays + // comparable. Attainment 8 is a single 0–80 score with no subject breakdown + // to form such a signature, so KS4 keys off establishment type only — a + // genuine (if extreme) 0.0 still shows its real figure and comparison. const ks2Placeholder = latestResults != null && latestResults.rwm_expected_pct === 0 && (latestResults.reading_expected_pct ?? 0) === 0 && (latestResults.writing_expected_pct ?? 0) === 0 && (latestResults.maths_expected_pct ?? 0) === 0; - const ks4Placeholder = latestResults != null && latestResults.attainment_8_score === 0; // Whether to drop the England-average deltas / national markers / "below" // framing on the attainment measures. const suppressKs2Comparison = isSpecial || ks2Placeholder; - const suppressKs4Comparison = isSpecial || ks4Placeholder; + const suppressKs4Comparison = isSpecial; // Build section nav items dynamically — only sections with data. // Order is engagement-led (from section_nav_used analytics): the most-sought diff --git a/nextjs-app/components/SchoolRow.tsx b/nextjs-app/components/SchoolRow.tsx index b472051..dbafd05 100644 --- a/nextjs-app/components/SchoolRow.tsx +++ b/nextjs-app/components/SchoolRow.tsx @@ -40,12 +40,18 @@ export function SchoolRow({ // Special schools / PRUs / AP: the mainstream RWM measure and its England // comparison aren't a fair judgement (their pupils have SEND), so a "0% · - // −62 vs national" row misrepresents them. Treat the mainstream stat as not - // comparable — same for a placeholder all-zero value. + // −62 vs national" row misrepresents them. Also guard a placeholder all-zero + // row (every subject 0 — a special/suppressed signature), matching + // SchoolDetailView's ks2Placeholder. A genuine 0% combined (some pupils met + // individual subjects but not all three) is NOT all-zero, so it stays + // comparable and shows its real figure. + const rwmPlaceholder = + school.rwm_expected_pct === 0 && + (school.reading_expected_pct ?? 0) === 0 && + (school.writing_expected_pct ?? 0) === 0 && + (school.maths_expected_pct ?? 0) === 0; const rwmComparable = - school.rwm_expected_pct != null && - school.rwm_expected_pct !== 0 && - !isSpecialSchool(school); + school.rwm_expected_pct != null && !rwmPlaceholder && !isSpecialSchool(school); // vs-national delta const rwmDelta = diff --git a/nextjs-app/components/SecondarySchoolDetailView.tsx b/nextjs-app/components/SecondarySchoolDetailView.tsx index 071e544..d2716bc 100644 --- a/nextjs-app/components/SecondarySchoolDetailView.tsx +++ b/nextjs-app/components/SecondarySchoolDetailView.tsx @@ -110,10 +110,12 @@ export function SecondarySchoolDetailView({ // Special schools / PRUs / AP sit the same GCSEs but teach pupils with SEND, // so their headline attainment is far below the mainstream average by design. // Drop the England comparison + "below" framing so the page doesn't portray - // them as failing against a benchmark that doesn't fit. (Also guards a - // placeholder all-zero Attainment 8.) + // them as failing against a benchmark that doesn't fit. Attainment 8 is a + // single 0–80 score with no subject breakdown to test for a placeholder, so + // this keys off establishment type only — a genuine (if extreme) 0.0 at a + // mainstream school still shows its real value and comparison. const isSpecial = isSpecialSchool(schoolInfo); - const suppressComparison = isSpecial || (latestResults != null && latestResults.attainment_8_score === 0); + const suppressComparison = isSpecial; const admissionsTag = (() => { const policy = schoolInfo.admissions_policy?.toLowerCase() ?? ''; diff --git a/nextjs-app/components/SecondarySchoolRow.tsx b/nextjs-app/components/SecondarySchoolRow.tsx index f08d20c..0477d36 100644 --- a/nextjs-app/components/SecondarySchoolRow.tsx +++ b/nextjs-app/components/SecondarySchoolRow.tsx @@ -57,8 +57,11 @@ export function SecondarySchoolRow({ const att8 = school.attainment_8_score; // Special schools / PRUs / AP: Attainment 8 vs the LA average isn't a fair // comparison (their pupils have SEND), so drop the delta and the number - // rather than show them trailing "the average" by design. - const att8Comparable = att8 != null && att8 !== 0 && !isSpecialSchool(school); + // rather than show them trailing "the average" by design. Attainment 8 is a + // single 0–80 score with no subject breakdown to test for a placeholder, so + // this keys off establishment type only — a genuine (if extreme) 0.0 at a + // mainstream school still shows its real value. + const att8Comparable = att8 != null && !isSpecialSchool(school); const laDelta = att8Comparable && laAvgAttainment8 != null ? (att8 as number) - laAvgAttainment8 : null;