feat: add secondary school support with KS4 data and metric tooltips
Some checks failed
Build and Push Docker Images / Build Frontend (Next.js) (push) Has been cancelled
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Has been cancelled
Build and Push Docker Images / Trigger Portainer Update (push) Has been cancelled
Build and Push Docker Images / Build Backend (FastAPI) (push) Has been cancelled

- Backend: replace INNER JOIN ks2 with UNION ALL (ks2 + ks4) so primary
  and secondary schools both appear in the main DataFrame
- Backend: add /api/national-averages endpoint computing means from live
  data, replacing the hardcoded NATIONAL_AVG constant on the frontend
- Backend: add phase filter param to /api/schools; return phases from
  /api/filters; fix hardcoded "phase": "Primary" in school detail endpoint
- Backend: add KS4 metric definitions (Attainment 8, Progress 8, EBacc,
  English & Maths pass rates) to METRIC_DEFINITIONS and RANKING_COLUMNS
- Frontend: SchoolDetailView is now phase-aware — secondary schools show
  a GCSE Results section (Att8, P8, E&M, EBacc) instead of SATs; phonics
  tab hidden for secondary; admissions says Year 7 instead of Year 3;
  history table shows KS4 columns; chart datasets switch for secondary
- Frontend: new MetricTooltip component (CSS-only ⓘ icon) backed by
  METRIC_EXPLANATIONS — added to RWM, GPS, SEN, EAL, IDACI, progress
  scores and all KS4 metrics throughout SchoolDetailView and SchoolCard
- Frontend: METRIC_EXPLANATIONS extended with KS4 terms (Attainment 8,
  Progress 8, EBacc) and previously missing terms (SEN, EHCP, EAL, IDACI)
- Frontend: SchoolCard expands "RWM" to "Reading, Writing & Maths" and
  shows Attainment 8 / English & Maths Grade 4+ for secondary schools
- Frontend: FilterBar adds Phase dropdown (Primary / Secondary / All-through)
- Frontend: HomeView hero copy updated; compact list shows phase-aware metric
- Global metadata updated to remove "primary only" framing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-28 14:59:40 +00:00
parent b0990e30ee
commit 5eff9af69c
16 changed files with 903 additions and 187 deletions

View File

@@ -34,24 +34,50 @@ ChartJS.register(
interface PerformanceChartProps {
data: SchoolResult[];
schoolName: string;
isSecondary?: boolean;
}
export function PerformanceChart({ data, schoolName }: PerformanceChartProps) {
export function PerformanceChart({ data, schoolName, isSecondary = false }: PerformanceChartProps) {
// Sort data by year
const sortedData = [...data].sort((a, b) => a.year - b.year);
const years = sortedData.map(d => d.year.toString());
// Prepare datasets
const datasets = [
// Prepare datasets — phase-aware
const datasets = isSecondary ? [
{
label: 'RWM Expected %',
label: 'Attainment 8',
data: sortedData.map(d => d.attainment_8_score),
borderColor: 'rgb(59, 130, 246)',
backgroundColor: 'rgba(59, 130, 246, 0.1)',
tension: 0.3,
yAxisID: 'y',
},
{
label: 'English & Maths Grade 4+',
data: sortedData.map(d => d.english_maths_standard_pass_pct),
borderColor: 'rgb(16, 185, 129)',
backgroundColor: 'rgba(16, 185, 129, 0.1)',
tension: 0.3,
yAxisID: 'y',
},
{
label: 'Progress 8',
data: sortedData.map(d => d.progress_8_score),
borderColor: 'rgb(245, 158, 11)',
backgroundColor: 'rgba(245, 158, 11, 0.1)',
tension: 0.3,
yAxisID: 'y1',
},
] : [
{
label: 'Reading, Writing & Maths Expected %',
data: sortedData.map(d => d.rwm_expected_pct),
borderColor: 'rgb(59, 130, 246)',
backgroundColor: 'rgba(59, 130, 246, 0.1)',
tension: 0.3,
},
{
label: 'RWM Higher %',
label: 'Reading, Writing & Maths Higher %',
data: sortedData.map(d => d.rwm_high_pct),
borderColor: 'rgb(16, 185, 129)',
backgroundColor: 'rgba(16, 185, 129, 0.1)',
@@ -153,14 +179,14 @@ export function PerformanceChart({ data, schoolName }: PerformanceChartProps) {
position: 'left' as const,
title: {
display: true,
text: 'Percentage (%)',
text: isSecondary ? 'Score / Percentage (%)' : 'Percentage (%)',
font: {
size: 12,
weight: 'bold',
},
},
min: 0,
max: 100,
max: isSecondary ? undefined : 100,
grid: {
color: 'rgba(0, 0, 0, 0.05)',
},
@@ -171,7 +197,7 @@ export function PerformanceChart({ data, schoolName }: PerformanceChartProps) {
position: 'right' as const,
title: {
display: true,
text: 'Progress Score',
text: isSecondary ? 'Progress 8 Score' : 'Progress Score',
font: {
size: 12,
weight: 'bold',