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>
44 lines
1.3 KiB
TypeScript
44 lines
1.3 KiB
TypeScript
/**
|
|
* Shared primitives for the school detail sections, mirroring
|
|
* components/compare/sectionShared.tsx.
|
|
*
|
|
* Deliberately minimal: the sections were extracted as verbatim moves from the
|
|
* two detail views, so wrapping their markup in heavyweight primitives would
|
|
* risk changing the DOM the CSS modules depend on. This provides only the
|
|
* outer <section> shell every section shares, plus the stylesheet.
|
|
*
|
|
* All section components are SERVER components — no 'use client' anywhere in
|
|
* this directory except AdmissionsViewToggle.
|
|
*/
|
|
|
|
import type { ReactNode } from 'react';
|
|
import styles from './schoolSections.module.css';
|
|
|
|
export const sectionStyles = styles;
|
|
|
|
/** Tone class for a progress score: positive, negative, or neutral. */
|
|
export function progressClass(val: number | null | undefined): string {
|
|
if (val == null) return '';
|
|
if (val > 0) return styles.progressPositive;
|
|
if (val < 0) return styles.progressNegative;
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* The section shell. `id` must match the id buildNavItems emits, because the
|
|
* sticky nav's scroll-spy locates sections with document.getElementById.
|
|
*/
|
|
export function Section({
|
|
id,
|
|
children,
|
|
}: {
|
|
id: string;
|
|
children: ReactNode;
|
|
}) {
|
|
return (
|
|
<section id={id} className={styles.card}>
|
|
{children}
|
|
</section>
|
|
);
|
|
}
|