The row of grey chips under the name mixed the council, a GIAS governance term, the age range and provision, with no labels. Parents could not tell what "Wandsworth" or "Nursery" meant, and selective, faith and fees were missing or buried in the details. The header now prints one fact line (phase pill · ages · type · pupils), then flags only for what applies, in a fixed order: who can apply or what it costs (Fee-paying, Selective, Girls'/Boys' school, the religious character as recorded), then what the school offers (Nursery class, Sixth form). Flags carry no hue: they are facts, not verdicts. The council joins the address unless the address already names it. The details keep headteacher, website, phone, academy trust (hidden when it has the school's own name) and capacity; county, constituency and religious character leave the header. The proposed-to-close strip is unchanged. lib/schoolFacts holds the type label and the flags so the search rows can print the same words. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
67 lines
2.6 KiB
TypeScript
67 lines
2.6 KiB
TypeScript
/**
|
|
* The facts the school header and the search rows print, so a parent reads
|
|
* the same words in the list and on the page.
|
|
*
|
|
* Every value comes from one register field. Nothing is inferred or explained
|
|
* inline, and a missing field prints nothing.
|
|
*/
|
|
|
|
import type { School } from './types';
|
|
import { hasNurseryClasses, hasReligiousCharacter, singleSexLabel } from './utils';
|
|
|
|
/** The search filter's type groups (backend/school_groups.py), without its
|
|
* parenthesised notes: fees have a flag of their own. */
|
|
const TYPE_GROUP_LABELS: Record<string, string> = {
|
|
state: 'State school',
|
|
independent: 'Independent school',
|
|
special: 'Special school (SEND)',
|
|
post16: 'Sixth form or college',
|
|
alternative: 'Alternative provision',
|
|
};
|
|
|
|
/** The school's type in the search filter's terms, or the register's own name
|
|
* for a type in no group (secure units, online providers). */
|
|
export function schoolTypeLabel(school: Pick<School, 'type_group' | 'school_type'>): string | null {
|
|
const grouped = school.type_group ? TYPE_GROUP_LABELS[school.type_group] : undefined;
|
|
return grouped ?? (school.school_type?.trim() || null);
|
|
}
|
|
|
|
/** "condition": changes who can apply or what it costs.
|
|
* "provision": what the school offers. */
|
|
export type SchoolFlagKind = 'condition' | 'provision';
|
|
|
|
export interface SchoolFlag {
|
|
label: string;
|
|
kind: SchoolFlagKind;
|
|
}
|
|
|
|
type FlagFields = Pick<
|
|
School,
|
|
'type_group' | 'admissions_policy' | 'gender' | 'religious_denomination'
|
|
| 'nursery_provision' | 'has_sixth_form' | 'phase'
|
|
>;
|
|
|
|
/**
|
|
* Flags for what applies, in a fixed order: conditions first, then provision.
|
|
*
|
|
* Selective needs the exact value. The register files a partly selective
|
|
* school as "Non-selective", so that value is never printed.
|
|
*/
|
|
export function schoolFlags(school: FlagFields): SchoolFlag[] {
|
|
const flags: SchoolFlag[] = [];
|
|
const condition = (label: string) => flags.push({ label, kind: 'condition' });
|
|
const provision = (label: string) => flags.push({ label, kind: 'provision' });
|
|
const phase = school.phase?.trim().toLowerCase();
|
|
|
|
if (school.type_group === 'independent') condition('Fee-paying');
|
|
if (school.admissions_policy?.trim().toLowerCase() === 'selective') condition('Selective');
|
|
const singleSex = singleSexLabel(school.gender);
|
|
if (singleSex) condition(singleSex);
|
|
if (hasReligiousCharacter(school.religious_denomination)) {
|
|
condition(school.religious_denomination!.trim());
|
|
}
|
|
if (hasNurseryClasses(school.nursery_provision) && phase !== 'nursery') provision('Nursery class');
|
|
if (school.has_sixth_form && phase !== '16 plus') provision('Sixth form');
|
|
return flags;
|
|
}
|