From 2b4cf20d75e6be1bc622cad2a7b9c71f13d12312 Mon Sep 17 00:00:00 2001 From: Tudor Date: Fri, 28 Aug 2026 16:15:21 +0100 Subject: [PATCH] feat(destinations): the post-16 section, replacing the placeholder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'Post-16 destination data coming soon' note is deleted rather than reworded: for a school with no sixth form the truthful statement is that the question does not apply, and a placeholder there implies something is missing. hasSixthForm and .sixthFormNote go with it — nothing else used them. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01BvdDKvFFSZuMVDH5fEyTob --- .../Post16DestinationsSection.test.tsx | 45 +++++++++++++++++++ .../school/Post16DestinationsSection.tsx | 40 +++++++++++++++++ .../school/SecondaryAdmissionsSection.tsx | 8 +--- .../school/SecondarySchoolSections.tsx | 8 +++- .../school/schoolSections.module.css | 11 +---- 5 files changed, 94 insertions(+), 18 deletions(-) create mode 100644 nextjs-app/__tests__/components/Post16DestinationsSection.test.tsx create mode 100644 nextjs-app/components/school/Post16DestinationsSection.tsx diff --git a/nextjs-app/__tests__/components/Post16DestinationsSection.test.tsx b/nextjs-app/__tests__/components/Post16DestinationsSection.test.tsx new file mode 100644 index 0000000..946d88f --- /dev/null +++ b/nextjs-app/__tests__/components/Post16DestinationsSection.test.tsx @@ -0,0 +1,45 @@ +import { render, screen } from '@testing-library/react'; +import { Post16DestinationsSection } from '@/components/school/Post16DestinationsSection'; +import type { DestinationPhase } from '@/lib/types'; + +const phase: DestinationPhase = { + cohort_year: '2022/23', + groups: { + all: { + cohort: 96, + categories: [ + { category: 'higher_education', pupils: 56, percentage: 58.3, status: 'published' }, + { category: 'further_education', pupils: 12, percentage: 12.5, status: 'published' }, + { category: 'apprenticeship', pupils: 9, percentage: 9.4, status: 'published' }, + { category: 'employment', pupils: 13, percentage: 13.5, status: 'published' }, + { category: 'not_sustained', pupils: 6, percentage: 6.3, status: 'published' }, + ], + aggregates: {}, + }, + }, +}; + +describe('Post16DestinationsSection', () => { + it('names the Year 13 cohort, not Year 11', () => { + const { container } = render(); + expect(container.textContent).toMatch(/Year 13/); + expect(container.textContent).not.toMatch(/Year 11/); + }); + + it('reports higher education destinations', () => { + render(); + expect(screen.getByText(/UK higher education/i)).toBeInTheDocument(); + }); + + it('uses its own anchor so the nav does not collide with After Year 11', () => { + const { container } = render(); + expect(container.querySelector('#post16-destinations')).toBeTruthy(); + expect(container.querySelector('#destinations')).toBeNull(); + }); + + it('renders nothing when no group carries categories', () => { + const empty: DestinationPhase = { cohort_year: '2022/23', groups: {} }; + const { container } = render(); + expect(container.firstChild).toBeNull(); + }); +}); diff --git a/nextjs-app/components/school/Post16DestinationsSection.tsx b/nextjs-app/components/school/Post16DestinationsSection.tsx new file mode 100644 index 0000000..e5113eb --- /dev/null +++ b/nextjs-app/components/school/Post16DestinationsSection.tsx @@ -0,0 +1,40 @@ +/** + * Post16DestinationsSection — where a school's Year 13 leavers went. + * Server component. + * + * A separate publication, a separate cohort and a separate question from + * After Year 11, so it is a separate section rather than a tab: a parent + * choosing a secondary and a student choosing a sixth form are not the same + * reader. + * + * Not rendered at all for a school without post-16 provision. A "no data" + * placeholder there would imply something is missing, when the truthful + * statement is that the question does not apply — which is why the old + * "Post-16 destination data coming soon" note is gone rather than reworded. + */ + +import type { DestinationPhase } from '@/lib/types'; +import { Section, sectionStyles } from './sectionShared'; +import { DestinationsView } from './DestinationsView'; + +export function Post16DestinationsSection({ + destinations, +}: { destinations: DestinationPhase }) { + const hasContent = Object.values(destinations.groups) + .some(group => (group?.categories?.length ?? 0) > 0); + if (!hasContent) return null; + + const cohort = destinations.groups.all?.cohort ?? null; + const year = destinations.cohort_year; + + return ( +
+

After the sixth form

+

+ Where {cohort ? `the ${cohort} students` : 'the students'} who finished + Year 13{year ? ` in ${year}` : ''} went next. +

+ +
+ ); +} diff --git a/nextjs-app/components/school/SecondaryAdmissionsSection.tsx b/nextjs-app/components/school/SecondaryAdmissionsSection.tsx index 49c8970..73a8e36 100644 --- a/nextjs-app/components/school/SecondaryAdmissionsSection.tsx +++ b/nextjs-app/components/school/SecondaryAdmissionsSection.tsx @@ -15,7 +15,7 @@ import { } from './lastDistanceOffered'; export function SecondaryAdmissionsSection({ - admissions, admissionsHistory, admissionDistance, schoolInfo, hasSixthForm, + admissions, admissionsHistory, admissionDistance, schoolInfo, }: { /* Nullable for the same reason as the primary section: a school can have a published cut-off and no EES admissions row. */ @@ -23,7 +23,6 @@ export function SecondaryAdmissionsSection({ admissionsHistory: SchoolAdmissions[]; admissionDistance: SchoolAdmissionDistance | null; schoolInfo: School; - hasSixthForm: boolean; }) { const cutoff = describeCutoff(admissionDistance); // Moved with this section from SecondarySchoolDetailView, its only consumer. @@ -112,11 +111,6 @@ export function SecondaryAdmissionsSection({

)} - {hasSixthForm && ( -
- This school has a sixth form (Post-16 provision). Post-16 destination data coming soon. -
- )} ); } diff --git a/nextjs-app/components/school/SecondarySchoolSections.tsx b/nextjs-app/components/school/SecondarySchoolSections.tsx index 8530f47..f3542ef 100644 --- a/nextjs-app/components/school/SecondarySchoolSections.tsx +++ b/nextjs-app/components/school/SecondarySchoolSections.tsx @@ -21,6 +21,7 @@ import type { SecondaryFlags } from '@/lib/schoolSections'; import { OfstedSection } from './OfstedSection'; import { GcseSection } from './GcseSection'; import { DestinationsSection } from './DestinationsSection'; +import { Post16DestinationsSection } from './Post16DestinationsSection'; import { SecondaryAdmissionsSection } from './SecondaryAdmissionsSection'; import { DistanceSection } from './DistanceSection'; import { SecondaryHistorySection } from './SecondaryHistorySection'; @@ -94,6 +95,12 @@ export function SecondarySchoolSections({ )} + {/* Sixth-form schools only. Absent, not placeheld, for a school with no + post-16 provision — the question simply does not apply there. */} + {flags.hasKs5Destinations && destinations?.ks5 && ( + + )} + {/* See PrimarySchoolSections: distance and EES admissions are independent sources, so either one warrants the section. */} {(admissions || admissionDistance) && ( @@ -102,7 +109,6 @@ export function SecondarySchoolSections({ admissionDistance={admissionDistance} admissionsHistory={admissionsHistory} schoolInfo={schoolInfo} - hasSixthForm={flags.hasSixthForm} /> )} diff --git a/nextjs-app/components/school/schoolSections.module.css b/nextjs-app/components/school/schoolSections.module.css index 7e26d29..931fee0 100644 --- a/nextjs-app/components/school/schoolSections.module.css +++ b/nextjs-app/components/school/schoolSections.module.css @@ -1883,15 +1883,7 @@ color: var(--phase-secondary-text); border: 1px solid rgba(var(--status-above-rgb), 0.2); } -.sixthFormNote { - margin-top: 1rem; - padding: 0.625rem 0.875rem; - background: var(--bg-secondary); - border-radius: 6px; - font-size: 0.825rem; - color: var(--text-secondary); - border-left: 3px solid var(--brand); -} + .genderSplitHint { font-size: 0.7rem; color: var(--text-muted); @@ -2107,7 +2099,6 @@ border-top: 1px solid var(--border); } - .cutoffMapFigure { /* Enough to read a set of concentric rings and no more — this is a diagram of a number, not a map anyone navigates by. */