/** * SchoolRow Component * Four-line row for primary school search results * * Line 1: School name · Ofsted badge * Line 2: School type · Age range · Denomination · Gender * Line 3: R,W&M % · Progress score · Pupil count * Line 4: Local authority · Distance */ import type { School } from '@/lib/types'; import { formatPercentage, formatProgress, calculateTrend, schoolUrl } from '@/lib/utils'; import { progressBand } from '@/lib/metrics'; import styles from './SchoolRow.module.css'; const OFSTED_LABELS: Record = { 1: 'Outstanding', 2: 'Good', 3: 'Req. Improvement', 4: 'Inadequate', }; interface SchoolRowProps { school: School; isLocationSearch?: boolean; isInCompare?: boolean; onAddToCompare?: (school: School) => void; onRemoveFromCompare?: (urn: number) => void; } export function SchoolRow({ school, isLocationSearch, isInCompare = false, onAddToCompare, onRemoveFromCompare, }: SchoolRowProps) { const trend = calculateTrend(school.rwm_expected_pct, school.prev_rwm_expected_pct); // Use reading progress as representative; fall back to writing, then maths const progressScore = school.reading_progress ?? school.writing_progress ?? school.maths_progress ?? null; const handleCompareClick = () => { if (isInCompare) { onRemoveFromCompare?.(school.urn); } else { onAddToCompare?.(school); } }; const showGender = school.gender && school.gender.toLowerCase() !== 'mixed'; const showDenomination = school.religious_denomination && school.religious_denomination !== 'Does not apply'; return (
{/* Left: four content lines */}
{/* Line 1: School name + Ofsted badge */}
{school.school_name} {school.ofsted_grade && ( {OFSTED_LABELS[school.ofsted_grade]} {school.ofsted_date && ( {' '}({new Date(school.ofsted_date).getFullYear()}) )} )}
{/* Line 2: Context tags */}
{school.school_type && {school.school_type}} {school.age_range && {school.age_range}} {showDenomination && {school.religious_denomination}} {showGender && {school.gender}}
{/* Line 3: Key stats */}
{school.rwm_expected_pct != null ? ( {formatPercentage(school.rwm_expected_pct, 0)} {school.prev_rwm_expected_pct != null && ( {trend === 'up' && ( )} {trend === 'down' && ( )} {trend === 'stable' && ( )} )} R, W & M ) : ( R, W & M )} {progressScore != null && ( {formatProgress(progressScore)} progress · {progressBand(progressScore)} )} {school.total_pupils != null && ( {school.total_pupils.toLocaleString()} pupils )}
{/* Line 4: Location + distance */}
{school.local_authority && ( {school.local_authority} )} {isLocationSearch && school.distance != null && ( {school.distance.toFixed(1)} mi )}
{/* Right: actions, vertically centred */}
View {(onAddToCompare || onRemoveFromCompare) && ( )}
); }