feat(admissions): add admissions guide page and homepage countdown strip
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 14s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 51s
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 14s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 51s
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
- New /admissions route with AdmissionsView client component - Live countdowns (days until) to Primary/Secondary deadlines and Offer Days - Step-by-step timelines for both tracks with highlighted milestone rows - Tips section covering equal preference rule, late applications, waiting lists - Homepage countdown strip (4 cards) between discovery chips and how-it-works - Admissions nav link and footer link added Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,14 @@
|
|||||||
|
import type { Metadata } from 'next';
|
||||||
|
import { AdmissionsView } from '@/components/AdmissionsView';
|
||||||
|
|
||||||
|
export const dynamic = 'force-static';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'School Admissions Guide',
|
||||||
|
description:
|
||||||
|
'Understand the Primary and Secondary school admissions process in England, with live countdowns to every key deadline and National Offer Day.',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function AdmissionsPage() {
|
||||||
|
return <AdmissionsView />;
|
||||||
|
}
|
||||||
@@ -0,0 +1,426 @@
|
|||||||
|
.page {
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 1.25rem 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ─── Hero ───────────────────────────────────────────── */
|
||||||
|
|
||||||
|
.hero {
|
||||||
|
text-align: center;
|
||||||
|
padding: 3rem 0 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eyebrow {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eyebrowDot {
|
||||||
|
display: inline-block;
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--accent-teal, #2d7d7d);
|
||||||
|
}
|
||||||
|
|
||||||
|
.heroTitle {
|
||||||
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
|
font-size: 2.75rem;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.1;
|
||||||
|
letter-spacing: -0.015em;
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
|
margin-bottom: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heroSub {
|
||||||
|
font-size: 1.05rem;
|
||||||
|
color: var(--text-secondary, #5c564d);
|
||||||
|
max-width: 640px;
|
||||||
|
margin: 0 auto;
|
||||||
|
line-height: 1.55;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ─── Countdown strip ────────────────────────────────── */
|
||||||
|
|
||||||
|
.countdownSection {
|
||||||
|
padding: 0 0 2.5rem;
|
||||||
|
border-bottom: 1px solid var(--border-color, #e5dfd5);
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stripHeader {
|
||||||
|
margin-bottom: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stripLabel {
|
||||||
|
font-size: 0.72rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--text-muted, #6d685f);
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdownRail {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip {
|
||||||
|
background: var(--bg-card, #fff);
|
||||||
|
border: 1px solid var(--border-color, #e5dfd5);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 1rem 1.1rem 0.9rem;
|
||||||
|
box-shadow: 0 2px 8px rgba(26, 22, 18, 0.06);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.2rem;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 3px;
|
||||||
|
border-radius: 12px 12px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chipDeadline::before { background: var(--accent-coral, #e07256); }
|
||||||
|
.chipOffer::before { background: var(--accent-teal, #2d7d7d); }
|
||||||
|
|
||||||
|
.chipUrgent {
|
||||||
|
border-color: rgba(224, 114, 86, 0.4);
|
||||||
|
background: rgba(224, 114, 86, 0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chipTrack {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.3rem;
|
||||||
|
font-size: 0.6rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin-bottom: 0.15rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chipTrackDeadline { color: var(--accent-coral, #e07256); }
|
||||||
|
.chipTrackOffer { color: var(--accent-teal, #2d7d7d); }
|
||||||
|
|
||||||
|
.chipTrackDot {
|
||||||
|
width: 5px;
|
||||||
|
height: 5px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: currentColor;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chipDays {
|
||||||
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
|
font-size: 2.6rem;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chipDeadline .chipDays,
|
||||||
|
.chipUrgent .chipDays {
|
||||||
|
color: var(--accent-coral-dark, #c45a3f);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chipOffer .chipDays {
|
||||||
|
color: var(--accent-teal, #2d7d7d);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chipDaysUnit {
|
||||||
|
font-size: 0.78rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--text-muted, #6d685f);
|
||||||
|
margin-left: 0.2rem;
|
||||||
|
vertical-align: bottom;
|
||||||
|
line-height: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chipMilestone {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
|
line-height: 1.25;
|
||||||
|
margin-top: 0.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chipDate {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: var(--text-muted, #6d685f);
|
||||||
|
margin-top: 0.05rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ─── Track (Secondary / Primary) ────────────────────── */
|
||||||
|
|
||||||
|
.track {
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
background: var(--bg-card, #fff);
|
||||||
|
border: 1px solid var(--border-color, #e5dfd5);
|
||||||
|
border-radius: 14px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trackHeader {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 1.5rem;
|
||||||
|
padding: 1.75rem 2rem 1.5rem;
|
||||||
|
border-bottom: 1px solid var(--border-color, #e5dfd5);
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trackHeaderLeft {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trackKicker {
|
||||||
|
display: block;
|
||||||
|
font-size: 0.68rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--accent-coral, #e07256);
|
||||||
|
margin-bottom: 0.35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trackTitle {
|
||||||
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
|
margin-bottom: 0.4rem;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trackSub {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--text-secondary, #5c564d);
|
||||||
|
line-height: 1.5;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trackDates {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
flex-shrink: 0;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trackDateRow {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.05rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trackDateLabel {
|
||||||
|
font-size: 0.62rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--text-muted, #6d685f);
|
||||||
|
}
|
||||||
|
|
||||||
|
.trackDateVal {
|
||||||
|
font-size: 0.88rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ─── Timeline ───────────────────────────────────────── */
|
||||||
|
|
||||||
|
.timeline {
|
||||||
|
list-style: none;
|
||||||
|
padding: 1.5rem 2rem 1.75rem;
|
||||||
|
margin: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.step {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stepDotCol {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 20px;
|
||||||
|
padding-top: 0.15rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stepDot {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--bg-card, #fff);
|
||||||
|
border: 2px solid var(--border-color, #e5dfd5);
|
||||||
|
flex-shrink: 0;
|
||||||
|
transition: border-color 0.2s ease, background 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stepDeadline .stepDot {
|
||||||
|
background: rgba(224, 114, 86, 0.15);
|
||||||
|
border-color: var(--accent-coral, #e07256);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stepOffer .stepDot {
|
||||||
|
background: rgba(45, 125, 125, 0.15);
|
||||||
|
border-color: var(--accent-teal, #2d7d7d);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stepLine {
|
||||||
|
width: 2px;
|
||||||
|
flex: 1;
|
||||||
|
min-height: 24px;
|
||||||
|
background: var(--border-color, #e5dfd5);
|
||||||
|
margin: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stepContent {
|
||||||
|
padding-bottom: 1.5rem;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.step:last-child .stepContent {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stepDate {
|
||||||
|
font-size: 0.72rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.06em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--text-muted, #6d685f);
|
||||||
|
margin-bottom: 0.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stepDeadline .stepDate { color: var(--accent-coral, #e07256); }
|
||||||
|
.stepOffer .stepDate { color: var(--accent-teal, #2d7d7d); }
|
||||||
|
|
||||||
|
.stepTitle {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stepDeadline .stepTitle { color: var(--accent-coral-dark, #c45a3f); }
|
||||||
|
.stepOffer .stepTitle { color: var(--accent-teal, #2d7d7d); }
|
||||||
|
|
||||||
|
.stepBody {
|
||||||
|
font-size: 0.88rem;
|
||||||
|
color: var(--text-secondary, #5c564d);
|
||||||
|
line-height: 1.55;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ─── Tips ───────────────────────────────────────────── */
|
||||||
|
|
||||||
|
.tips {
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tipsHeading {
|
||||||
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
|
font-size: 1.35rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tipsGrid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tipCard {
|
||||||
|
background: var(--bg-secondary, #f3ede4);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tipNumber {
|
||||||
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
|
font-size: 1.75rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--border-color, #e5dfd5);
|
||||||
|
line-height: 1;
|
||||||
|
margin-bottom: 0.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tipHeading {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
|
margin-bottom: 0.4rem;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tipBody {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: var(--text-secondary, #5c564d);
|
||||||
|
line-height: 1.55;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ─── Responsive ─────────────────────────────────────── */
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.heroTitle {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdownRail {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.trackHeader {
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 1.25rem 1.25rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trackDates {
|
||||||
|
text-align: left;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline {
|
||||||
|
padding: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tipsGrid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,291 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import styles from './AdmissionsView.module.css';
|
||||||
|
|
||||||
|
/* ─── Date helpers ─────────────────────────────────────── */
|
||||||
|
|
||||||
|
function daysUntil(month: number, day: number): number {
|
||||||
|
const today = new Date();
|
||||||
|
today.setHours(0, 0, 0, 0);
|
||||||
|
const y = today.getFullYear();
|
||||||
|
let target = new Date(y, month - 1, day);
|
||||||
|
if (target <= today) target = new Date(y + 1, month - 1, day);
|
||||||
|
return Math.round((target.getTime() - today.getTime()) / 86_400_000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextDate(month: number, day: number): Date {
|
||||||
|
const today = new Date();
|
||||||
|
today.setHours(0, 0, 0, 0);
|
||||||
|
const y = today.getFullYear();
|
||||||
|
const target = new Date(y, month - 1, day);
|
||||||
|
if (target <= today) return new Date(y + 1, month - 1, day);
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fmtDate(month: number, day: number): string {
|
||||||
|
return nextDate(month, day).toLocaleDateString('en-GB', {
|
||||||
|
weekday: 'short',
|
||||||
|
day: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
year: 'numeric',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ─── Data ─────────────────────────────────────────────── */
|
||||||
|
|
||||||
|
interface Chip {
|
||||||
|
type: 'deadline' | 'offer';
|
||||||
|
track: string;
|
||||||
|
milestone: string;
|
||||||
|
month: number;
|
||||||
|
day: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CHIPS: Chip[] = [
|
||||||
|
{ type: 'offer', track: 'Primary · Offer Day', milestone: 'Primary National Offer Day', month: 4, day: 16 },
|
||||||
|
{ type: 'deadline', track: 'Secondary · Deadline', milestone: 'Secondary applications close', month: 10, day: 31 },
|
||||||
|
{ type: 'deadline', track: 'Primary · Deadline', milestone: 'Primary applications close', month: 1, day: 15 },
|
||||||
|
{ type: 'offer', track: 'Secondary · Offer Day', milestone: 'Secondary National Offer Day', month: 3, day: 1 },
|
||||||
|
];
|
||||||
|
|
||||||
|
interface Step {
|
||||||
|
date?: string;
|
||||||
|
title: string;
|
||||||
|
body: string;
|
||||||
|
highlight?: 'deadline' | 'offer';
|
||||||
|
}
|
||||||
|
|
||||||
|
const SECONDARY_STEPS: Step[] = [
|
||||||
|
{
|
||||||
|
title: 'Check entry criteria',
|
||||||
|
body: 'Look at each school\'s admissions policy — catchment areas, faith criteria, sibling priority, and aptitude tests vary widely. Use school detail pages on SchoolCompare for admissions history.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: 'September',
|
||||||
|
title: 'Portal opens',
|
||||||
|
body: 'Your local council opens its online admissions portal. Register early to avoid last-minute technical issues. You apply through your home council even if you prefer schools in neighbouring boroughs.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '31 October',
|
||||||
|
title: 'Application deadline',
|
||||||
|
body: 'Submit your ranked list of up to six schools. Councils treat all preferences equally — list schools in the genuine order you want them, not strategically.',
|
||||||
|
highlight: 'deadline',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '1 March',
|
||||||
|
title: 'National Offer Day',
|
||||||
|
body: 'Results are published online, usually from 12:01 am. You\'ll receive an email or letter with your allocated school.',
|
||||||
|
highlight: 'offer',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '~15 March',
|
||||||
|
title: 'Accept or decline',
|
||||||
|
body: 'Respond by the deadline your council gives — typically around 15 March. Accepting does not prevent you from keeping a place on a waiting list for a preferred school.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Appeals',
|
||||||
|
body: 'If unsuccessful, you can appeal within 20 school days of the refusal letter. Secondary appeals consider whether prejudice to the school outweighs your case — success rates vary.',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const PRIMARY_STEPS: Step[] = [
|
||||||
|
{
|
||||||
|
title: 'Research entry criteria',
|
||||||
|
body: 'Faith schools, language units, and distance-based catchments differ by school. Start by reading each school\'s admissions policy on their website or the council\'s website.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: 'September',
|
||||||
|
title: 'Portal opens',
|
||||||
|
body: 'Apply through your home council\'s portal, even if your preferred school is in another borough. Most councils accept applications from September.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '15 January',
|
||||||
|
title: 'Application deadline',
|
||||||
|
body: 'List up to 3–6 schools (the number varies by council) in genuine preference order. The equal preference rule means all preferences are considered before any offers are made.',
|
||||||
|
highlight: 'deadline',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '16 April',
|
||||||
|
title: 'National Offer Day',
|
||||||
|
body: 'Results are published online. Reception offers are sent on 16 April (or the next working day if that falls on a weekend or bank holiday).',
|
||||||
|
highlight: 'offer',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '~1 May',
|
||||||
|
title: 'Accept or decline',
|
||||||
|
body: 'Respond by your council\'s deadline, typically around 1 May. Accepting secures the place while you wait to see if a preferred school\'s waiting list moves.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Appeals',
|
||||||
|
body: 'Infant class-size appeals (Reception to Year 2) have a very narrow legal test and a low success rate. For Year 3+, appeals follow the same process as secondary.',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
interface Tip {
|
||||||
|
heading: string;
|
||||||
|
body: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TIPS: Tip[] = [
|
||||||
|
{
|
||||||
|
heading: 'Equal preference rule',
|
||||||
|
body: 'Councils rank offers by your eligibility for each school, not by the order you listed them. You cannot game the system — put schools in the order you actually want them.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
heading: 'Late applications go to the back',
|
||||||
|
body: 'Submit before the deadline even if your child does not turn the required age until later in the year. Late applicants are only considered after all on-time applications.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
heading: 'Waiting lists',
|
||||||
|
body: 'You can go on waiting lists for multiple schools simultaneously. Lists are ordered by admissions criteria, not when you joined. They can move significantly over the summer.',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
/* ─── Component ────────────────────────────────────────── */
|
||||||
|
|
||||||
|
export function AdmissionsView() {
|
||||||
|
const [chipDays, setChipDays] = useState<(number | null)[]>(CHIPS.map(() => null));
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setChipDays(CHIPS.map(c => daysUntil(c.month, c.day)));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.page}>
|
||||||
|
|
||||||
|
{/* Hero */}
|
||||||
|
<section className={styles.hero}>
|
||||||
|
<span className={styles.eyebrow}>
|
||||||
|
<span className={styles.eyebrowDot} aria-hidden="true" />
|
||||||
|
England · Primary & Secondary
|
||||||
|
</span>
|
||||||
|
<h1 className={styles.heroTitle}>School Admissions Guide</h1>
|
||||||
|
<p className={styles.heroSub}>
|
||||||
|
Everything parents need to know about applying for a school place in England — from opening dates to National Offer Day, with live countdowns to every key milestone.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Countdown strip */}
|
||||||
|
<section className={styles.countdownSection}>
|
||||||
|
<div className={styles.stripHeader}>
|
||||||
|
<span className={styles.stripLabel}>Days until next milestone</span>
|
||||||
|
</div>
|
||||||
|
<div className={styles.countdownRail}>
|
||||||
|
{CHIPS.map((chip, i) => {
|
||||||
|
const days = chipDays[i];
|
||||||
|
const isUrgent = days !== null && days <= 14;
|
||||||
|
const chipClass = [
|
||||||
|
styles.chip,
|
||||||
|
chip.type === 'deadline' ? styles.chipDeadline : styles.chipOffer,
|
||||||
|
isUrgent ? styles.chipUrgent : '',
|
||||||
|
].filter(Boolean).join(' ');
|
||||||
|
return (
|
||||||
|
<div key={chip.milestone} className={chipClass}>
|
||||||
|
<span className={[styles.chipTrack, chip.type === 'deadline' ? styles.chipTrackDeadline : styles.chipTrackOffer].join(' ')}>
|
||||||
|
<span className={styles.chipTrackDot} aria-hidden="true" />
|
||||||
|
{chip.track}
|
||||||
|
</span>
|
||||||
|
<div>
|
||||||
|
<span className={styles.chipDays}>{days ?? '—'}</span>
|
||||||
|
{days !== null && <span className={styles.chipDaysUnit}>days</span>}
|
||||||
|
</div>
|
||||||
|
<div className={styles.chipMilestone}>{chip.milestone}</div>
|
||||||
|
<div className={styles.chipDate}>{days !== null ? fmtDate(chip.month, chip.day) : ''}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Secondary track */}
|
||||||
|
<section className={styles.track}>
|
||||||
|
<div className={styles.trackHeader}>
|
||||||
|
<div className={styles.trackHeaderLeft}>
|
||||||
|
<span className={styles.trackKicker}>Year 7 entry</span>
|
||||||
|
<h2 className={styles.trackTitle}>Secondary school admissions</h2>
|
||||||
|
<p className={styles.trackSub}>For children starting secondary school (Year 7) in September. Applications are submitted in the autumn of Year 6.</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.trackDates}>
|
||||||
|
<div className={styles.trackDateRow}>
|
||||||
|
<span className={styles.trackDateLabel}>Deadline</span>
|
||||||
|
<span className={styles.trackDateVal}>{fmtDate(10, 31)}</span>
|
||||||
|
</div>
|
||||||
|
<div className={styles.trackDateRow}>
|
||||||
|
<span className={styles.trackDateLabel}>Offer Day</span>
|
||||||
|
<span className={styles.trackDateVal}>{fmtDate(3, 1)}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ol className={styles.timeline}>
|
||||||
|
{SECONDARY_STEPS.map((step, i) => (
|
||||||
|
<li key={i} className={[styles.step, step.highlight === 'deadline' ? styles.stepDeadline : step.highlight === 'offer' ? styles.stepOffer : ''].filter(Boolean).join(' ')}>
|
||||||
|
<div className={styles.stepDotCol}>
|
||||||
|
<div className={styles.stepDot} />
|
||||||
|
{i < SECONDARY_STEPS.length - 1 && <div className={styles.stepLine} />}
|
||||||
|
</div>
|
||||||
|
<div className={styles.stepContent}>
|
||||||
|
{step.date && <div className={styles.stepDate}>{step.date}</div>}
|
||||||
|
<div className={styles.stepTitle}>{step.title}</div>
|
||||||
|
<p className={styles.stepBody}>{step.body}</p>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ol>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Primary track */}
|
||||||
|
<section className={styles.track}>
|
||||||
|
<div className={styles.trackHeader}>
|
||||||
|
<div className={styles.trackHeaderLeft}>
|
||||||
|
<span className={styles.trackKicker}>Reception entry</span>
|
||||||
|
<h2 className={styles.trackTitle}>Primary school admissions</h2>
|
||||||
|
<p className={styles.trackSub}>For children starting Reception (Year R) in September. Applications are submitted in the autumn of the year before entry.</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.trackDates}>
|
||||||
|
<div className={styles.trackDateRow}>
|
||||||
|
<span className={styles.trackDateLabel}>Deadline</span>
|
||||||
|
<span className={styles.trackDateVal}>{fmtDate(1, 15)}</span>
|
||||||
|
</div>
|
||||||
|
<div className={styles.trackDateRow}>
|
||||||
|
<span className={styles.trackDateLabel}>Offer Day</span>
|
||||||
|
<span className={styles.trackDateVal}>{fmtDate(4, 16)}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ol className={styles.timeline}>
|
||||||
|
{PRIMARY_STEPS.map((step, i) => (
|
||||||
|
<li key={i} className={[styles.step, step.highlight === 'deadline' ? styles.stepDeadline : step.highlight === 'offer' ? styles.stepOffer : ''].filter(Boolean).join(' ')}>
|
||||||
|
<div className={styles.stepDotCol}>
|
||||||
|
<div className={styles.stepDot} />
|
||||||
|
{i < PRIMARY_STEPS.length - 1 && <div className={styles.stepLine} />}
|
||||||
|
</div>
|
||||||
|
<div className={styles.stepContent}>
|
||||||
|
{step.date && <div className={styles.stepDate}>{step.date}</div>}
|
||||||
|
<div className={styles.stepTitle}>{step.title}</div>
|
||||||
|
<p className={styles.stepBody}>{step.body}</p>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ol>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Tips */}
|
||||||
|
<section className={styles.tips}>
|
||||||
|
<h2 className={styles.tipsHeading}>Three things most parents get wrong</h2>
|
||||||
|
<div className={styles.tipsGrid}>
|
||||||
|
{TIPS.map((tip, i) => (
|
||||||
|
<div key={i} className={styles.tipCard}>
|
||||||
|
<div className={styles.tipNumber}>{String(i + 1).padStart(2, '0')}</div>
|
||||||
|
<h3 className={styles.tipHeading}>{tip.heading}</h3>
|
||||||
|
<p className={styles.tipBody}>{tip.body}</p>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@ export function Footer() {
|
|||||||
<li><a href="/" className={styles.link}>Search schools</a></li>
|
<li><a href="/" className={styles.link}>Search schools</a></li>
|
||||||
<li><a href="/rankings" className={styles.link}>Rankings</a></li>
|
<li><a href="/rankings" className={styles.link}>Rankings</a></li>
|
||||||
<li><a href="/compare" className={styles.link}>Compare shortlist</a></li>
|
<li><a href="/compare" className={styles.link}>Compare shortlist</a></li>
|
||||||
|
<li><a href="/admissions" className={styles.link}>Admissions guide</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1173,3 +1173,156 @@
|
|||||||
.loadMoreButton {
|
.loadMoreButton {
|
||||||
min-width: 160px;
|
min-width: 160px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* =========================================================
|
||||||
|
Admissions Countdown Strip
|
||||||
|
========================================================= */
|
||||||
|
|
||||||
|
.admissionsStrip {
|
||||||
|
padding: 1.5rem 0 2rem;
|
||||||
|
border-top: 1px solid var(--border-color, #e5dfd5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stripHeader {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stripLabel {
|
||||||
|
font-size: 0.72rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--text-muted, #6d685f);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stripCta {
|
||||||
|
font-size: 0.82rem;
|
||||||
|
color: var(--accent-teal, #2d7d7d);
|
||||||
|
font-weight: 600;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stripCta:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdownRail {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdownChip {
|
||||||
|
background: var(--bg-card, #fff);
|
||||||
|
border: 1px solid var(--border-color, #e5dfd5);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 1rem 1.1rem 0.9rem;
|
||||||
|
box-shadow: 0 2px 8px rgba(26, 22, 18, 0.06);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.2rem;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdownChip::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 3px;
|
||||||
|
border-radius: 12px 12px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdownChipDeadline::before {
|
||||||
|
background: var(--accent-coral, #e07256);
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdownChipOffer::before {
|
||||||
|
background: var(--accent-teal, #2d7d7d);
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdownChipUrgent {
|
||||||
|
border-color: rgba(224, 114, 86, 0.4);
|
||||||
|
background: rgba(224, 114, 86, 0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chipTrack {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.3rem;
|
||||||
|
font-size: 0.6rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin-bottom: 0.15rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chipTrackDeadline {
|
||||||
|
color: var(--accent-coral, #e07256);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chipTrackOffer {
|
||||||
|
color: var(--accent-teal, #2d7d7d);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chipTrackDot {
|
||||||
|
width: 5px;
|
||||||
|
height: 5px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: currentColor;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chipDays {
|
||||||
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
|
font-size: 2.6rem;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdownChipDeadline .chipDays,
|
||||||
|
.countdownChipUrgent .chipDays {
|
||||||
|
color: var(--accent-coral-dark, #c45a3f);
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdownChipOffer .chipDays {
|
||||||
|
color: var(--accent-teal, #2d7d7d);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chipDaysUnit {
|
||||||
|
font-family: 'DM Sans', sans-serif;
|
||||||
|
font-size: 0.78rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--text-muted, #6d685f);
|
||||||
|
margin-left: 0.2rem;
|
||||||
|
vertical-align: bottom;
|
||||||
|
line-height: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chipMilestone {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
|
line-height: 1.25;
|
||||||
|
margin-top: 0.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chipDate {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: var(--text-muted, #6d685f);
|
||||||
|
margin-top: 0.05rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.countdownRail {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,6 +24,39 @@ interface HomeViewProps {
|
|||||||
totalSchools?: number | null;
|
totalSchools?: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function daysUntil(month: number, day: number): number {
|
||||||
|
const today = new Date();
|
||||||
|
today.setHours(0, 0, 0, 0);
|
||||||
|
const y = today.getFullYear();
|
||||||
|
let target = new Date(y, month - 1, day);
|
||||||
|
if (target <= today) target = new Date(y + 1, month - 1, day);
|
||||||
|
return Math.round((target.getTime() - today.getTime()) / 86_400_000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatCountdownDate(month: number, day: number): string {
|
||||||
|
const today = new Date();
|
||||||
|
today.setHours(0, 0, 0, 0);
|
||||||
|
const y = today.getFullYear();
|
||||||
|
let target = new Date(y, month - 1, day);
|
||||||
|
if (target <= today) target = new Date(y + 1, month - 1, day);
|
||||||
|
return target.toLocaleDateString('en-GB', { weekday: 'short', day: 'numeric', month: 'long', year: 'numeric' });
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CountdownChipData {
|
||||||
|
type: 'deadline' | 'offer';
|
||||||
|
track: string;
|
||||||
|
milestone: string;
|
||||||
|
month: number;
|
||||||
|
day: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ADMISSIONS_CHIPS: CountdownChipData[] = [
|
||||||
|
{ type: 'offer', track: 'Primary · Offer Day', milestone: 'Primary National Offer Day', month: 4, day: 16 },
|
||||||
|
{ type: 'deadline', track: 'Secondary · Deadline', milestone: 'Secondary applications close', month: 10, day: 31 },
|
||||||
|
{ type: 'deadline', track: 'Primary · Deadline', milestone: 'Primary applications close', month: 1, day: 15 },
|
||||||
|
{ type: 'offer', track: 'Secondary · Offer Day', milestone: 'Secondary National Offer Day', month: 3, day: 1 },
|
||||||
|
];
|
||||||
|
|
||||||
export function HomeView({ initialSchools, filters, totalSchools }: HomeViewProps) {
|
export function HomeView({ initialSchools, filters, totalSchools }: HomeViewProps) {
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -43,6 +76,7 @@ export function HomeView({ initialSchools, filters, totalSchools }: HomeViewProp
|
|||||||
const prevSearchParamsRef = useRef(searchParams.toString());
|
const prevSearchParamsRef = useRef(searchParams.toString());
|
||||||
const [geoState, setGeoState] = useState<'idle' | 'requesting' | 'error'>('idle');
|
const [geoState, setGeoState] = useState<'idle' | 'requesting' | 'error'>('idle');
|
||||||
const [geoError, setGeoError] = useState<string | null>(null);
|
const [geoError, setGeoError] = useState<string | null>(null);
|
||||||
|
const [chipDays, setChipDays] = useState<(number | null)[]>(ADMISSIONS_CHIPS.map(() => 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');
|
||||||
@@ -100,6 +134,11 @@ export function HomeView({ initialSchools, filters, totalSchools }: HomeViewProp
|
|||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Compute admissions countdown days client-side to avoid SSR mismatch
|
||||||
|
useEffect(() => {
|
||||||
|
setChipDays(ADMISSIONS_CHIPS.map(c => daysUntil(c.month, c.day)));
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleLoadMore = async () => {
|
const handleLoadMore = async () => {
|
||||||
if (isLoadingMore || !hasMore) return;
|
if (isLoadingMore || !hasMore) return;
|
||||||
setIsLoadingMore(true);
|
setIsLoadingMore(true);
|
||||||
@@ -240,6 +279,47 @@ export function HomeView({ initialSchools, filters, totalSchools }: HomeViewProp
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Admissions countdown strip — only on landing page */}
|
||||||
|
{!isSearchActive && (
|
||||||
|
<section className={styles.admissionsStrip}>
|
||||||
|
<div className={styles.stripHeader}>
|
||||||
|
<span className={styles.stripLabel}>Key admissions deadlines</span>
|
||||||
|
<a href="/admissions" className={styles.stripCta}>Full admissions guide →</a>
|
||||||
|
</div>
|
||||||
|
<div className={styles.countdownRail}>
|
||||||
|
{ADMISSIONS_CHIPS.map((chip, i) => {
|
||||||
|
const days = chipDays[i];
|
||||||
|
const isUrgent = days !== null && days <= 14;
|
||||||
|
const chipClass = [
|
||||||
|
styles.countdownChip,
|
||||||
|
chip.type === 'deadline' ? styles.countdownChipDeadline : styles.countdownChipOffer,
|
||||||
|
isUrgent ? styles.countdownChipUrgent : '',
|
||||||
|
].filter(Boolean).join(' ');
|
||||||
|
const trackClass = [
|
||||||
|
styles.chipTrack,
|
||||||
|
chip.type === 'deadline' ? styles.chipTrackDeadline : styles.chipTrackOffer,
|
||||||
|
].join(' ');
|
||||||
|
return (
|
||||||
|
<div key={chip.milestone} className={chipClass}>
|
||||||
|
<span className={trackClass}>
|
||||||
|
<span className={styles.chipTrackDot} aria-hidden="true" />
|
||||||
|
{chip.track}
|
||||||
|
</span>
|
||||||
|
<div>
|
||||||
|
<span className={styles.chipDays}>{days ?? '—'}</span>
|
||||||
|
{days !== null && <span className={styles.chipDaysUnit}>days</span>}
|
||||||
|
</div>
|
||||||
|
<div className={styles.chipMilestone}>{chip.milestone}</div>
|
||||||
|
<div className={styles.chipDate}>
|
||||||
|
{days !== null ? formatCountdownDate(chip.month, chip.day) : ''}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* How it works — only on landing page */}
|
{/* How it works — only on landing page */}
|
||||||
{!isSearchActive && (
|
{!isSearchActive && (
|
||||||
<section className={styles.howItWorks}>
|
<section className={styles.howItWorks}>
|
||||||
|
|||||||
@@ -59,6 +59,12 @@ export function Navigation() {
|
|||||||
>
|
>
|
||||||
Rankings
|
Rankings
|
||||||
</Link>
|
</Link>
|
||||||
|
<Link
|
||||||
|
href="/admissions"
|
||||||
|
className={isActive('/admissions') ? `${styles.navLink} ${styles.active}` : styles.navLink}
|
||||||
|
>
|
||||||
|
Admissions
|
||||||
|
</Link>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
Reference in New Issue
Block a user