diff --git a/nextjs-app/__tests__/components/SecondarySchoolRow.test.tsx b/nextjs-app/__tests__/components/SecondarySchoolRow.test.tsx index affaecb..a868256 100644 --- a/nextjs-app/__tests__/components/SecondarySchoolRow.test.tsx +++ b/nextjs-app/__tests__/components/SecondarySchoolRow.test.tsx @@ -44,3 +44,24 @@ describe('SecondarySchoolRow sixth-form tag', () => { expect(screen.queryByText('Sixth form')).not.toBeInTheDocument(); }); }); + +describe('SecondarySchoolRow proposed-to-close tag', () => { + it('shows the tag when GIAS status is "Open, but proposed to close"', () => { + render( + , + ); + expect(screen.getByText(/Proposed to close/)).toBeInTheDocument(); + }); + + it('hides the tag for a plain open school', () => { + render(); + expect(screen.queryByText(/Proposed to close/)).not.toBeInTheDocument(); + }); + + it('hides the tag when status is missing', () => { + render(); + expect(screen.queryByText(/Proposed to close/)).not.toBeInTheDocument(); + }); +}); diff --git a/nextjs-app/__tests__/lib/utils.test.ts b/nextjs-app/__tests__/lib/utils.test.ts index 2a9c664..a1ebbbc 100644 --- a/nextjs-app/__tests__/lib/utils.test.ts +++ b/nextjs-app/__tests__/lib/utils.test.ts @@ -212,3 +212,14 @@ describe('computeYBounds', () => { expect(computeYBounds([], 'progress')).toEqual({}); }); }); + +describe('isProposedToClose', () => { + const { isProposedToClose } = require('@/lib/utils'); + + it('is true only for the exact GIAS proposed-to-close status', () => { + expect(isProposedToClose({ status: 'Open, but proposed to close' })).toBe(true); + expect(isProposedToClose({ status: 'Open' })).toBe(false); + expect(isProposedToClose({ status: null })).toBe(false); + expect(isProposedToClose({})).toBe(false); + }); +}); diff --git a/nextjs-app/components/SchoolDetailView.module.css b/nextjs-app/components/SchoolDetailView.module.css index e2ac1b8..b2b419a 100644 --- a/nextjs-app/components/SchoolDetailView.module.css +++ b/nextjs-app/components/SchoolDetailView.module.css @@ -1543,3 +1543,18 @@ .historyDisclosure[open] > .historyToggle::before { transform: rotate(90deg); } + +/* GIAS "Open, but proposed to close" notice strip */ +.closingStrip { + background: #fdf6e3; + border-left: 4px solid #e2c96f; + border-radius: 0 6px 6px 0; + padding: 0.55rem 0.9rem; + margin: 0.5rem 0; + font-size: 0.88rem; + color: #6e5a00; + max-width: 68ch; +} +.closingStrip strong { + color: #8a6200; +} diff --git a/nextjs-app/components/SchoolDetailView.tsx b/nextjs-app/components/SchoolDetailView.tsx index 8625278..ab0dfe1 100644 --- a/nextjs-app/components/SchoolDetailView.tsx +++ b/nextjs-app/components/SchoolDetailView.tsx @@ -18,7 +18,7 @@ import type { SchoolDeprivation, SchoolFinance, NationalAverages, } from '@/lib/types'; import { - formatPercentage, formatProgress, formatAcademicYear, + formatPercentage, formatProgress, formatAcademicYear, isProposedToClose, } from '@/lib/utils'; import { DeltaChip } from './DeltaChip'; @@ -313,6 +313,13 @@ export function SchoolDetailView({ {schoolInfo.gender}'s school )} + {isProposedToClose(schoolInfo) && ( +
+ ⚠ Proposed to close — this school is proposed for closure, + although a formal closure process has not necessarily started. Check with the + local authority before applying. +
+ )} {schoolInfo.address && (

{schoolInfo.address}{schoolInfo.postcode && `, ${schoolInfo.postcode}`} diff --git a/nextjs-app/components/SchoolRow.module.css b/nextjs-app/components/SchoolRow.module.css index 2bc0e47..20f03e8 100644 --- a/nextjs-app/components/SchoolRow.module.css +++ b/nextjs-app/components/SchoolRow.module.css @@ -254,3 +254,10 @@ justify-content: center; } } + +/* GIAS "Open, but proposed to close" marker */ +.attrClosing { + background: #fdf6e3; + color: #8a6200; + border: 1px solid #e2c96f; +} diff --git a/nextjs-app/components/SchoolRow.tsx b/nextjs-app/components/SchoolRow.tsx index 71fd763..43dc205 100644 --- a/nextjs-app/components/SchoolRow.tsx +++ b/nextjs-app/components/SchoolRow.tsx @@ -9,7 +9,7 @@ */ import type { School } from '@/lib/types'; -import { formatPercentage, calculateTrend, getPhaseStyle, schoolUrl, buildOfstedListBadge, formatAgeRange } from '@/lib/utils'; +import { formatPercentage, calculateTrend, getPhaseStyle, schoolUrl, buildOfstedListBadge, formatAgeRange, isProposedToClose } from '@/lib/utils'; import styles from './SchoolRow.module.css'; interface SchoolRowProps { @@ -78,6 +78,9 @@ export function SchoolRow({ {school.age_range && {formatAgeRange(school.age_range)}} {showDenomination && {school.religious_denomination}} {showGender && {school.gender}} + {isProposedToClose(school) && ( + ⚠ Proposed to close + )} {/* Line 3: Key stats */} diff --git a/nextjs-app/components/SecondarySchoolDetailView.module.css b/nextjs-app/components/SecondarySchoolDetailView.module.css index 1c90337..6ac06bf 100644 --- a/nextjs-app/components/SecondarySchoolDetailView.module.css +++ b/nextjs-app/components/SecondarySchoolDetailView.module.css @@ -1099,3 +1099,18 @@ padding: 0.75rem; } } + +/* GIAS "Open, but proposed to close" notice strip */ +.closingStrip { + background: #fdf6e3; + border-left: 4px solid #e2c96f; + border-radius: 0 6px 6px 0; + padding: 0.55rem 0.9rem; + margin: 0.5rem 0; + font-size: 0.88rem; + color: #6e5a00; + max-width: 68ch; +} +.closingStrip strong { + color: #8a6200; +} diff --git a/nextjs-app/components/SecondarySchoolDetailView.tsx b/nextjs-app/components/SecondarySchoolDetailView.tsx index 8210313..7246164 100644 --- a/nextjs-app/components/SecondarySchoolDetailView.tsx +++ b/nextjs-app/components/SecondarySchoolDetailView.tsx @@ -23,7 +23,7 @@ import type { SchoolAdmissions, SenDetail, Phonics, SchoolDeprivation, SchoolFinance, NationalAverages, } from '@/lib/types'; -import { formatPercentage, formatProgress, formatAcademicYear, formatAgeRange } from '@/lib/utils'; +import { formatPercentage, formatProgress, formatAcademicYear, formatAgeRange, isProposedToClose } from '@/lib/utils'; import { DeltaChip } from './DeltaChip'; import { track, getNavigationSource } from '@/lib/analytics'; import styles from './SecondarySchoolDetailView.module.css'; @@ -237,6 +237,13 @@ export function SecondarySchoolDetailView({ )} + {isProposedToClose(schoolInfo) && ( +

+ ⚠ Proposed to close — this school is proposed for closure, + although a formal closure process has not necessarily started. Check with the + local authority before applying. +
+ )} {schoolInfo.address && (

{schoolInfo.address}{schoolInfo.postcode && `, ${schoolInfo.postcode}`} diff --git a/nextjs-app/components/SecondarySchoolRow.module.css b/nextjs-app/components/SecondarySchoolRow.module.css index 0949f11..ae64de6 100644 --- a/nextjs-app/components/SecondarySchoolRow.module.css +++ b/nextjs-app/components/SecondarySchoolRow.module.css @@ -266,3 +266,9 @@ justify-content: center; } } + +.closingTag { + background: #fdf6e3; + color: #8a6200; + border: 1px solid #e2c96f; +} diff --git a/nextjs-app/components/SecondarySchoolRow.tsx b/nextjs-app/components/SecondarySchoolRow.tsx index c32dab4..39c1256 100644 --- a/nextjs-app/components/SecondarySchoolRow.tsx +++ b/nextjs-app/components/SecondarySchoolRow.tsx @@ -11,7 +11,7 @@ 'use client'; import type { School } from '@/lib/types'; -import { buildOfstedListBadge, getPhaseStyle, schoolUrl, formatAgeRange } from '@/lib/utils'; +import { buildOfstedListBadge, getPhaseStyle, schoolUrl, formatAgeRange, isProposedToClose } from '@/lib/utils'; import styles from './SecondarySchoolRow.module.css'; function detectAdmissionsTag(school: School): string | null { @@ -97,6 +97,9 @@ export function SecondarySchoolRow({ {admissionsTag} )} + {isProposedToClose(school) && ( + ⚠ Proposed to close + )} {/* Line 3: KS4 stats */} diff --git a/nextjs-app/lib/types.ts b/nextjs-app/lib/types.ts index dc1cd2a..c29512c 100644 --- a/nextjs-app/lib/types.ts +++ b/nextjs-app/lib/types.ts @@ -18,6 +18,7 @@ export interface School { religious_denomination: string | null; age_range: string | null; has_sixth_form?: boolean | null; + status?: string | null; // GIAS establishment status ("Open" / "Open, but proposed to close") // Address address1: string | null; diff --git a/nextjs-app/lib/utils.ts b/nextjs-app/lib/utils.ts index 07b5d2e..fa1edf0 100644 --- a/nextjs-app/lib/utils.ts +++ b/nextjs-app/lib/utils.ts @@ -718,3 +718,18 @@ export function buildOfstedListBadge(school: { return { label: 'Not yet inspected', cssClass: 'ofstedPending' }; } + +// ============================================================================ +// Establishment status +// ============================================================================ + +export const PROPOSED_TO_CLOSE_STATUS = 'Open, but proposed to close'; + +/** + * GIAS lists some operating schools as "Open, but proposed to close". + * They remain open (and may stay open if the proposal is withdrawn), but the + * UI marks them so families check with the local authority before applying. + */ +export function isProposedToClose(school: { status?: string | null }): boolean { + return school.status === PROPOSED_TO_CLOSE_STATUS; +}