refactor(detail): extract sections as server components
Moves ~1,300 lines of section markup out of the two client views into components/school/, mirroring the components/compare/ layout. Twelve section components plus shared primitives, all server components. The only client file is AdmissionsViewToggle, which owns the hidden/aria-pressed state and receives both views as server-rendered children. JSX was extracted mechanically rather than retyped, so the markup the CSS modules depend on is verbatim. Sharing follows measured similarity, not assumption: - Finances (91%) shared. The secondary premises-cost card is gated behind a prop so primary pages are unchanged; enabling it is a one-line follow-up. - Ofsted (80%) shared, but behind a variant prop. The headline similarity hid a real fork: on a school with no overall grade the primary page shows a "Not rated" badge while the secondary shows a four-area OEIF panel, and the disclaimer copy differs. Both preserved exactly; reconciling them is a human decision, not a side effect of a move. - Admissions (14%) and History (40%) kept separate. Not yet wired up -- the old views still render. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* SecondaryAdmissionsSection — secondary pages.
|
||||
*
|
||||
* Not shared with the primary AdmissionsSection: the two were only 14%
|
||||
* similar. This one has no year/trend toggle, so it ships no client
|
||||
* JavaScript at all. Server component.
|
||||
*/
|
||||
|
||||
import type { School, SchoolAdmissions } from '@/lib/types';
|
||||
import { formatPercentage } from '@/lib/utils';
|
||||
import { Section, sectionStyles as styles } from './sectionShared';
|
||||
|
||||
export function SecondaryAdmissionsSection({
|
||||
admissions, schoolInfo, hasSixthForm,
|
||||
}: {
|
||||
admissions: SchoolAdmissions;
|
||||
schoolInfo: School;
|
||||
hasSixthForm: boolean;
|
||||
}) {
|
||||
// Moved with this section from SecondarySchoolDetailView, its only consumer.
|
||||
const admissionsTag = (() => {
|
||||
const policy = schoolInfo.admissions_policy?.toLowerCase() ?? '';
|
||||
if (policy.includes('selective')) return 'Selective';
|
||||
const denom = schoolInfo.religious_denomination ?? '';
|
||||
if (denom && denom !== 'Does not apply') return 'Faith priority';
|
||||
return null;
|
||||
})();
|
||||
|
||||
return (
|
||||
<section id="admissions" className={styles.card}>
|
||||
<h2 className={styles.sectionTitle}>Admissions</h2>
|
||||
|
||||
{admissionsTag && (
|
||||
<div className={`${styles.admissionsTypeBadge} ${admissionsTag === 'Selective' ? styles.admissionsSelective : styles.admissionsFaith}`}>
|
||||
<strong>{admissionsTag}</strong>{' '}
|
||||
{admissionsTag === 'Selective'
|
||||
? '— Entry to this school is by selective examination (e.g. 11+).'
|
||||
: `— This school has a faith-based admissions priority (${schoolInfo.religious_denomination}).`}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className={styles.metricsGrid}>
|
||||
{admissions.places_offered != null && (
|
||||
<div className={styles.metricCard}>
|
||||
<div className={styles.metricLabel}>Year 7 places offered</div>
|
||||
<div className={styles.metricValue}>{admissions.places_offered}</div>
|
||||
</div>
|
||||
)}
|
||||
{admissions.total_applications != null && (
|
||||
<div className={styles.metricCard}>
|
||||
<div className={styles.metricLabel}>Total applications</div>
|
||||
<div className={styles.metricValue}>{admissions.total_applications.toLocaleString()}</div>
|
||||
</div>
|
||||
)}
|
||||
{admissions.first_preference_applications != null && (
|
||||
<div className={styles.metricCard}>
|
||||
<div className={styles.metricLabel}>1st preference applications</div>
|
||||
<div className={styles.metricValue}>{admissions.first_preference_applications.toLocaleString()}</div>
|
||||
</div>
|
||||
)}
|
||||
{admissions.first_preference_offer_pct != null && (
|
||||
<div className={styles.metricCard}>
|
||||
<div className={styles.metricLabel}>Families who got their first choice</div>
|
||||
<div className={styles.metricValue}>{formatPercentage(admissions.first_preference_offer_pct)}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{admissions.oversubscribed != null && (
|
||||
<div className={`${styles.admissionsBadge} ${admissions.oversubscribed ? styles.statusWarn : styles.statusGood}`}>
|
||||
{admissions.oversubscribed
|
||||
? '⚠ Applications exceeded places last year'
|
||||
: '✓ Places were available last year'}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<p className={styles.sectionSubtitle} style={{ marginTop: '1rem' }}>
|
||||
Historical distance cut-off data is not available for this school. Contact the admissions authority for oversubscription criteria details.
|
||||
</p>
|
||||
|
||||
{hasSixthForm && (
|
||||
<div className={styles.sixthFormNote}>
|
||||
This school has a sixth form (Post-16 provision). Post-16 destination data coming soon.
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user