fix(compare): Ofsted rows show the grade still in force and the latest visit
'Inspected' is the school's latest visit, so Washwood Heath reads 21 May 2025 rather than '3 Mar 2020 · 4+ years ago' (audit M1). The Result row names the inspection a grade came from, or says 'No overall grade'; 'Grade carried forward' and 'transitional framework' go. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9ef48da4b1
commit
d37baa572b
3 files changed
+56
-37
No files matched your search
@@ -33,18 +33,26 @@ function ofsted(partial: Partial<OfstedInspection>): OfstedInspection {
|
||||
};
|
||||
}
|
||||
|
||||
const schools = [school(1, 'Graded School'), school(2, 'Carried School'), school(3, 'Card School')];
|
||||
const schools = [school(1, 'Graded School'), school(2, 'Confirmed School'), school(3, 'Card School')];
|
||||
|
||||
const data: Record<string, ComparisonData> = {
|
||||
'1': {
|
||||
school_info: schools[0],
|
||||
yearly_data: [],
|
||||
ofsted: ofsted({ overall_effectiveness: 1, grade_source: 'graded' }),
|
||||
ofsted: ofsted({
|
||||
overall_effectiveness: 1,
|
||||
current_grade: { grade: 1, date: '2021-10-07', basis: 'graded' },
|
||||
latest_visit: { date: '2021-10-07', kind: 'graded', outcome: null },
|
||||
}),
|
||||
},
|
||||
'2': {
|
||||
school_info: schools[1],
|
||||
yearly_data: [],
|
||||
ofsted: ofsted({ overall_effectiveness: 2, grade_source: 'ungraded_carried_forward' }),
|
||||
ofsted: ofsted({
|
||||
overall_effectiveness: 2,
|
||||
current_grade: { grade: 2, date: '2023-03-14', basis: 'confirmed' },
|
||||
latest_visit: { date: '2023-03-14', kind: 'ungraded', outcome: 'School remains Good' },
|
||||
}),
|
||||
},
|
||||
'3': {
|
||||
school_info: schools[2],
|
||||
@@ -65,9 +73,9 @@ describe('CompareOfsted', () => {
|
||||
render(<CompareOfsted schools={schools} data={data} />);
|
||||
|
||||
expect(screen.getByText('Outstanding')).toBeInTheDocument();
|
||||
// Carried-forward grade is shown but marked as such
|
||||
// A grade confirmed at an ungraded visit says so, with that visit's date
|
||||
expect(screen.getByText('Good')).toBeInTheDocument();
|
||||
expect(screen.getByText(/carried forward/i)).toBeInTheDocument();
|
||||
expect(screen.getByText('Confirmed at an ungraded inspection, 14 March 2023')).toBeInTheDocument();
|
||||
// Report card: label present, no overall-grade badge for that school
|
||||
expect(screen.getByText('Report card')).toBeInTheDocument();
|
||||
expect(screen.getByText(/no overall grade/i)).toBeInTheDocument();
|
||||
@@ -104,7 +112,7 @@ describe('CompareOfsted', () => {
|
||||
yearly_data: [],
|
||||
ofsted: ofsted({
|
||||
overall_effectiveness: 2,
|
||||
grade_source: 'graded',
|
||||
current_grade: { grade: 2, date: '2021-10-07', basis: 'graded' },
|
||||
quality_of_education: 1,
|
||||
early_years_provision: 9,
|
||||
sixth_form_provision: 2,
|
||||
@@ -167,4 +175,26 @@ describe('CompareOfsted', () => {
|
||||
expect(screen.getAllByText('Graded').length).toBe(4);
|
||||
expect(screen.getAllByText('Card').length).toBe(4);
|
||||
});
|
||||
|
||||
it('dates "Inspected" by the latest visit, not the graded inspection (Washwood Heath)', () => {
|
||||
const s1 = school(7, 'Washwood Heath Academy');
|
||||
render(<CompareOfsted schools={[s1]} data={{ '7': { school_info: s1, yearly_data: [], ofsted: ofsted({
|
||||
inspection_date: '2020-03-03', overall_effectiveness: 2, quality_of_education: 2,
|
||||
current_grade: { grade: 2, date: '2020-03-03', basis: 'graded' },
|
||||
latest_visit: { date: '2025-05-21', kind: 'ungraded', outcome: 'Standards maintained' },
|
||||
}) } }} />);
|
||||
expect(screen.getByText(/21 May 2025/)).toBeInTheDocument();
|
||||
expect(screen.queryByText('4+ years ago')).not.toBeInTheDocument();
|
||||
expect(screen.getByText('Graded inspection, 3 March 2020')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows no overall grade after a no-grade inspection (Rabbsfarm)', () => {
|
||||
const s1 = school(8, 'Rabbsfarm Primary School');
|
||||
render(<CompareOfsted schools={[s1]} data={{ '8': { school_info: s1, yearly_data: [], ofsted: ofsted({
|
||||
inspection_date: '2025-06-17', quality_of_education: 3,
|
||||
current_grade: null, latest_visit: { date: '2025-06-17', kind: 'graded', outcome: null },
|
||||
}) } }} />);
|
||||
expect(screen.getAllByText('No overall grade').length).toBeGreaterThan(0);
|
||||
expect(screen.queryByText('Good')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -78,21 +78,18 @@ export function CompareAtAGlance({
|
||||
return (
|
||||
<Cell key={school.urn} school={school} index={i}>
|
||||
{display.kind === 'report_card' && <ReportCardChips summary={display.summary} />}
|
||||
{(display.kind === 'graded' || display.kind === 'carried_forward') && (
|
||||
{(display.kind === 'graded' || display.kind === 'confirmed') && (
|
||||
<>
|
||||
<span className={`${s.badge} ${display.grade <= 2 ? s.badgeGood : display.grade === 3 ? s.badgeWarn : s.badgeBad}`}>
|
||||
{display.gradeLabel}
|
||||
</span>
|
||||
{display.carriedForward && <span className={s.small}>Grade carried forward</span>}
|
||||
{display.kind === 'confirmed' && <span className={s.small}>Confirmed at an ungraded inspection</span>}
|
||||
</>
|
||||
)}
|
||||
{display.kind === 'transitional' && (
|
||||
<>
|
||||
<span className={s.badge} style={{ backgroundColor: 'var(--bg-secondary)', color: 'var(--text-secondary)' }}>
|
||||
No overall grade
|
||||
</span>
|
||||
<span className={s.small}>Sub-judgements only</span>
|
||||
</>
|
||||
{display.kind === 'no_overall_grade' && (
|
||||
<span className={s.badge} style={{ backgroundColor: 'var(--bg-secondary)', color: 'var(--text-secondary)' }}>
|
||||
No overall grade
|
||||
</span>
|
||||
)}
|
||||
{display.kind === 'none' && <span className={s.small}>No inspection in our dataset</span>}
|
||||
</Cell>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/**
|
||||
* Ofsted section — one visual grammar for inspection detail across all
|
||||
* three regimes (legacy graded, interim carried-forward, renewed-framework
|
||||
* report card). Copy comes verbatim from the reviewed mockups.
|
||||
* three regimes (legacy graded, no overall grade, renewed-framework report
|
||||
* card). The grade shown is the one still in force, with the inspection that
|
||||
* awarded or confirmed it; "Inspected" is the latest visit.
|
||||
*/
|
||||
|
||||
'use client';
|
||||
@@ -12,7 +13,8 @@ import {
|
||||
rcAreaLabel,
|
||||
type OfstedDisplay,
|
||||
} from '@/lib/compareLogic';
|
||||
import type { ComparisonData, OfstedInspection, School } from '@/lib/types';
|
||||
import { gradeSourceLine } from '@/lib/ofstedStatus';
|
||||
import type { ComparisonData, OfstedCurrentGrade, OfstedInspection, School } from '@/lib/types';
|
||||
import { Cell, Chip, Measure, Section, SectionGrid, sectionStyles as s } from './sectionShared';
|
||||
|
||||
const GRADE_TONE: Record<number, 'good' | 'warn' | 'bad'> = {
|
||||
@@ -39,7 +41,7 @@ function yearsSince(iso: string | null): number | null {
|
||||
return (Date.now() - d.getTime()) / (365.25 * 24 * 3600 * 1000);
|
||||
}
|
||||
|
||||
function ResultCell({ display }: { display: OfstedDisplay }) {
|
||||
function ResultCell({ display, current }: { display: OfstedDisplay; current: OfstedCurrentGrade | null }) {
|
||||
if (display.kind === 'none') {
|
||||
return <span className={s.small}>No inspection outcome in our dataset</span>;
|
||||
}
|
||||
@@ -51,15 +53,13 @@ function ResultCell({ display }: { display: OfstedDisplay }) {
|
||||
</>
|
||||
);
|
||||
}
|
||||
if (display.kind === 'transitional') {
|
||||
if (display.kind === 'no_overall_grade') {
|
||||
return (
|
||||
<>
|
||||
<span className={s.badge} style={{ backgroundColor: 'var(--bg-secondary)', color: 'var(--text-secondary)' }}>
|
||||
No overall grade
|
||||
</span>
|
||||
<span className={s.small}>
|
||||
Inspected under transitional framework (sub-judgements only)
|
||||
</span>
|
||||
<span className={s.small}>Ofsted stopped giving overall grades in September 2024</span>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -68,11 +68,7 @@ function ResultCell({ display }: { display: OfstedDisplay }) {
|
||||
<span className={`${s.badge} ${display.grade <= 2 ? s.badgeGood : display.grade === 3 ? s.badgeWarn : s.badgeBad}`}>
|
||||
{display.gradeLabel}
|
||||
</span>
|
||||
<span className={s.small}>
|
||||
{display.carriedForward
|
||||
? 'Grade carried forward from an earlier inspection (ungraded visit since)'
|
||||
: 'Overall grade (older-style inspection)'}
|
||||
</span>
|
||||
{current && <span className={s.small}>{gradeSourceLine(current)}</span>}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -179,7 +175,7 @@ export function CompareOfsted({
|
||||
<Measure label="Result">
|
||||
{schools.map((school, i) => (
|
||||
<Cell key={school.urn} school={school} index={i}>
|
||||
<ResultCell display={displays[i]} />
|
||||
<ResultCell display={displays[i]} current={data[String(school.urn)]?.ofsted?.current_grade ?? null} />
|
||||
</Cell>
|
||||
))}
|
||||
</Measure>
|
||||
@@ -187,19 +183,15 @@ export function CompareOfsted({
|
||||
<Measure label="Inspected">
|
||||
{schools.map((school, i) => {
|
||||
const ofsted = data[String(school.urn)]?.ofsted;
|
||||
// A report card is dated by its OWN inspection date. The legacy
|
||||
// inspection_date belongs to an older inspection and must never
|
||||
// be shown against a report card (report cards exist only from
|
||||
// Nov 2025).
|
||||
const dateIso =
|
||||
displays[i].kind === 'report_card'
|
||||
? ofsted?.rc_inspection_date ?? null
|
||||
: ofsted?.inspection_date ?? null;
|
||||
// The school's latest visit of any kind (a report card's own date
|
||||
// when there is one), never an older inspection a grade comes from.
|
||||
const dateIso = ofsted?.latest_visit?.date ?? ofsted?.rc_inspection_date ?? null;
|
||||
const age = yearsSince(dateIso);
|
||||
return (
|
||||
<Cell key={school.urn} school={school} index={i}>
|
||||
{formatInspectionDate(dateIso)}{' '}
|
||||
{age != null && age > 4 && <Chip tone="neutral">4+ years ago</Chip>}
|
||||
{ofsted?.latest_visit?.outcome && <span className={s.small}>{ofsted.latest_visit.outcome}</span>}
|
||||
</Cell>
|
||||
);
|
||||
})}
|
||||
|
||||
Reference in new issue
Block a user