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
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:
@@ -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}>
|
||||
|
||||
Reference in New Issue
Block a user