61 lines
2.4 KiB
TypeScript
61 lines
2.4 KiB
TypeScript
/**
|
|||
|
|
* Shared logic and copy for the "last distance offered" figure.
|
||
|
|
*
|
||
|
|
* The primary and secondary admissions sections lay their metrics out
|
||
|
|
* differently (a seamless tile grid vs. metric cards), so the markup is not
|
||
|
|
* shared — but the words are. Every caveat below is doing a specific job, and
|
||
|
|
* a figure that appeared on one template without them would be misleading in a
|
||
|
|
* way the other template was not:
|
||
|
|
*
|
||
|
|
* * The year, because a cut-off is the outcome of one particular admissions
|
||
|
|
* round and means nothing detached from it.
|
||
|
|
* * "not a fixed catchment", because that is the inference a parent will
|
||
|
|
* otherwise draw, and it is wrong — the distance moves every year.
|
||
|
|
* * The route count, because on a banded school the headline is the widest
|
||
|
|
* of several cut-offs and does not apply to every child.
|
||
|
|
*/
|
||
|
|
|
||
|
|
import type { SchoolAdmissionDistance } from '@/lib/types';
|
||
|
|
import { formatCutoffDistance, formatEntryYear } from '@/lib/utils';
|
||
|
|
|
||
|
|
export interface CutoffDisplay {
|
||
|
|
/** Headline figure, e.g. "0.31 miles". */
|
||
|
|
primary: string;
|
||
|
|
/** Supporting conversion, e.g. "500 m". */
|
||
|
|
secondary: string;
|
||
|
|
/** Entry point the figure belongs to, e.g. "September 2025". */
|
||
|
|
entryYear: string;
|
||
|
|
/** Present only where several admission routes were collapsed into one figure. */
|
||
|
|
routeNote: string | null;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** What the cut-off measures, and what it does not. Identical on both templates. */
|
||
|
|
export const CUTOFF_NOTE =
|
||
|
|
'The furthest home offered a place, after higher priorities such as siblings, ' +
|
||
|
|
'faith and EHCP were applied. It is not a fixed catchment — it moves every year ' +
|
||
|
|
'with the number of applications.';
|
||
|
|
|
||
|
|
/** Straight-line, because that is how councils measure it. */
|
||
|
|
export const CUTOFF_MEASUREMENT_NOTE = 'Measured in a straight line from the school.';
|
||
|
|
|
||
|
|
export function describeCutoff(
|
||
|
|
distance: SchoolAdmissionDistance | null | undefined
|
||
|
|
): CutoffDisplay | null {
|
||
|
|
if (!distance) return null;
|
||
|
|
|
||
|
|
const figure = formatCutoffDistance(distance.distance_m);
|
||
|
|
if (!figure) return null;
|
||
|
|
|
||
|
|
const routes = distance.route_count ?? 1;
|
||
|
|
|
||
|
|
return {
|
||
|
|
primary: figure.primary,
|
||
|
|
secondary: figure.secondary,
|
||
|
|
entryYear: formatEntryYear(distance.year),
|
||
|
|
routeNote:
|
||
|
|
routes > 1
|
||
|
|
? `Furthest of ${routes} admission routes at this school — the one that ` +
|
||
|
|
'applies to your child may have had a shorter cut-off.'
|
||
|
|
: null,
|
||
|
|
};
|
||
|
|
}
|