fix(detail): enrich secondary overview tab — show Ofsted grades, admissions, SEN
All checks were successful
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 37s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m6s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 31s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s

The overview tab was sparse for schools without parent view data, showing
only 2 cards. Now shows:
- Individual Ofsted grades when no overall effectiveness (post-Sept 2024)
- Admissions summary card (PAN, applications, 1st choice rate)
- School context card (pupils, capacity, SEN support, EHCP)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-29 10:59:30 +01:00
parent 63dfa22255
commit 77a0f5b674

View File

@@ -232,12 +232,33 @@ export function SecondarySchoolDetailView({
<p className={styles.sectionSubtitle}>
From November 2025, Ofsted replaced single overall grades with Report Cards.
</p>
) : (
) : ofsted.overall_effectiveness ? (
<div className={styles.ofstedHeader}>
<span className={`${styles.ofstedGrade} ${styles[`ofstedGrade${ofsted.overall_effectiveness}`]}`}>
{ofsted.overall_effectiveness ? OFSTED_LABELS[ofsted.overall_effectiveness] : 'Not rated'}
{OFSTED_LABELS[ofsted.overall_effectiveness]}
</span>
</div>
) : (
<>
<p className={styles.sectionSubtitle}>
From September 2024, Ofsted no longer gives a single overall grade.
</p>
<div className={styles.metricsGrid}>
{[
{ label: 'Quality of Education', value: ofsted.quality_of_education },
{ label: 'Behaviour & Attitudes', value: ofsted.behaviour_attitudes },
{ label: 'Personal Development', value: ofsted.personal_development },
{ label: 'Leadership & Management', value: ofsted.leadership_management },
].filter(({ value }) => value != null).map(({ label, value }) => (
<div key={label} className={styles.metricCard}>
<div className={styles.metricLabel}>{label}</div>
<div className={`${styles.metricValue} ${styles[`ofstedGrade${value}`]}`}>
{OFSTED_LABELS[value!]}
</div>
</div>
))}
</div>
</>
)}
{parentView?.q_recommend_pct != null && parentView.total_responses != null && parentView.total_responses > 0 && (
<p className={styles.parentRecommendLine}>
@@ -288,6 +309,66 @@ export function SecondarySchoolDetailView({
</div>
)}
{/* Admissions summary */}
{admissions && (admissions.published_admission_number != null || admissions.total_applications != null) && (
<div className={styles.card}>
<h2 className={styles.sectionTitle}>Admissions at a Glance</h2>
<div className={styles.metricsGrid}>
{admissions.published_admission_number != null && (
<div className={styles.metricCard}>
<div className={styles.metricLabel}>Year 7 places (PAN)</div>
<div className={styles.metricValue}>{admissions.published_admission_number}</div>
</div>
)}
{admissions.total_applications != null && (
<div className={styles.metricCard}>
<div className={styles.metricLabel}>Total applications</div>
<div className={styles.metricValue}>{admissions.total_applications.toLocaleString()}</div>
</div>
)}
{admissions.first_preference_offer_pct != null && (
<div className={styles.metricCard}>
<div className={styles.metricLabel}>1st choice offer rate</div>
<div className={styles.metricValue}>{admissions.first_preference_offer_pct}%</div>
</div>
)}
</div>
<button onClick={() => setActiveTab('admissions')} className={styles.tabLink}>
Full admissions details
</button>
</div>
)}
{/* SEN & school context summary */}
{(latestResults?.sen_support_pct != null || latestResults?.sen_ehcp_pct != null || latestResults?.total_pupils != null) && (
<div className={styles.card}>
<h2 className={styles.sectionTitle}>School Context</h2>
<div className={styles.metricsGrid}>
{latestResults?.total_pupils != null && (
<div className={styles.metricCard}>
<div className={styles.metricLabel}>Total pupils</div>
<div className={styles.metricValue}>{latestResults.total_pupils.toLocaleString()}</div>
{schoolInfo.capacity != null && (
<div className={styles.metricHint}>Capacity: {schoolInfo.capacity}</div>
)}
</div>
)}
{latestResults?.sen_support_pct != null && (
<div className={styles.metricCard}>
<div className={styles.metricLabel}>SEN support</div>
<div className={styles.metricValue}>{formatPercentage(latestResults.sen_support_pct)}</div>
</div>
)}
{latestResults?.sen_ehcp_pct != null && (
<div className={styles.metricCard}>
<div className={styles.metricLabel}>EHCP</div>
<div className={styles.metricValue}>{formatPercentage(latestResults.sen_ehcp_pct)}</div>
</div>
)}
</div>
</div>
)}
{/* Top Parent View scores */}
{parentView != null && parentView.total_responses != null && parentView.total_responses > 0 && (
<div className={styles.card}>