From 15c00556874e6fedd0c5c4576f9cd9a8f2d7787d Mon Sep 17 00:00:00 2001 From: Tudor Date: Sun, 29 Mar 2026 14:48:06 +0100 Subject: [PATCH] =?UTF-8?q?refactor(detail):=20align=20secondary=20school?= =?UTF-8?q?=20page=20with=20primary=20=E2=80=94=20scroll-to-section=20nav?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace tab-based show/hide with always-visible sections and anchor link navigation, matching the primary school detail page behaviour. Co-Authored-By: Claude Opus 4.6 --- .../SecondarySchoolDetailView.module.css | 36 +- .../components/SecondarySchoolDetailView.tsx | 1018 +++++++---------- 2 files changed, 414 insertions(+), 640 deletions(-) diff --git a/nextjs-app/components/SecondarySchoolDetailView.module.css b/nextjs-app/components/SecondarySchoolDetailView.module.css index 53fb5d2..c853dd3 100644 --- a/nextjs-app/components/SecondarySchoolDetailView.module.css +++ b/nextjs-app/components/SecondarySchoolDetailView.module.css @@ -199,6 +199,7 @@ cursor: pointer; transition: all 0.15s ease; white-space: nowrap; + text-decoration: none; } .tabBtn:hover { @@ -206,24 +207,6 @@ color: var(--text-primary, #1a1612); } -.tabBtnActive { - background: var(--accent-coral, #e07256); - color: white; - font-weight: 600; -} - -.tabBtnActive:hover { - background: var(--accent-coral-dark, #c45a3f); - color: white; -} - -/* ── Tab content area ────────────────────────────────── */ -.tabContent { - display: flex; - flex-direction: column; - gap: 0; /* cards have their own margin-bottom */ -} - /* ── Card ────────────────────────────────────────────── */ .card { background: var(--bg-card, white); @@ -232,6 +215,7 @@ padding: 1.25rem 1.5rem; margin-bottom: 1rem; box-shadow: var(--shadow-soft); + scroll-margin-top: 6rem; } /* ── Section Title ───────────────────────────────────── */ @@ -581,22 +565,6 @@ color: var(--text-primary, #1a1612); } -/* Tab link (inline button styled as link) */ -.tabLink { - background: none; - border: none; - color: var(--accent-teal, #2d7d7d); - font-size: 0.8125rem; - cursor: pointer; - padding: 0; - margin-top: 0.75rem; - text-decoration: none; -} - -.tabLink:hover { - text-decoration: underline; -} - /* ── Admissions ──────────────────────────────────────── */ .admissionsTypeBadge { border-radius: 6px; diff --git a/nextjs-app/components/SecondarySchoolDetailView.tsx b/nextjs-app/components/SecondarySchoolDetailView.tsx index f432431..76bb24e 100644 --- a/nextjs-app/components/SecondarySchoolDetailView.tsx +++ b/nextjs-app/components/SecondarySchoolDetailView.tsx @@ -1,7 +1,7 @@ /** * SecondarySchoolDetailView Component - * Dedicated detail view for secondary schools with tabbed navigation: - * Overview | Academic | Admissions | Wellbeing | Parents | Finance + * Dedicated detail view for secondary schools with scroll-to-section navigation. + * All sections render at once; the sticky nav scrolls to each. */ 'use client'; @@ -39,7 +39,18 @@ const RC_CATEGORIES = [ { key: 'rc_sixth_form' as const, label: 'Sixth Form' }, ]; -type Tab = 'overview' | 'academic' | 'admissions' | 'wellbeing' | 'parents' | 'finance'; +function progressClass(val: number | null | undefined, modStyles: Record): string { + if (val == null) return ''; + if (val > 0) return modStyles.progressPositive; + if (val < 0) return modStyles.progressNegative; + return ''; +} + +function deprivationDesc(decile: number): string { + if (decile <= 3) return `This school is in one of England's most deprived areas (decile ${decile}/10). Many pupils may face additional challenges at home.`; + if (decile <= 7) return `This school is in an area with average levels of deprivation (decile ${decile}/10).`; + return `This school is in one of England's less deprived areas (decile ${decile}/10).`; +} interface SecondarySchoolDetailViewProps { schoolInfo: School; @@ -55,19 +66,6 @@ interface SecondarySchoolDetailViewProps { finance: SchoolFinance | null; } -function progressClass(val: number | null | undefined, modStyles: Record): string { - if (val == null) return ''; - if (val > 0) return modStyles.progressPositive; - if (val < 0) return modStyles.progressNegative; - return ''; -} - -function deprivationDesc(decile: number): string { - if (decile <= 3) return `This school is in one of England's most deprived areas (decile ${decile}/10). Many pupils may face additional challenges at home.`; - if (decile <= 7) return `This school is in an area with average levels of deprivation (decile ${decile}/10).`; - return `This school is in one of England's less deprived areas (decile ${decile}/10).`; -} - export function SecondarySchoolDetailView({ schoolInfo, yearlyData, ofsted, parentView, admissions, senDetail, deprivation, finance, absenceData, @@ -78,7 +76,6 @@ export function SecondarySchoolDetailView({ const latestResults = yearlyData.length > 0 ? yearlyData[yearlyData.length - 1] : null; - const [activeTab, setActiveTab] = useState('overview'); const [nationalAvg, setNationalAvg] = useState(null); useEffect(() => { @@ -92,9 +89,11 @@ export function SecondarySchoolDetailView({ const hasSixthForm = schoolInfo.age_range?.includes('18') ?? false; const hasFinance = finance != null && finance.per_pupil_spend != null; - const hasParents = parentView != null || ofsted != null; + const hasParents = parentView != null && parentView.total_responses != null && parentView.total_responses > 0; const hasDeprivation = deprivation != null && deprivation.idaci_decile != null; + const hasWellbeing = (latestResults?.sen_support_pct != null || latestResults?.sen_ehcp_pct != null) || hasDeprivation; const p8Suspended = latestResults != null && latestResults.year >= 202425; + const hasResults = latestResults?.attainment_8_score != null; const admissionsTag = (() => { const policy = schoolInfo.admissions_policy?.toLowerCase() ?? ''; @@ -104,15 +103,6 @@ export function SecondarySchoolDetailView({ return null; })(); - const tabs: { key: Tab; label: string }[] = [ - { key: 'overview', label: 'Overview' }, - { key: 'academic', label: 'Academic' }, - { key: 'admissions', label: 'Admissions' }, - { key: 'wellbeing', label: 'Wellbeing' }, - ...(hasParents ? [{ key: 'parents' as Tab, label: 'Parents' }] : []), - ...(hasFinance ? [{ key: 'finance' as Tab, label: 'Finance' }] : []), - ]; - const handleComparisonToggle = () => { if (isInComparison) { removeSchool(schoolInfo.urn); @@ -121,6 +111,16 @@ export function SecondarySchoolDetailView({ } }; + // Build nav items dynamically based on available data + const navItems: { id: string; label: string }[] = []; + if (ofsted) navItems.push({ id: 'ofsted', label: 'Ofsted' }); + if (hasParents) navItems.push({ id: 'parents', label: 'Parents' }); + if (hasResults) navItems.push({ id: 'gcse', label: 'GCSEs' }); + if (admissions) navItems.push({ id: 'admissions', label: 'Admissions' }); + if (hasWellbeing) navItems.push({ id: 'wellbeing', label: 'Wellbeing' }); + if (hasFinance) navItems.push({ id: 'finances', label: 'Finances' }); + if (yearlyData.length > 1) navItems.push({ id: 'history', label: 'History' }); + return (
{/* ── Header ─────────────────────────────────────── */} @@ -189,348 +189,298 @@ export function SecondarySchoolDetailView({
- {/* ── Tab navigation (sticky) ─────────────────────── */} -