fix(frontend): format 6-digit EES academic year codes correctly
All checks were successful
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 32s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m5s
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

formatAcademicYear now handles both 4-digit (2023→2023/24) and 6-digit
EES codes (202526→2025/26). Applied to all year displays: SATs, phonics,
admissions, finances, and the yearly results table.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-27 18:30:37 +00:00
parent 7724fe3503
commit cd1c649d0f
2 changed files with 13 additions and 7 deletions

View File

@@ -15,7 +15,7 @@ import type {
SchoolAdmissions, SenDetail, Phonics, SchoolAdmissions, SenDetail, Phonics,
SchoolDeprivation, SchoolFinance, SchoolDeprivation, SchoolFinance,
} from '@/lib/types'; } from '@/lib/types';
import { formatPercentage, formatProgress } from '@/lib/utils'; import { formatPercentage, formatProgress, formatAcademicYear } from '@/lib/utils';
import styles from './SchoolDetailView.module.css'; import styles from './SchoolDetailView.module.css';
const OFSTED_LABELS: Record<number, string> = { const OFSTED_LABELS: Record<number, string> = {
@@ -331,7 +331,7 @@ export function SchoolDetailView({
{/* SATs Results (merged with Subject Breakdown) */} {/* SATs Results (merged with Subject Breakdown) */}
{latestResults && ( {latestResults && (
<section id="sats" className={styles.card}> <section id="sats" className={styles.card}>
<h2 className={styles.sectionTitle}>SATs Results ({latestResults.year})</h2> <h2 className={styles.sectionTitle}>SATs Results ({formatAcademicYear(latestResults.year)})</h2>
<p className={styles.sectionSubtitle}> <p className={styles.sectionSubtitle}>
End-of-primary-school tests taken by Year 6 pupils. National averages shown for comparison. End-of-primary-school tests taken by Year 6 pupils. National averages shown for comparison.
</p> </p>
@@ -458,7 +458,7 @@ export function SchoolDetailView({
{/* Year 1 Phonics */} {/* Year 1 Phonics */}
{hasPhonics && phonics && ( {hasPhonics && phonics && (
<section id="phonics" className={styles.card}> <section id="phonics" className={styles.card}>
<h2 className={styles.sectionTitle}>Year 1 Phonics ({phonics.year})</h2> <h2 className={styles.sectionTitle}>Year 1 Phonics ({formatAcademicYear(phonics.year)})</h2>
<p className={styles.sectionSubtitle}> <p className={styles.sectionSubtitle}>
Phonics is a key early reading skill. Children are tested at the end of Year 1. Phonics is a key early reading skill. Children are tested at the end of Year 1.
</p> </p>
@@ -511,7 +511,7 @@ export function SchoolDetailView({
{/* How Hard to Get In */} {/* How Hard to Get In */}
{admissions && ( {admissions && (
<section id="admissions" className={styles.card}> <section id="admissions" className={styles.card}>
<h2 className={styles.sectionTitle}>How Hard to Get Into This School ({admissions.year})</h2> <h2 className={styles.sectionTitle}>How Hard to Get Into This School ({formatAcademicYear(admissions.year)})</h2>
<div className={styles.metricsGrid}> <div className={styles.metricsGrid}>
{admissions.published_admission_number != null && ( {admissions.published_admission_number != null && (
<div className={styles.metricCard}> <div className={styles.metricCard}>
@@ -631,7 +631,7 @@ export function SchoolDetailView({
{/* Finances */} {/* Finances */}
{hasFinance && finance && ( {hasFinance && finance && (
<section id="finances" className={styles.card}> <section id="finances" className={styles.card}>
<h2 className={styles.sectionTitle}>School Finances ({finance.year})</h2> <h2 className={styles.sectionTitle}>School Finances ({formatAcademicYear(finance.year)})</h2>
<p className={styles.sectionSubtitle}> <p className={styles.sectionSubtitle}>
Per-pupil spending shows how much the school has to spend on each child&apos;s education. Per-pupil spending shows how much the school has to spend on each child&apos;s education.
</p> </p>
@@ -685,7 +685,7 @@ export function SchoolDetailView({
<tbody> <tbody>
{yearlyData.map((result) => ( {yearlyData.map((result) => (
<tr key={result.year}> <tr key={result.year}>
<td className={styles.yearCell}>{result.year}</td> <td className={styles.yearCell}>{formatAcademicYear(result.year)}</td>
<td>{result.rwm_expected_pct !== null ? formatPercentage(result.rwm_expected_pct) : '-'}</td> <td>{result.rwm_expected_pct !== null ? formatPercentage(result.rwm_expected_pct) : '-'}</td>
<td>{result.rwm_high_pct !== null ? formatPercentage(result.rwm_high_pct) : '-'}</td> <td>{result.rwm_high_pct !== null ? formatPercentage(result.rwm_high_pct) : '-'}</td>
<td>{result.reading_progress !== null ? formatProgress(result.reading_progress) : '-'}</td> <td>{result.reading_progress !== null ? formatProgress(result.reading_progress) : '-'}</td>

View File

@@ -338,9 +338,15 @@ export function parseQueryString(search: string): Record<string, string> {
// ============================================================================ // ============================================================================
/** /**
* Format academic year (e.g., 2023 -> "2023/24") * Format academic year.
* Handles both 4-digit start years (2023 → "2023/24") and
* 6-digit EES codes (202526 → "2025/26").
*/ */
export function formatAcademicYear(year: number): string { export function formatAcademicYear(year: number): string {
const s = year.toString();
if (s.length === 6) {
return `${s.slice(0, 4)}/${s.slice(4)}`;
}
const nextYear = (year + 1).toString().slice(-2); const nextYear = (year + 1).toString().slice(-2);
return `${year}/${nextYear}`; return `${year}/${nextYear}`;
} }