PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m4s
PR Checks / Backend Smoke (pull_request) Successful in 9s
PR Checks / Build Backend (no push) (pull_request) Successful in 11s
PR Checks / Build Frontend (no push) (pull_request) Successful in 46s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 10s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 1m8s
The secondary admissions section words the absence of a cut-off distance:
"<LA> has not published a cut-off distance for this school." That sentence
is true when the authority publishes nothing. It is false when the
authority does publish and the admission_distance flag is simply off — and
off is the current state, so every secondary page with an EES admissions
row has been making a claim about a council on our behalf.
The backend already draws the distinction the copy needs. /api/schools/{urn}
omits the admission_distance key entirely while the flag is dark rather than
sending null, precisely so that "we are not publishing cut-offs" stays
distinguishable from "this school has no cut-off"; lib/types.ts says so in
as many words. The page then collapsed the two with `?? null` before the
section ever saw them.
So stop collapsing it: thread the raw field to SecondarySchoolSections and
word the absence only when the feature is on. Null still gets the sentence
naming the authority — that case is unchanged and still tested.
Primary pages are unaffected: AdmissionsSection carries no absence copy and
renders nothing when there is no figure. DistanceSection already treated
absent and null alike; only its type widens.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FuPUioHpxtaiDNagQvjxyM
52 lines
1.9 KiB
TypeScript
52 lines
1.9 KiB
TypeScript
/**
|
|
* DistanceSection — "How far away are you?"
|
|
*
|
|
* The section exists to answer one question a parent cannot answer from a
|
|
* number alone: whether their own address falls inside it. The figure itself is
|
|
* already on the Admissions tile above; this turns it into something they can
|
|
* act on.
|
|
*
|
|
* Scope note. This used to carry the full published record — chart, year table
|
|
* and a set of shrinking rings. Earlier years are now held back as a paid
|
|
* feature and no longer leave the API at all, so what remains is the latest
|
|
* year and the check against it. The pipeline is unchanged: every published
|
|
* year is still loaded into fact_admission_distance, so restoring history for
|
|
* entitled callers is a serving change rather than a re-collection.
|
|
*
|
|
* Server component; the map and postcode form carry their own client boundary.
|
|
*/
|
|
|
|
import type { School, SchoolAdmissionDistance } from '@/lib/types';
|
|
import { Section, sectionStyles as styles } from './sectionShared';
|
|
import { CutoffMapPanel } from './CutoffMapPanel';
|
|
|
|
export function DistanceSection({
|
|
admissionDistance,
|
|
schoolInfo,
|
|
}: {
|
|
admissionDistance: SchoolAdmissionDistance | null | undefined;
|
|
schoolInfo: School;
|
|
}) {
|
|
// Without a figure there is nothing to compare against, and without
|
|
// coordinates there is nothing to measure — CutoffMapPanel enforces the
|
|
// second, but the section must not render an empty card either way.
|
|
if (
|
|
admissionDistance?.distance_m == null
|
|
|| schoolInfo.latitude == null
|
|
|| schoolInfo.longitude == null
|
|
) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<Section id="distance">
|
|
<h2 className={styles.sectionTitle}>How far away are you?</h2>
|
|
<p className={styles.sectionSubtitle}>
|
|
Check your postcode against the furthest home offered a place in
|
|
September {admissionDistance.year}.
|
|
</p>
|
|
<CutoffMapPanel schoolInfo={schoolInfo} cutoff={admissionDistance} />
|
|
</Section>
|
|
);
|
|
}
|