feat(home): implement redesigned homepage
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 13s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 49s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 13s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 13s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 49s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 13s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
- Hero: Playfair heading with coral italic accent, teal eyebrow pill, richer sub-copy describing both primary and secondary coverage - Discovery: geolocation "Schools near me" button (reverse-geocodes via postcodes.io → /?postcode=…&radius=1), plus Start exploring chips linking to /rankings and /compare - How it works: 3-card grid showing miniature real-UI previews for Performance (primary SATs cascade + secondary Att8 bar), Ofsted inspection card, and side-by-side Compare table - Editorial: text column + factbox (totalSchools, LA count, coverage dates) rendered inside a white card below the how-it-works section - Footer: expanded to 3 columns (brand blurb, Product, Resources); links updated to / /rankings /compare and real gov.uk/ofsted URLs - All new sections visible only on landing (no search active) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,8 +12,8 @@
|
|||||||
|
|
||||||
.content {
|
.content {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 2fr 1fr;
|
grid-template-columns: 1.5fr 1fr 1fr;
|
||||||
gap: 3rem;
|
gap: 2rem;
|
||||||
margin-bottom: 3rem;
|
margin-bottom: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,23 +15,22 @@ export function Footer() {
|
|||||||
<div className={styles.section}>
|
<div className={styles.section}>
|
||||||
<h3 className={styles.title}>SchoolCompare</h3>
|
<h3 className={styles.title}>SchoolCompare</h3>
|
||||||
<p className={styles.description}>
|
<p className={styles.description}>
|
||||||
Compare primary and secondary schools across England.
|
Compare primary and secondary schools across England. Free, independent, built on public data.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.section}>
|
||||||
|
<h4 className={styles.sectionTitle}>Product</h4>
|
||||||
|
<ul className={styles.links}>
|
||||||
|
<li><a href="/" className={styles.link}>Search schools</a></li>
|
||||||
|
<li><a href="/rankings" className={styles.link}>Rankings</a></li>
|
||||||
|
<li><a href="/compare" className={styles.link}>Compare shortlist</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className={styles.section}>
|
<div className={styles.section}>
|
||||||
<h4 className={styles.sectionTitle}>Resources</h4>
|
<h4 className={styles.sectionTitle}>Resources</h4>
|
||||||
<ul className={styles.links}>
|
<ul className={styles.links}>
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
href="https://www.gov.uk/government/organisations/department-for-education"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className={styles.link}
|
|
||||||
>
|
|
||||||
Department for Education
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
href="https://www.gov.uk/school-performance-tables"
|
href="https://www.gov.uk/school-performance-tables"
|
||||||
@@ -42,6 +41,16 @@ export function Footer() {
|
|||||||
School Performance Tables
|
School Performance Tables
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="https://reports.ofsted.gov.uk/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className={styles.link}
|
||||||
|
>
|
||||||
|
Ofsted reports
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,32 +4,73 @@
|
|||||||
|
|
||||||
.heroSection {
|
.heroSection {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 1.5rem;
|
||||||
padding-top: 1rem;
|
padding-top: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heroEyebrow {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
font-size: 0.72rem;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--accent-teal, #2d7d7d);
|
||||||
|
background: rgba(45, 125, 125, 0.1);
|
||||||
|
padding: 0.3rem 0.7rem;
|
||||||
|
border-radius: 999px;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heroEyebrowDot {
|
||||||
|
display: inline-block;
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--accent-teal, #2d7d7d);
|
||||||
}
|
}
|
||||||
|
|
||||||
.heroTitle {
|
.heroTitle {
|
||||||
font-size: 2.5rem;
|
font-size: 3rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--text-primary, #1a1612);
|
color: var(--text-primary, #1a1612);
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.85rem;
|
||||||
line-height: 1.2;
|
line-height: 1.08;
|
||||||
|
letter-spacing: -0.015em;
|
||||||
font-family: var(--font-playfair), 'Playfair Display', serif;
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
|
max-width: 840px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heroEmph {
|
||||||
|
color: var(--accent-coral-dark, #c45a3f);
|
||||||
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
.heroDescription {
|
.heroDescription {
|
||||||
font-size: 1.1rem;
|
font-size: 1.05rem;
|
||||||
color: var(--text-secondary, #5c564d);
|
color: var(--text-secondary, #5c564d);
|
||||||
margin: 0 auto;
|
margin: 0 auto 0.5rem;
|
||||||
max-width: 600px;
|
max-width: 680px;
|
||||||
|
line-height: 1.55;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heroDescription strong {
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
|
.heroSection {
|
||||||
|
padding-top: 1.5rem;
|
||||||
|
}
|
||||||
.heroTitle {
|
.heroTitle {
|
||||||
font-size: 1.75rem;
|
font-size: 2rem;
|
||||||
}
|
}
|
||||||
.heroDescription {
|
.heroDescription {
|
||||||
font-size: 1rem;
|
font-size: 0.95rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -423,26 +464,67 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.discoverySection {
|
.discoverySection {
|
||||||
padding: 2rem var(--page-padding, 2rem);
|
padding: 0.5rem 0 0.5rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.discoveryCount {
|
.nearMeRow {
|
||||||
font-size: 1.1rem;
|
display: flex;
|
||||||
color: var(--text-secondary);
|
flex-direction: column;
|
||||||
margin-bottom: 0.5rem;
|
align-items: center;
|
||||||
}
|
gap: 0.5rem;
|
||||||
|
|
||||||
.discoveryCount strong {
|
|
||||||
color: var(--text-primary);
|
|
||||||
font-size: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.discoveryHints {
|
|
||||||
color: var(--text-muted);
|
|
||||||
margin-bottom: 1.25rem;
|
margin-bottom: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nearMeBtn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.625rem 1.375rem;
|
||||||
|
background: var(--accent-teal, #2d7d7d);
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 999px;
|
||||||
|
font-size: 0.9375rem;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.2s ease, transform 0.15s ease;
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nearMeBtn:hover:not(:disabled) {
|
||||||
|
background: #235f5f;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nearMeBtn:disabled {
|
||||||
|
opacity: 0.7;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nearMeBtnSpinner {
|
||||||
|
display: inline-block;
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
border: 2px solid rgba(255, 255, 255, 0.35);
|
||||||
|
border-top-color: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: nearMeSpin 0.7s linear infinite;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes nearMeSpin {
|
||||||
|
to { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.geoError {
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
color: var(--accent-coral, #e07256);
|
||||||
|
margin: 0;
|
||||||
|
max-width: 340px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.quickSearches {
|
.quickSearches {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -473,6 +555,550 @@
|
|||||||
border-color: var(--accent-coral);
|
border-color: var(--accent-coral);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.exploringRow {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.6rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.exploringLabel {
|
||||||
|
font-size: 0.72rem;
|
||||||
|
color: var(--text-muted, #6d685f);
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.exploringChips {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.exploringChip {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
padding: 0.5rem 0.95rem;
|
||||||
|
background: var(--bg-card, white);
|
||||||
|
border: 1px solid var(--border-color, #e5dfd5);
|
||||||
|
border-radius: 999px;
|
||||||
|
font-size: 0.82rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--text-secondary, #5c564d);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.exploringChip:hover {
|
||||||
|
border-color: var(--accent-coral, #e07256);
|
||||||
|
color: var(--accent-coral-dark, #c45a3f);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chipDot {
|
||||||
|
display: inline-block;
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: currentColor;
|
||||||
|
opacity: 0.55;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── How it works section ─────────────────────────────── */
|
||||||
|
|
||||||
|
.howItWorks {
|
||||||
|
padding: 3rem 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hiwHeader {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hiwHeading {
|
||||||
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
|
font-size: 1.75rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hiwSub {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: var(--text-muted, #6d685f);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hiwGrid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hiwCard {
|
||||||
|
background: var(--bg-card, white);
|
||||||
|
border: 1px solid var(--border-color, #e5dfd5);
|
||||||
|
border-radius: 14px;
|
||||||
|
padding: 1.25rem;
|
||||||
|
box-shadow: 0 2px 8px rgba(26, 22, 18, 0.06);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hiwVisual {
|
||||||
|
background: var(--bg-secondary, #f3ede4);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 0.9rem;
|
||||||
|
min-height: 180px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hiwPhaseBlock {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hiwPhaseLabel {
|
||||||
|
font-size: 0.58rem;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--text-muted, #6d685f);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hiwPhaseLabel strong {
|
||||||
|
color: var(--accent-teal, #2d7d7d);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hiwCardBody {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hiwStep {
|
||||||
|
font-size: 0.65rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--accent-coral, #e07256);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hiwTitle {
|
||||||
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
|
line-height: 1.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hiwDesc {
|
||||||
|
font-size: 0.86rem;
|
||||||
|
color: var(--text-secondary, #5c564d);
|
||||||
|
line-height: 1.45;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mini cascade (performance card) */
|
||||||
|
.miniCascade {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 0.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.miniCascadeCol {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.15rem;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.miniSubj {
|
||||||
|
font-size: 0.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--text-muted, #6d685f);
|
||||||
|
margin-bottom: 0.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.miniRowHead {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 0.48rem;
|
||||||
|
color: var(--text-muted, #6d685f);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.miniRowHead strong {
|
||||||
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
|
font-size: 0.62rem;
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.miniTrack {
|
||||||
|
height: 5px;
|
||||||
|
border-radius: 2px;
|
||||||
|
background: rgba(45, 125, 125, 0.08);
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.miniBarExp {
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 2px;
|
||||||
|
background: var(--accent-teal-light, #3a9e9e);
|
||||||
|
}
|
||||||
|
|
||||||
|
.miniBarExc {
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 2px;
|
||||||
|
background: var(--accent-teal, #2d7d7d);
|
||||||
|
}
|
||||||
|
|
||||||
|
.miniNatPill {
|
||||||
|
position: absolute;
|
||||||
|
top: -9px;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
background: var(--accent-coral, #e07256);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 0.4rem;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 0.05rem 0.2rem;
|
||||||
|
border-radius: 3px;
|
||||||
|
z-index: 2;
|
||||||
|
white-space: nowrap;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attainment 8 mini bar */
|
||||||
|
.att8Row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr auto;
|
||||||
|
gap: 0.6rem;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.att8BarWrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.att8BarHead {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 0.5rem;
|
||||||
|
color: var(--text-muted, #6d685f);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.att8Track {
|
||||||
|
height: 7px;
|
||||||
|
background: rgba(45, 125, 125, 0.08);
|
||||||
|
border-radius: 3px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.att8Fill {
|
||||||
|
height: 100%;
|
||||||
|
background: var(--accent-teal, #2d7d7d);
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.att8NatLine {
|
||||||
|
position: absolute;
|
||||||
|
top: -2px;
|
||||||
|
bottom: -2px;
|
||||||
|
width: 1.5px;
|
||||||
|
background: rgba(224, 114, 86, 0.6);
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.att8Score {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.att8Value {
|
||||||
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--accent-teal, #2d7d7d);
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.att8Delta {
|
||||||
|
font-size: 0.55rem;
|
||||||
|
color: var(--accent-teal, #2d7d7d);
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
margin-top: 0.15rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ofsted preview */
|
||||||
|
.ofstedPreview {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.4rem 0.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ofstedHead {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding-bottom: 0.4rem;
|
||||||
|
border-bottom: 1.5px solid var(--border-color, #e5dfd5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ofstedBullet {
|
||||||
|
display: block;
|
||||||
|
width: 3px;
|
||||||
|
height: 1em;
|
||||||
|
background: var(--accent-coral, #e07256);
|
||||||
|
border-radius: 2px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ofstedTitle {
|
||||||
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ofstedBadge {
|
||||||
|
align-self: flex-start;
|
||||||
|
padding: 0.2rem 0.55rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: rgba(45, 125, 125, 0.12);
|
||||||
|
color: var(--accent-teal, #2d7d7d);
|
||||||
|
font-size: 0.55rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ofstedVerdict {
|
||||||
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
|
font-size: 1.05rem;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.2;
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ofstedVerdict em {
|
||||||
|
color: var(--accent-teal, #2d7d7d);
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ofstedMeta {
|
||||||
|
font-size: 0.6rem;
|
||||||
|
color: var(--text-muted, #6d685f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compare preview */
|
||||||
|
.comparePreview {
|
||||||
|
width: 100%;
|
||||||
|
background: var(--bg-card, white);
|
||||||
|
border: 1px solid var(--border-color, #e5dfd5);
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 0.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compareHead {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr repeat(2, 1fr);
|
||||||
|
background: rgba(45, 125, 125, 0.1);
|
||||||
|
padding: 0.35rem 0.5rem;
|
||||||
|
gap: 0.35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compareHeadCell {
|
||||||
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
|
font-size: 0.62rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--accent-teal, #2d7d7d);
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compareHeadLabel {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 0.48rem;
|
||||||
|
color: var(--text-muted, #6d685f);
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compareRow {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr repeat(2, 1fr);
|
||||||
|
padding: 0.3rem 0.5rem;
|
||||||
|
gap: 0.35rem;
|
||||||
|
border-top: 1px solid var(--border-color, #e5dfd5);
|
||||||
|
align-items: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compareRowLabel {
|
||||||
|
font-size: 0.55rem;
|
||||||
|
color: var(--text-muted, #6d685f);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compareRowVal {
|
||||||
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
|
font-size: 0.72rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
|
}
|
||||||
|
|
||||||
|
.compareRowValHi {
|
||||||
|
color: var(--accent-teal, #2d7d7d);
|
||||||
|
}
|
||||||
|
|
||||||
|
.compareFoot {
|
||||||
|
font-size: 0.52rem;
|
||||||
|
color: var(--text-muted, #6d685f);
|
||||||
|
padding: 0.35rem 0.5rem;
|
||||||
|
background: var(--bg-secondary, #f3ede4);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.06em;
|
||||||
|
text-align: center;
|
||||||
|
border-top: 1px solid var(--border-color, #e5dfd5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.hiwGrid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
.hiwHeader {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
.hiwHeading {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Editorial section ───────────────────────────────── */
|
||||||
|
|
||||||
|
.editorial {
|
||||||
|
padding: 2rem 0 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editorialGrid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1.4fr 1fr;
|
||||||
|
gap: 2rem;
|
||||||
|
padding: 1.75rem;
|
||||||
|
background: var(--bg-card, white);
|
||||||
|
border: 1px solid var(--border-color, #e5dfd5);
|
||||||
|
border-radius: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editorialText {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.65rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editorialKicker {
|
||||||
|
font-size: 0.68rem;
|
||||||
|
color: var(--accent-coral, #e07256);
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editorialHeading {
|
||||||
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
|
font-size: 1.35rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editorialText p {
|
||||||
|
font-size: 0.92rem;
|
||||||
|
color: var(--text-secondary, #5c564d);
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.factbox {
|
||||||
|
background: var(--bg-secondary, #f3ede4);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 1.25rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.factboxHeading {
|
||||||
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
|
margin: 0 0 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.factRow {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: baseline;
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
border-bottom: 1px solid var(--border-color, #e5dfd5);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.factRow:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.factKey {
|
||||||
|
color: var(--text-muted, #6d685f);
|
||||||
|
}
|
||||||
|
|
||||||
|
.factVal {
|
||||||
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.editorialGrid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
padding: 1.25rem;
|
||||||
|
gap: 1.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.resultsHeader {
|
.resultsHeader {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import React, { useState, useEffect, useRef } from 'react';
|
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
||||||
import { useSearchParams, useRouter, usePathname } from 'next/navigation';
|
import { useSearchParams, useRouter, usePathname } from 'next/navigation';
|
||||||
import { FilterBar } from './FilterBar';
|
import { FilterBar } from './FilterBar';
|
||||||
import { SchoolRow } from './SchoolRow';
|
import { SchoolRow } from './SchoolRow';
|
||||||
@@ -41,6 +41,8 @@ export function HomeView({ initialSchools, filters, totalSchools }: HomeViewProp
|
|||||||
const [mapSchools, setMapSchools] = useState<School[]>([]);
|
const [mapSchools, setMapSchools] = useState<School[]>([]);
|
||||||
const [isLoadingMap, setIsLoadingMap] = useState(false);
|
const [isLoadingMap, setIsLoadingMap] = useState(false);
|
||||||
const prevSearchParamsRef = useRef(searchParams.toString());
|
const prevSearchParamsRef = useRef(searchParams.toString());
|
||||||
|
const [geoState, setGeoState] = useState<'idle' | 'requesting' | 'error'>('idle');
|
||||||
|
const [geoError, setGeoError] = useState<string | null>(null);
|
||||||
|
|
||||||
const hasSearch = searchParams.get('search') || searchParams.get('postcode');
|
const hasSearch = searchParams.get('search') || searchParams.get('postcode');
|
||||||
const isLocationSearch = !!searchParams.get('postcode');
|
const isLocationSearch = !!searchParams.get('postcode');
|
||||||
@@ -117,6 +119,47 @@ export function HomeView({ initialSchools, filters, totalSchools }: HomeViewProp
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleNearMe = useCallback(() => {
|
||||||
|
if (!navigator.geolocation) {
|
||||||
|
setGeoState('error');
|
||||||
|
setGeoError('Geolocation is not supported by your browser. Enter a postcode instead.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setGeoState('requesting');
|
||||||
|
setGeoError(null);
|
||||||
|
navigator.geolocation.getCurrentPosition(
|
||||||
|
async (position) => {
|
||||||
|
const { latitude, longitude } = position.coords;
|
||||||
|
try {
|
||||||
|
const res = await fetch(
|
||||||
|
`https://api.postcodes.io/postcodes?lon=${longitude}&lat=${latitude}&limit=1`
|
||||||
|
);
|
||||||
|
const data = await res.json();
|
||||||
|
if (data.result && data.result.length > 0) {
|
||||||
|
const postcode = data.result[0].postcode as string;
|
||||||
|
setGeoState('idle');
|
||||||
|
router.push(`/?postcode=${encodeURIComponent(postcode)}&radius=1`);
|
||||||
|
} else {
|
||||||
|
setGeoState('error');
|
||||||
|
setGeoError('No postcode found near your location. Try entering one above.');
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
setGeoState('error');
|
||||||
|
setGeoError('Could not look up your location. Please try again.');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
setGeoState('error');
|
||||||
|
if (err.code === err.PERMISSION_DENIED) {
|
||||||
|
setGeoError('Location access was denied. Enter a postcode above to find nearby schools.');
|
||||||
|
} else {
|
||||||
|
setGeoError('Could not get your location. Please try again or enter a postcode.');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ timeout: 10000, maximumAge: 60000 }
|
||||||
|
);
|
||||||
|
}, [router]);
|
||||||
|
|
||||||
const sortedSchools = [...allSchools].sort((a, b) => {
|
const sortedSchools = [...allSchools].sort((a, b) => {
|
||||||
if (sortOrder === 'rwm_desc') return (b.rwm_expected_pct ?? -Infinity) - (a.rwm_expected_pct ?? -Infinity);
|
if (sortOrder === 'rwm_desc') return (b.rwm_expected_pct ?? -Infinity) - (a.rwm_expected_pct ?? -Infinity);
|
||||||
if (sortOrder === 'rwm_asc') return (a.rwm_expected_pct ?? Infinity) - (b.rwm_expected_pct ?? Infinity);
|
if (sortOrder === 'rwm_asc') return (a.rwm_expected_pct ?? Infinity) - (b.rwm_expected_pct ?? Infinity);
|
||||||
@@ -132,8 +175,16 @@ export function HomeView({ initialSchools, filters, totalSchools }: HomeViewProp
|
|||||||
{/* Combined Hero + Search and Filters */}
|
{/* Combined Hero + Search and Filters */}
|
||||||
{!isSearchActive && (
|
{!isSearchActive && (
|
||||||
<div className={styles.heroSection}>
|
<div className={styles.heroSection}>
|
||||||
<h1 className={styles.heroTitle}>Find Local Schools</h1>
|
<span className={styles.heroEyebrow}>
|
||||||
<p className={styles.heroDescription}>Compare school results (SATs and GCSE), for thousands of schools across England</p>
|
<span className={styles.heroEyebrowDot} aria-hidden="true" />
|
||||||
|
2024/25 results · updated April 2026
|
||||||
|
</span>
|
||||||
|
<h1 className={styles.heroTitle}>
|
||||||
|
Every English school, <em className={styles.heroEmph}>compared.</em>
|
||||||
|
</h1>
|
||||||
|
<p className={styles.heroDescription}>
|
||||||
|
<strong>24,000+ primary and secondary schools</strong> with Key Stage 2 SATs, GCSE results, Ofsted grades, progress scores and admissions data — side by side, in one place.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -146,17 +197,214 @@ export function HomeView({ initialSchools, filters, totalSchools }: HomeViewProp
|
|||||||
{/* Discovery section shown on landing page before any search */}
|
{/* Discovery section shown on landing page before any search */}
|
||||||
{!isSearchActive && initialSchools.schools.length === 0 && (
|
{!isSearchActive && initialSchools.schools.length === 0 && (
|
||||||
<div className={styles.discoverySection}>
|
<div className={styles.discoverySection}>
|
||||||
{totalSchools && <p className={styles.discoveryCount}><strong>{totalSchools.toLocaleString()}+</strong> primary and secondary schools across England</p>}
|
<div className={styles.nearMeRow}>
|
||||||
<p className={styles.discoveryHints}>Try searching for a school name, or enter a postcode to find schools near you.</p>
|
<button
|
||||||
<div className={styles.quickSearches}>
|
className={styles.nearMeBtn}
|
||||||
<span className={styles.quickSearchLabel}>Quick searches:</span>
|
onClick={handleNearMe}
|
||||||
{['Manchester', 'Bristol', 'Leeds', 'Birmingham'].map(city => (
|
disabled={geoState === 'requesting'}
|
||||||
<a key={city} href={`/?search=${city}`} className={styles.quickSearchChip}>{city}</a>
|
>
|
||||||
))}
|
{geoState === 'requesting' ? (
|
||||||
|
<>
|
||||||
|
<span className={styles.nearMeBtnSpinner} aria-hidden="true" />
|
||||||
|
Locating you…
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" aria-hidden="true">
|
||||||
|
<path d="M12 2a7 7 0 0 1 7 7c0 5.25-7 13-7 13S5 14.25 5 9a7 7 0 0 1 7-7z"/>
|
||||||
|
<circle cx="12" cy="9" r="2.5"/>
|
||||||
|
</svg>
|
||||||
|
Schools near me
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
{geoError && <p className={styles.geoError} role="alert">{geoError}</p>}
|
||||||
|
</div>
|
||||||
|
<div className={styles.exploringRow}>
|
||||||
|
<span className={styles.exploringLabel}>Start exploring</span>
|
||||||
|
<div className={styles.exploringChips}>
|
||||||
|
<a href="/rankings" className={styles.exploringChip}>
|
||||||
|
<span className={styles.chipDot} aria-hidden="true" />
|
||||||
|
Top-rated primary schools
|
||||||
|
</a>
|
||||||
|
<a href="/rankings" className={styles.exploringChip}>
|
||||||
|
<span className={styles.chipDot} aria-hidden="true" />
|
||||||
|
Top-rated secondary schools
|
||||||
|
</a>
|
||||||
|
<a href="/compare" className={styles.exploringChip}>
|
||||||
|
<span className={styles.chipDot} aria-hidden="true" />
|
||||||
|
Start a comparison
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* How it works — only on landing page */}
|
||||||
|
{!isSearchActive && (
|
||||||
|
<section className={styles.howItWorks}>
|
||||||
|
<div className={styles.hiwHeader}>
|
||||||
|
<h2 className={styles.hiwHeading}>What you'll see on every school</h2>
|
||||||
|
<span className={styles.hiwSub}>Primary or secondary — the page adapts to the phase</span>
|
||||||
|
</div>
|
||||||
|
<div className={styles.hiwGrid}>
|
||||||
|
|
||||||
|
{/* Card 1 — Performance */}
|
||||||
|
<div className={styles.hiwCard}>
|
||||||
|
<div className={styles.hiwVisual}>
|
||||||
|
{/* Primary: mini cascade */}
|
||||||
|
<div className={styles.hiwPhaseBlock}>
|
||||||
|
<div className={styles.hiwPhaseLabel}>Primary · Year 6 · <strong>Key Stage 2 SATs</strong></div>
|
||||||
|
<div className={styles.miniCascade}>
|
||||||
|
{[
|
||||||
|
{ subj: 'Reading', exp: 96, exc: 73, nat: 75 },
|
||||||
|
{ subj: 'Writing', exp: 81, exc: 15, nat: 72 },
|
||||||
|
{ subj: 'Maths', exp: 85, exc: 47, nat: 74 },
|
||||||
|
].map(({ subj, exp, exc, nat }) => (
|
||||||
|
<div key={subj} className={styles.miniCascadeCol}>
|
||||||
|
<div className={styles.miniSubj}>{subj}</div>
|
||||||
|
<div className={styles.miniRowHead}><span>Expected</span><strong>{exp}%</strong></div>
|
||||||
|
<div className={styles.miniTrack}>
|
||||||
|
<div className={styles.miniNatPill} style={{ left: `${nat}%` }}>{nat}%</div>
|
||||||
|
<div className={styles.miniBarExp} style={{ width: `${exp}%` }} />
|
||||||
|
</div>
|
||||||
|
<div className={styles.miniRowHead}><span>Exceeding</span><strong>{exc}%</strong></div>
|
||||||
|
<div className={styles.miniTrack}>
|
||||||
|
<div className={styles.miniBarExc} style={{ width: `${exc}%` }} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* Secondary: Attainment 8 */}
|
||||||
|
<div className={styles.hiwPhaseBlock}>
|
||||||
|
<div className={styles.hiwPhaseLabel}>Secondary · Year 11 · <strong>GCSE Attainment 8</strong></div>
|
||||||
|
<div className={styles.att8Row}>
|
||||||
|
<div className={styles.att8BarWrap}>
|
||||||
|
<div className={styles.att8BarHead}><span>This school</span><span>National avg 50.2</span></div>
|
||||||
|
<div className={styles.att8Track}>
|
||||||
|
<div className={styles.att8Fill} style={{ width: '62%' }} />
|
||||||
|
<div className={styles.att8NatLine} style={{ left: '50%' }} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.att8Score}>
|
||||||
|
<div className={styles.att8Value}>62.4</div>
|
||||||
|
<div className={styles.att8Delta}>+12.2 vs national</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.hiwCardBody}>
|
||||||
|
<div className={styles.hiwStep}>Performance</div>
|
||||||
|
<div className={styles.hiwTitle}>Results against the national average</div>
|
||||||
|
<p className={styles.hiwDesc}>For primary schools, each subject's Expected and Exceeding percentages side by side. For secondary schools, GCSE Attainment 8 with the national benchmark overlaid.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Card 2 — Ofsted */}
|
||||||
|
<div className={styles.hiwCard}>
|
||||||
|
<div className={styles.hiwVisual}>
|
||||||
|
<div className={styles.ofstedPreview}>
|
||||||
|
<div className={styles.ofstedHead}>
|
||||||
|
<span className={styles.ofstedBullet} />
|
||||||
|
<span className={styles.ofstedTitle}>Latest Ofsted inspection</span>
|
||||||
|
</div>
|
||||||
|
<span className={styles.ofstedBadge}>OUTSTANDING</span>
|
||||||
|
<div className={styles.ofstedVerdict}>Rated <em>Outstanding</em> at last inspection.</div>
|
||||||
|
<div className={styles.ofstedMeta}>Full inspection · March 2024</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.hiwCardBody}>
|
||||||
|
<div className={styles.hiwStep}>Judgement</div>
|
||||||
|
<div className={styles.hiwTitle}>Ofsted at a glance</div>
|
||||||
|
<p className={styles.hiwDesc}>Current grade, inspection date, and a plain-English headline — without opening a 40-page report.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Card 3 — Compare */}
|
||||||
|
<div className={styles.hiwCard}>
|
||||||
|
<div className={styles.hiwVisual}>
|
||||||
|
<div className={styles.comparePreview}>
|
||||||
|
<div className={styles.compareHead}>
|
||||||
|
<div className={`${styles.compareHeadCell} ${styles.compareHeadLabel}`}>Metric</div>
|
||||||
|
<div className={styles.compareHeadCell}>Our Lady<br />Queen of Heaven</div>
|
||||||
|
<div className={styles.compareHeadCell}>St Mary's<br />Catholic Primary</div>
|
||||||
|
</div>
|
||||||
|
{[
|
||||||
|
{ label: 'Reading, Writing & Maths', a: '70%', b: '64%', aHi: true },
|
||||||
|
{ label: 'Ofsted', a: 'Outstanding', b: 'Good', aHi: true },
|
||||||
|
{ label: 'Reading progress', a: '+2.1', b: '+0.4', aHi: true },
|
||||||
|
].map(({ label, a, b, aHi }) => (
|
||||||
|
<div key={label} className={styles.compareRow}>
|
||||||
|
<span className={styles.compareRowLabel}>{label}</span>
|
||||||
|
<span className={`${styles.compareRowVal} ${aHi ? styles.compareRowValHi : ''}`}>{a}</span>
|
||||||
|
<span className={styles.compareRowVal}>{b}</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<div className={styles.compareFoot}>+ pin up to 5 schools</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.hiwCardBody}>
|
||||||
|
<div className={styles.hiwStep}>Compare</div>
|
||||||
|
<div className={styles.hiwTitle}>Side-by-side shortlists</div>
|
||||||
|
<p className={styles.hiwDesc}>Pin up to five schools and every metric aligns in the same columns — works for primary and secondary alike.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Editorial — only on landing page */}
|
||||||
|
{!isSearchActive && (
|
||||||
|
<section className={styles.editorial}>
|
||||||
|
<div className={styles.editorialGrid}>
|
||||||
|
<div className={styles.editorialText}>
|
||||||
|
<div className={styles.editorialKicker}>About school data</div>
|
||||||
|
<h2 className={styles.editorialHeading}>Making UK school performance data actually readable</h2>
|
||||||
|
<p>
|
||||||
|
School performance data in England is rich but fragmented. The Department for Education publishes
|
||||||
|
Key Stage 2 SATs, GCSE attainment, Ofsted outcomes, progress scores, admissions figures and
|
||||||
|
demographics — each in its own table, each with its own jargon.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
SchoolCompare brings it all into one place. Every school page shows performance against the national
|
||||||
|
average, explains what the numbers mean, and lets you shortlist schools side by side. Built for
|
||||||
|
parents, governors, journalists, and anyone who wants to understand a school without reading a
|
||||||
|
40-page inspection report.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.factbox}>
|
||||||
|
<h3 className={styles.factboxHeading}>Coverage at a glance</h3>
|
||||||
|
<div className={styles.factRow}>
|
||||||
|
<span className={styles.factKey}>Schools covered</span>
|
||||||
|
<span className={styles.factVal}>{totalSchools ? `${totalSchools.toLocaleString()}` : '24,000+'}</span>
|
||||||
|
</div>
|
||||||
|
<div className={styles.factRow}>
|
||||||
|
<span className={styles.factKey}>Local authorities</span>
|
||||||
|
<span className={styles.factVal}>{filters.local_authorities.length > 0 ? filters.local_authorities.length : 152}</span>
|
||||||
|
</div>
|
||||||
|
<div className={styles.factRow}>
|
||||||
|
<span className={styles.factKey}>Phases</span>
|
||||||
|
<span className={styles.factVal}>Primary & Secondary</span>
|
||||||
|
</div>
|
||||||
|
<div className={styles.factRow}>
|
||||||
|
<span className={styles.factKey}>Latest results year</span>
|
||||||
|
<span className={styles.factVal}>2024/25</span>
|
||||||
|
</div>
|
||||||
|
<div className={styles.factRow}>
|
||||||
|
<span className={styles.factKey}>Historical data</span>
|
||||||
|
<span className={styles.factVal}>2016–2025</span>
|
||||||
|
</div>
|
||||||
|
<div className={styles.factRow}>
|
||||||
|
<span className={styles.factKey}>Metrics per school</span>
|
||||||
|
<span className={styles.factVal}>40+</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Results Section */}
|
{/* Results Section */}
|
||||||
<section className={`${styles.results} ${resultsView === 'map' && isLocationSearch ? styles.mapViewResults : ''}`}>
|
<section className={`${styles.results} ${resultsView === 'map' && isLocationSearch ? styles.mapViewResults : ''}`}>
|
||||||
{!hasSearch && initialSchools.schools.length > 0 && (
|
{!hasSearch && initialSchools.schools.length > 0 && (
|
||||||
|
|||||||
Reference in New Issue
Block a user