This commit is contained in:
Andras Schmelczer 2026-06-25 22:29:52 +01:00
parent 2efa4d9f47
commit 5e73287eaf
99 changed files with 6392 additions and 1462 deletions

View file

@ -1,4 +1,6 @@
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import type { TFunction } from 'i18next';
import type { SchoolMetadata } from '../../types';
import { POI_GROUP_COLORS } from '../../lib/consts';
@ -32,7 +34,7 @@ function normalizeSchoolWebsiteUrl(raw: string): string | null {
return null;
}
function renderSchoolMetadata(school: SchoolMetadata) {
function renderSchoolMetadata(school: SchoolMetadata, t: TFunction) {
// First line collects the headline classification (phase, type, religious
// character) so the popup is scannable even when most fields are absent.
const headline: string[] = [];
@ -41,11 +43,11 @@ function renderSchoolMetadata(school: SchoolMetadata) {
const pupilsLine =
school.pupils !== undefined && school.capacity !== undefined
? `${school.pupils.toLocaleString()} / ${school.capacity.toLocaleString()} pupils`
? `${school.pupils.toLocaleString()} / ${school.capacity.toLocaleString()} ${t('poiPopup.school.pupils')}`
: school.pupils !== undefined
? `${school.pupils.toLocaleString()} pupils`
? `${school.pupils.toLocaleString()} ${t('poiPopup.school.pupils')}`
: school.capacity !== undefined
? `Capacity ${school.capacity.toLocaleString()}`
? `${t('poiPopup.school.capacity')} ${school.capacity.toLocaleString()}`
: null;
const websiteUrl = school.website ? normalizeSchoolWebsiteUrl(school.website) : null;
@ -54,69 +56,69 @@ function renderSchoolMetadata(school: SchoolMetadata) {
<dl className="mt-2 grid grid-cols-[auto_1fr] gap-x-2 gap-y-0.5 text-xs text-warm-600 dark:text-warm-300">
{headline.length > 0 && (
<>
<dt className="text-warm-500 dark:text-warm-400">Type</dt>
<dt className="text-warm-500 dark:text-warm-400">{t('poiPopup.school.type')}</dt>
<dd className="dark:text-warm-200">{headline.join(' · ')}</dd>
</>
)}
{school.age_range && (
<>
<dt className="text-warm-500 dark:text-warm-400">Ages</dt>
<dt className="text-warm-500 dark:text-warm-400">{t('poiPopup.school.ages')}</dt>
<dd className="dark:text-warm-200">{school.age_range}</dd>
</>
)}
{school.gender && school.gender !== 'Mixed' && (
<>
<dt className="text-warm-500 dark:text-warm-400">Gender</dt>
<dt className="text-warm-500 dark:text-warm-400">{t('poiPopup.school.gender')}</dt>
<dd className="dark:text-warm-200">{school.gender}</dd>
</>
)}
{pupilsLine && (
<>
<dt className="text-warm-500 dark:text-warm-400">Pupils</dt>
<dt className="text-warm-500 dark:text-warm-400">{t('poiPopup.school.pupilsLabel')}</dt>
<dd className="dark:text-warm-200">{pupilsLine}</dd>
</>
)}
{school.fsm_percent !== undefined && (
<>
<dt className="text-warm-500 dark:text-warm-400">Free meal</dt>
<dt className="text-warm-500 dark:text-warm-400">{t('poiPopup.school.freeMeal')}</dt>
<dd className="dark:text-warm-200">{school.fsm_percent.toFixed(1)}%</dd>
</>
)}
{school.ofsted_rating && (
<>
<dt className="text-warm-500 dark:text-warm-400">Ofsted</dt>
<dt className="text-warm-500 dark:text-warm-400">{t('poiPopup.school.ofsted')}</dt>
<dd className="dark:text-warm-200">{school.ofsted_rating}</dd>
</>
)}
{school.sixth_form === 'Has a sixth form' && (
<>
<dt className="text-warm-500 dark:text-warm-400">Sixth form</dt>
<dd className="dark:text-warm-200">Yes</dd>
<dt className="text-warm-500 dark:text-warm-400">{t('poiPopup.school.sixthForm')}</dt>
<dd className="dark:text-warm-200">{t('common.yes')}</dd>
</>
)}
{school.religious_character &&
school.religious_character !== 'Does not apply' &&
school.religious_character !== 'None' && (
<>
<dt className="text-warm-500 dark:text-warm-400">Religion</dt>
<dt className="text-warm-500 dark:text-warm-400">{t('poiPopup.school.religion')}</dt>
<dd className="dark:text-warm-200">{school.religious_character}</dd>
</>
)}
{school.admissions_policy && (
<>
<dt className="text-warm-500 dark:text-warm-400">Admissions</dt>
<dt className="text-warm-500 dark:text-warm-400">{t('poiPopup.school.admissions')}</dt>
<dd className="dark:text-warm-200">{school.admissions_policy}</dd>
</>
)}
{school.trust && (
<>
<dt className="text-warm-500 dark:text-warm-400">Trust</dt>
<dt className="text-warm-500 dark:text-warm-400">{t('poiPopup.school.trust')}</dt>
<dd className="dark:text-warm-200">{school.trust}</dd>
</>
)}
{(school.address || school.postcode) && (
<>
<dt className="text-warm-500 dark:text-warm-400">Address</dt>
<dt className="text-warm-500 dark:text-warm-400">{t('poiPopup.school.address')}</dt>
<dd className="dark:text-warm-200">
{[school.address, school.postcode].filter(Boolean).join(', ')}
</dd>
@ -124,19 +126,19 @@ function renderSchoolMetadata(school: SchoolMetadata) {
)}
{school.local_authority && (
<>
<dt className="text-warm-500 dark:text-warm-400">LA</dt>
<dt className="text-warm-500 dark:text-warm-400">{t('poiPopup.school.localAuthority')}</dt>
<dd className="dark:text-warm-200">{school.local_authority}</dd>
</>
)}
{school.head_name && (
<>
<dt className="text-warm-500 dark:text-warm-400">Head</dt>
<dt className="text-warm-500 dark:text-warm-400">{t('poiPopup.school.head')}</dt>
<dd className="dark:text-warm-200">{school.head_name}</dd>
</>
)}
{websiteUrl && (
<>
<dt className="text-warm-500 dark:text-warm-400">Website</dt>
<dt className="text-warm-500 dark:text-warm-400">{t('poiPopup.school.website')}</dt>
<dd className="truncate">
<a
href={websiteUrl}
@ -158,6 +160,7 @@ export const PoiPopupCardContent = memo(function PoiPopupCardContent({
}: {
poi: PoiPopupCardData;
}) {
const { t } = useTranslation();
return (
<div className="px-3 py-2 max-w-[280px]">
<div className="flex items-center gap-2">
@ -182,7 +185,7 @@ export const PoiPopupCardContent = memo(function PoiPopupCardContent({
</div>
</div>
</div>
{poi.school && renderSchoolMetadata(poi.school)}
{poi.school && renderSchoolMetadata(poi.school, t)}
</div>
);
});