feat(schools): label age range as "Ages 3–11" for clarity
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 12s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 46s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 12s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s

The bare "3-11" range gave no unit. Add a display-only formatAgeRange
helper ("3-11" -> "Ages 3–11", en-dash) used in the primary/secondary
search rows and the secondary detail badge. The raw age_range field is
left untouched so sixth-form detection (.includes('18')) still works.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tudor
2026-07-01 23:05:05 +01:00
co-authored by Claude Opus 4.8
parent 58c5eb8ecc
commit b7a94f1a52
4 changed files with 18 additions and 6 deletions
+2 -2
View File
@@ -9,7 +9,7 @@
*/ */
import type { School } from '@/lib/types'; import type { School } from '@/lib/types';
import { formatPercentage, calculateTrend, getPhaseStyle, schoolUrl, buildOfstedListBadge } from '@/lib/utils'; import { formatPercentage, calculateTrend, getPhaseStyle, schoolUrl, buildOfstedListBadge, formatAgeRange } from '@/lib/utils';
import styles from './SchoolRow.module.css'; import styles from './SchoolRow.module.css';
interface SchoolRowProps { interface SchoolRowProps {
@@ -75,7 +75,7 @@ export function SchoolRow({
</span> </span>
)} )}
{school.school_type && <span>{school.school_type}</span>} {school.school_type && <span>{school.school_type}</span>}
{school.age_range && <span>{school.age_range}</span>} {school.age_range && <span>{formatAgeRange(school.age_range)}</span>}
{showDenomination && <span>{school.religious_denomination}</span>} {showDenomination && <span>{school.religious_denomination}</span>}
{showGender && <span>{school.gender}</span>} {showGender && <span>{school.gender}</span>}
</div> </div>
@@ -23,7 +23,7 @@ import type {
SchoolAdmissions, SenDetail, Phonics, SchoolAdmissions, SenDetail, Phonics,
SchoolDeprivation, SchoolFinance, NationalAverages, SchoolDeprivation, SchoolFinance, NationalAverages,
} from '@/lib/types'; } from '@/lib/types';
import { formatPercentage, formatProgress, formatAcademicYear } from '@/lib/utils'; import { formatPercentage, formatProgress, formatAcademicYear, formatAgeRange } from '@/lib/utils';
import { DeltaChip } from './DeltaChip'; import { DeltaChip } from './DeltaChip';
import { track, getNavigationSource } from '@/lib/analytics'; import { track, getNavigationSource } from '@/lib/analytics';
import styles from './SecondarySchoolDetailView.module.css'; import styles from './SecondarySchoolDetailView.module.css';
@@ -228,7 +228,7 @@ export function SecondarySchoolDetailView({
<span className={styles.badge}>{schoolInfo.gender}&apos;s school</span> <span className={styles.badge}>{schoolInfo.gender}&apos;s school</span>
)} )}
{schoolInfo.age_range && ( {schoolInfo.age_range && (
<span className={styles.badge}>{schoolInfo.age_range}</span> <span className={styles.badge}>{formatAgeRange(schoolInfo.age_range)}</span>
)} )}
{hasSixthForm && ( {hasSixthForm && (
<span className={styles.badge}>Sixth form</span> <span className={styles.badge}>Sixth form</span>
+2 -2
View File
@@ -11,7 +11,7 @@
'use client'; 'use client';
import type { School } from '@/lib/types'; import type { School } from '@/lib/types';
import { buildOfstedListBadge, getPhaseStyle, schoolUrl } from '@/lib/utils'; import { buildOfstedListBadge, getPhaseStyle, schoolUrl, formatAgeRange } from '@/lib/utils';
import styles from './SecondarySchoolRow.module.css'; import styles from './SecondarySchoolRow.module.css';
function detectAdmissionsTag(school: School): string | null { function detectAdmissionsTag(school: School): string | null {
@@ -84,7 +84,7 @@ export function SecondarySchoolRow({
</span> </span>
)} )}
{school.school_type && <span>{school.school_type}</span>} {school.school_type && <span>{school.school_type}</span>}
{school.age_range && <span>{school.age_range}</span>} {school.age_range && <span>{formatAgeRange(school.age_range)}</span>}
{showGender && ( {showGender && (
<span className={styles.provisionTag}>{school.gender}</span> <span className={styles.provisionTag}>{school.gender}</span>
)} )}
+12
View File
@@ -59,6 +59,18 @@ export function truncate(text: string, maxLength: number): string {
return text.slice(0, maxLength).trim() + '...'; return text.slice(0, maxLength).trim() + '...';
} }
/**
* Format a school's age range for display, e.g. "3-11" → "Ages 311".
* Display-only — leaves the raw `age_range` field (used for sixth-form
* detection) untouched. Falls back to the raw value if it's not a plain range.
*/
export function formatAgeRange(ageRange: string | null | undefined): string {
if (!ageRange) return '';
const match = ageRange.match(/^\s*(\d+)\s*[-]\s*(\d+)\s*$/);
if (!match) return ageRange;
return `Ages ${match[1]}${match[2]}`;
}
// ============================================================================ // ============================================================================
// Number Formatting // Number Formatting
// ============================================================================ // ============================================================================