diff --git a/nextjs-app/components/LeafletMapInner.tsx b/nextjs-app/components/LeafletMapInner.tsx index cc7e2f6..588bedf 100644 --- a/nextjs-app/components/LeafletMapInner.tsx +++ b/nextjs-app/components/LeafletMapInner.tsx @@ -33,6 +33,10 @@ interface LeafletMapInnerProps { // Popup helpers (must work in plain JS string templates — no React / CSS Modules) // --------------------------------------------------------------------------- +function escapeHtml(s: string): string { + return s.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); +} + interface PopupBadge { label: string; style: string; @@ -135,8 +139,10 @@ export default function LeafletMapInner({ schools, center, zoom, referencePoint, if (laAvg != null) { const diff = Math.round((score - laAvg) * 10) / 10; const sign = diff >= 0 ? '+' : ''; + // Att8 scores range 0–90 in 0.1 increments; ±0.5 is meaningful here + // vs primary RWM % where ±2 pts is the threshold const colour = diff >= 0.5 ? '#2d7d7d' : diff <= -0.5 ? '#e07256' : '#8a847a'; - const laName = school.local_authority ?? 'LA'; + const laName = escapeHtml(school.local_authority ?? 'LA'); deltaLine = `
${sign}${diff} vs ${laName} avg
`; } metricHtml = `
@@ -167,11 +173,11 @@ export default function LeafletMapInner({ schools, center, zoom, referencePoint, const popupContent = `
- ${school.school_name} + ${escapeHtml(school.school_name)} ${badge.label}
- ${phaseLabel}${school.local_authority ? ` · ${school.local_authority}` : ''}${distanceStr} + ${phaseLabel}${school.local_authority ? ` · ${escapeHtml(school.local_authority)}` : ''}${distanceStr}
${metricHtml} View Details → @@ -201,7 +207,7 @@ export default function LeafletMapInner({ schools, center, zoom, referencePoint, return () => { // Don't destroy map on every update, just clean markers }; - }, [schools, center, zoom, referencePoint, onMarkerClick]); + }, [schools, center, zoom, referencePoint, onMarkerClick, nationalAvgRwm, laAverages]); // Cleanup map on unmount useEffect(() => {