import { useEffect, useState, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import { tDynamic } from '../../i18n'; import { ChevronIcon } from '../ui/icons/ChevronIcon'; import { SubNav } from '../ui/SubNav'; type LearnTab = 'data-sources' | 'faq' | 'support'; interface DataSourceDef { id: string; url: string; license: string; optOutUrl?: string; } const DATA_SOURCE_DEFS: DataSourceDef[] = [ { id: 'price-paid', url: 'https://www.gov.uk/government/statistical-data-sets/price-paid-data-downloads', license: 'Open Government Licence v3.0', }, { id: 'epc', url: 'https://epc.opendatacommunities.org/downloads/domestic', license: 'Open Government Licence v3.0', optOutUrl: 'https://www.gov.uk/guidance/energy-performance-certificates-opt-out-of-public-disclosure', }, { id: 'nspl', url: 'https://www.arcgis.com/sharing/rest/content/items/077631e063eb4e1ab43575d01381ec33/data', license: 'Open Government Licence v3.0', }, { id: 'iod', url: 'https://www.gov.uk/government/statistics/english-indices-of-deprivation-2025', license: 'Open Government Licence v3.0', }, { id: 'ethnicity', url: 'https://www.ethnicity-facts-figures.service.gov.uk/uk-population-by-ethnicity/national-and-regional-populations/regional-ethnic-diversity/latest/#download-the-data', license: 'Open Government Licence v3.0', }, { id: 'crime', url: 'https://data.police.uk/data/', license: 'Open Government Licence v3.0' }, { id: 'osm-pois', url: 'https://download.geofabrik.de/europe/great-britain-latest.osm.pbf', license: 'Open Data Commons Open Database License (ODbL)', }, { id: 'os-open-greenspace', url: 'https://osdatahub.os.uk/downloads/open/OpenGreenspace', license: 'Open Government Licence v3.0', }, { id: 'naptan', url: 'https://naptan.dft.gov.uk/naptan/schema/2.4/doc/NaPTANSchemaGuide-2.4-v0.57.pdf', license: 'Open Government Licence v3.0', }, { id: 'noise', url: 'https://environment.data.gov.uk/spatialdata/road-noise-all-metrics-england-round-4/wcs', license: 'Open Government Licence v3.0', }, { id: 'ofsted', url: 'https://www.gov.uk/government/statistical-data-sets/monthly-management-information-ofsteds-school-inspections-outcomes', license: 'Open Government Licence v3.0', }, { id: 'broadband', url: 'https://www.ofcom.org.uk/phones-and-broadband/coverage-and-speeds/connected-nations-20252/data-downloads-2025', license: 'Open Government Licence v3.0', }, { id: 'council-tax', url: 'https://www.gov.uk/government/statistics/council-tax-levels-set-by-local-authorities-in-england-2025-to-2026', license: 'Open Government Licence v3.0', }, { id: 'ons-rental', url: 'https://www.ons.gov.uk/peoplepopulationandcommunity/housing/datasets/privaterentalmarketsummarystatisticsinengland', license: 'Open Government Licence v3.0', }, { id: 'election-results', url: 'https://electionresults.parliament.uk/general-elections/6', license: 'Open Parliament Licence v3.0', }, ]; // Maps data source id → [nameKey, originKey, useKey] in en.ts learnPage section const DS_KEYS: Record = { 'price-paid': [ 'learnPage.dsPricePaidName', 'learnPage.dsPricePaidOrigin', 'learnPage.dsPricePaidUse', ], epc: ['learnPage.dsEpcName', 'learnPage.dsEpcOrigin', 'learnPage.dsEpcUse'], nspl: ['learnPage.dsNsplName', 'learnPage.dsNsplOrigin', 'learnPage.dsNsplUse'], iod: ['learnPage.dsIodName', 'learnPage.dsIodOrigin', 'learnPage.dsIodUse'], ethnicity: [ 'learnPage.dsEthnicityName', 'learnPage.dsEthnicityOrigin', 'learnPage.dsEthnicityUse', ], crime: ['learnPage.dsCrimeName', 'learnPage.dsCrimeOrigin', 'learnPage.dsCrimeUse'], 'osm-pois': ['learnPage.dsOsmName', 'learnPage.dsOsmOrigin', 'learnPage.dsOsmUse'], 'os-open-greenspace': [ 'learnPage.dsGreenspaceName', 'learnPage.dsGreenspaceOrigin', 'learnPage.dsGreenspaceUse', ], naptan: ['learnPage.dsNaptanName', 'learnPage.dsNaptanOrigin', 'learnPage.dsNaptanUse'], noise: ['learnPage.dsNoiseName', 'learnPage.dsNoiseOrigin', 'learnPage.dsNoiseUse'], ofsted: ['learnPage.dsOfstedName', 'learnPage.dsOfstedOrigin', 'learnPage.dsOfstedUse'], broadband: [ 'learnPage.dsBroadbandName', 'learnPage.dsBroadbandOrigin', 'learnPage.dsBroadbandUse', ], 'council-tax': [ 'learnPage.dsCouncilTaxName', 'learnPage.dsCouncilTaxOrigin', 'learnPage.dsCouncilTaxUse', ], 'ons-rental': ['learnPage.dsRentalName', 'learnPage.dsRentalOrigin', 'learnPage.dsRentalUse'], 'election-results': [ 'learnPage.dsElectionName', 'learnPage.dsElectionOrigin', 'learnPage.dsElectionUse', ], }; function FAQItemCard({ question, answer }: { question: string; answer: string }) { const [open, setOpen] = useState(false); return (
{open && (

{answer}

)}
); } export default function LearnPage() { const { t } = useTranslation(); const [tab, setTab] = useState('faq'); const [highlightedId, setHighlightedId] = useState(null); const cardRefs = useRef>({}); const scrollContainerRef = useRef(null); const LEARN_TABS = [ { key: 'faq', label: t('learnPage.faq') }, { key: 'data-sources', label: t('learnPage.dataSources') }, { key: 'support', label: t('learnPage.support') }, ]; const FAQ_SECTIONS = [ { title: t('learnPage.faqFindingTitle'), items: [ { question: t('learnPage.faqFinding1Q'), answer: t('learnPage.faqFinding1A') }, { question: t('learnPage.faqFinding2Q'), answer: t('learnPage.faqFinding2A') }, { question: t('learnPage.faqFinding3Q'), answer: t('learnPage.faqFinding3A') }, ], }, { title: t('learnPage.faqCommuteTitle'), items: [ { question: t('learnPage.faqCommute1Q'), answer: t('learnPage.faqCommute1A') }, { question: t('learnPage.faqCommute2Q'), answer: t('learnPage.faqCommute2A') }, ], }, { title: t('learnPage.faqBudgetTitle'), items: [ { question: t('learnPage.faqBudget1Q'), answer: t('learnPage.faqBudget1A') }, { question: t('learnPage.faqBudget2Q'), answer: t('learnPage.faqBudget2A') }, ], }, { title: t('learnPage.faqSafetyTitle'), items: [ { question: t('learnPage.faqSafety1Q'), answer: t('learnPage.faqSafety1A') }, { question: t('learnPage.faqSafety2Q'), answer: t('learnPage.faqSafety2A') }, ], }, { title: t('learnPage.faqFamiliesTitle'), items: [ { question: t('learnPage.faqFamilies1Q'), answer: t('learnPage.faqFamilies1A') }, { question: t('learnPage.faqFamilies2Q'), answer: t('learnPage.faqFamilies2A') }, ], }, { title: t('learnPage.faqEnvironmentTitle'), items: [ { question: t('learnPage.faqEnv1Q'), answer: t('learnPage.faqEnv1A') }, { question: t('learnPage.faqEnv2Q'), answer: t('learnPage.faqEnv2A') }, { question: t('learnPage.faqEnv3Q'), answer: t('learnPage.faqEnv3A') }, ], }, { title: t('learnPage.faqWhyTitle'), items: [ { question: t('learnPage.faqWhy1Q'), answer: t('learnPage.faqWhy1A') }, { question: t('learnPage.faqWhy2Q'), answer: t('learnPage.faqWhy2A') }, { question: t('learnPage.faqWhy3Q'), answer: t('learnPage.faqWhy3A') }, ], }, { title: t('learnPage.faqPricingTitle'), items: [ { question: t('learnPage.faqPricing1Q'), answer: t('learnPage.faqPricing1A') }, { question: t('learnPage.faqPricing2Q'), answer: t('learnPage.faqPricing2A') }, { question: t('learnPage.faqPricing3Q'), answer: t('learnPage.faqPricing3A') }, { question: t('learnPage.faqPricing4Q'), answer: t('learnPage.faqPricing4A') }, ], }, { title: t('learnPage.faqTipsTitle'), items: [ { question: t('learnPage.faqTips1Q'), answer: t('learnPage.faqTips1A') }, { question: t('learnPage.faqTips2Q'), answer: t('learnPage.faqTips2A') }, { question: t('learnPage.faqTips3Q'), answer: t('learnPage.faqTips3A') }, ], }, ]; useEffect(() => { function handleHash() { const hash = window.location.hash.replace('#', ''); if (hash === 'faq') { setTab('faq'); setHighlightedId(null); } else if (hash === 'support') { setTab('support'); setHighlightedId(null); } else if (hash && DATA_SOURCE_DEFS.some((s) => s.id === hash)) { setTab('data-sources'); setHighlightedId(hash); setTimeout(() => { cardRefs.current[hash]?.scrollIntoView({ behavior: 'smooth', block: 'center' }); }, 100); } else { setHighlightedId(null); } } handleHash(); window.addEventListener('hashchange', handleHash); return () => window.removeEventListener('hashchange', handleHash); }, []); useEffect(() => { scrollContainerRef.current?.scrollTo(0, 0); }, [tab]); const switchTab = (key: string) => { setTab(key as LearnTab); setHighlightedId(null); }; return (
{tab === 'data-sources' ? ( <>

{t('learnPage.dataSourcesIntro', { count: DATA_SOURCE_DEFS.length })}

{DATA_SOURCE_DEFS.map((source) => { const keys = DS_KEYS[source.id]; const [nameKey, originKey, useKey] = keys; return (
{ cardRefs.current[source.id] = el; }} className={`bg-white dark:bg-warm-800 rounded-lg border p-5 ${ highlightedId === source.id ? 'border-teal-400 ring-2 ring-teal-400' : 'border-warm-200 dark:border-warm-700' }`} >

{tDynamic(nameKey)}

{source.license}

{t('learnPage.source')} {tDynamic(originKey)}

{tDynamic(useKey)}

{source.url} {source.optOutUrl && ( )}
); })}
) : tab === 'faq' ? (

{t('learnPage.faqIntro')}

{FAQ_SECTIONS.map((section) => (

{section.title}

{section.items.map((item, index) => ( ))}
))}
) : (

{t('learnPage.supportIntro')}

{t('accountPage.needHelp')}

support@perfect-postcode.co.uk

{t('accountPage.responseTime')}

)}
); }