From 1fb4b3ec5e2681afded9623ec0df3bd43447b24c Mon Sep 17 00:00:00 2001 From: Tudor Sitaru Date: Fri, 17 Apr 2026 22:52:59 +0100 Subject: [PATCH] refactor(primary): move gender split out of header into Pupils & Inclusion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Header "Pupils" line reverts to plain inline text matching Headteacher and website weight. Gender split lives in Pupils & Inclusion as a card alongside pupil premium / EAL / SEN support — peers of similar weight. Co-Authored-By: Claude Opus 4.7 --- .../components/SchoolDetailView.module.css | 89 +++++------------ nextjs-app/components/SchoolDetailView.tsx | 95 +++++++++---------- 2 files changed, 72 insertions(+), 112 deletions(-) diff --git a/nextjs-app/components/SchoolDetailView.module.css b/nextjs-app/components/SchoolDetailView.module.css index 7a548d8..23a1564 100644 --- a/nextjs-app/components/SchoolDetailView.module.css +++ b/nextjs-app/components/SchoolDetailView.module.css @@ -83,95 +83,58 @@ text-decoration: underline; } -/* Pupils block — the "Pupils: N" inline text is upgraded to a richer - display whenever we have census gender data and the school is Mixed. */ -.pupilsBlock { - display: inline-flex; - align-items: center; - gap: 0.7rem; - padding: 0.3rem 0.65rem 0.3rem 0.4rem; - background: rgba(243, 237, 228, 0.5); - border-radius: 10px; -} - -.pupilsFigure { - font-family: var(--font-playfair), 'Playfair Display', serif; - font-size: 1.6rem; - font-weight: 700; - line-height: 1; - letter-spacing: -0.01em; - color: var(--text-primary, #1a1612); -} - -.pupilsInfo { - display: flex; - flex-direction: column; - gap: 0.15rem; - min-width: 140px; -} - -.pupilsLegend { - font-size: 0.72rem; - color: var(--text-muted, #6d685f); - font-weight: 500; - line-height: 1; -} - -.pupilsCapacity { - color: var(--text-muted, #6d685f); -} - -.pupilsSplitRow { +/* Gender split card — sits in the Pupils & Inclusion heroStatGrid */ +.genderSplitValue { display: flex; align-items: baseline; - gap: 0.35rem; - font-size: 0.75rem; - font-weight: 600; + gap: 0.3rem; + font-family: var(--font-playfair), "Playfair Display", Georgia, serif; + font-size: 1.55rem; + font-weight: 700; line-height: 1; + flex-wrap: wrap; } -.pupilsSplitGirls { +.genderSplitGirls { color: #b45778; } -.pupilsSplitBoys { +.genderSplitBoys { color: var(--accent-teal, #2d7d7d); } -.pupilsSplitSep { - color: var(--border-color, #e5dfd5); - font-weight: 400; +.genderSplitLabel { + font-family: var(--font-body, inherit); + font-size: 0.78rem; + font-weight: 500; + color: var(--text-muted, #6d685f); + letter-spacing: 0; } -.pupilsBar { +.genderSplitSep { + color: var(--border-color, #c8beb0); + font-weight: 400; + font-size: 1.2rem; + padding: 0 0.1rem; +} + +.genderBar { display: flex; - height: 4px; + height: 6px; border-radius: 999px; overflow: hidden; background: var(--border-color, #e5dfd5); width: 100%; - min-width: 140px; } -.pupilsBarGirls { +.genderBarGirls { background: #b45778; } -.pupilsBarBoys { +.genderBarBoys { background: var(--accent-teal, #2d7d7d); } -@media (max-width: 640px) { - .pupilsBlock { - display: flex; - width: 100%; - } - .pupilsInfo { - flex: 1; - min-width: 0; - } -} - .actions { display: flex; gap: 0.5rem; diff --git a/nextjs-app/components/SchoolDetailView.tsx b/nextjs-app/components/SchoolDetailView.tsx index 5a3baf0..afe84e4 100644 --- a/nextjs-app/components/SchoolDetailView.tsx +++ b/nextjs-app/components/SchoolDetailView.tsx @@ -109,11 +109,19 @@ export function SchoolDetailView({ return `This school is in one of England's less deprived areas (decile ${decile}/10).`; }; + // Gender split availability (only meaningful for Mixed schools with census data) + const isMixedSchool = schoolInfo.gender === 'Mixed' || schoolInfo.gender == null; + const hasGenderSplit = isMixedSchool + && census?.female_pupils != null + && census?.male_pupils != null + && (census.female_pupils + census.male_pupils) > 0; + // Guard for Pupils & Inclusion — only show if at least one metric is available const hasInclusionData = (latestResults?.disadvantaged_pct != null) || (latestResults?.eal_pct != null) || (latestResults?.sen_support_pct != null) - || senDetail != null; + || senDetail != null + || hasGenderSplit; const hasSchoolLife = absenceData != null || census?.class_size_avg != null; const hasPhonics = phonics != null && phonics.year1_phonics_pct != null; @@ -236,54 +244,14 @@ export function SchoolDetailView({ )} {(() => { - const censusTotal = census?.total_pupils ?? null; - const female = census?.female_pupils ?? null; - const male = census?.male_pupils ?? null; - const total = censusTotal ?? latestResults?.total_pupils ?? null; - const isMixed = schoolInfo.gender === 'Mixed' || schoolInfo.gender == null; - const hasSplit = isMixed && female != null && male != null && female + male > 0; - - if (hasSplit && total != null) { - const sum = female! + male!; - const girlsPct = Math.round((female! / sum) * 100); - const boysPct = 100 - girlsPct; - return ( -
-
{total.toLocaleString()}
-
-
- pupils - {schoolInfo.capacity != null && ( - · capacity {schoolInfo.capacity.toLocaleString()} - )} -
-
- {girlsPct}% girls - · - {boysPct}% boys -
-
- - -
-
-
- ); - } - - if (total != null) { - return ( - - Pupils: {total.toLocaleString()} - {schoolInfo.capacity != null && ` (capacity: ${schoolInfo.capacity})`} - - ); - } - return null; + const total = census?.total_pupils ?? latestResults?.total_pupils ?? null; + if (total == null) return null; + return ( + + Pupils: {total.toLocaleString()} + {schoolInfo.capacity != null && ` (capacity: ${schoolInfo.capacity})`} + + ); })()} {schoolInfo.trust_name && ( @@ -962,6 +930,35 @@ export function SchoolDetailView({ )} )} + {hasGenderSplit && (() => { + const female = census!.female_pupils!; + const male = census!.male_pupils!; + const girlsPct = Math.round((female / (female + male)) * 100); + const boysPct = 100 - girlsPct; + return ( +
+
Boys and girls
+
+ {girlsPct}% + girls + · + {boysPct}% + boys +
+
+ + +
+
+ {female.toLocaleString()} girls, {male.toLocaleString()} boys +
+
+ ); + })()} {senDetail && ( <>