Commit Graph

29 Commits

Author SHA1 Message Date
Tudor Sitaru bfff24fa5f style(detail): apply hero card style to Pupils & Inclusion
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
Renames the RWM-specific .rwmHero* classes to generic .heroStat*
and reuses them on the three Pupils & Inclusion headline cards
(disadvantaged, EAL, SEN support). Grid switches to auto-fit to
accommodate both 2- and 3-card layouts. SEN primary-need breakdown
stays on the dense .metricCard style.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 14:31:31 +01:00
Tudor Sitaru 34cd8ad26e style(sats): restyle RWM hero cards to match approved mockup
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 13s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 48s
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
Top two combined cards now use a teal-tinted background with a
2.1rem Playfair serif teal value and a compact uppercase label —
consistent with the hero treatment shown in the design mockup.
Scoped via new .rwmHero* classes so other metric cards on the page
keep their existing style.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 14:01:45 +01:00
Tudor Sitaru 045dbc65b7 feat(sats): add "why is combined lower?" bridge between hero and cascade
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 2m20s
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 0s
Explains the intersection semantics of RWM combined — a pupil is only
counted if they met the bar in all three subjects — with a math line
showing the per-subject percentages collapsing to the combined figure.
Only renders when all four values are present; national-average pill
markers on the cascade are untouched.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 13:30:11 +01:00
Tudor Sitaru 35deedcc16 feat(admissions): promote verdict to headline, move above Q&A
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 12s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 53s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 12s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 0s
The Oversubscribed badge + "Demand exceeds capacity" text lived at
the bottom of the tile as an afterthought. It's the headline finding —
a parent should read it first, then let the Q&A supply the detail.

Replace the footer badge with a Playfair Display sentence directly
under the section title: "This school is oversubscribed." (state word
coloured coral for oversubscribed, teal for undersubscribed). The
"Demand exceeds capacity" / "Supply meets demand" line sits below as
quiet muted text — present for context but not competing with the
headline.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 11:03:57 +01:00
Tudor Sitaru 5abab067a1 feat(admissions): replace bar + metric cards with Q&A tile
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 13s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 50s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 1m4s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
The "How Hard to Get Into This School" tile mixed a progress bar
(places vs first-choice) with three text metric cards, making the
data feel fragmented and hiding the real narrative. The progress bar
also broke visually when undersubscribed and didn't scale to different
school sizes.

Replace with a typographic Q&A list that answers the questions
parents actually ask — "How many places were offered?", "How many
families wanted this school first?", "How many got their first
choice?", "How many applied in total?" — with a verdict footer
(Oversubscribed / Not oversubscribed + one-sentence explanation).

The third row now uses first_preference_offers (already in the API
response) to show "27 of 42 (64.3%)" instead of just the percentage,
giving the raw count parents actually want.

Each row is independently null-gated; rows stack vertically under
480px so the Playfair numeral stays legible.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 10:01:19 +01:00
Tudor Sitaru 3bf2e8f262 feat(detail): replace SATs text tables with cascade bar charts, add admissions bar and history accordion
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 19s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 46s
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
Redesign the School Details page for better parent comprehension:
- New SatsChart component: horizontal cascade bars with ruler scale and
  national average marker (teal/coral palette matching site theme)
- Admissions section: visual progress bar showing 1st-preference demand
  vs available places, colour-coded by oversubscription status
- Historical data: collapse raw year-by-year table behind a disclosure
  element while keeping the performance line chart always visible
- EAL metric: add national average comparison via DeltaChip (backend now
  includes eal_pct in national averages endpoint)
- New formatWithSuppression utility for null/suppressed data handling

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 21:22:24 +01:00
Tudor Sitaru 536a166b35 feat(school-detail): highlight active section in sticky nav on scroll
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 13s
Build and Push Docker Images / Build Frontend (Next.js) (push) Failing after 43s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 12s
Build and Push Docker Images / Trigger Portainer Update (push) Has been skipped
Uses IntersectionObserver on each section element. Multiple thresholds
(0, 0.1, 0.25, 0.5, 0.75, 1.0) track the intersection ratio of every
section simultaneously; whichever has the highest visible ratio at any
moment becomes the active item. rootMargin offsets for the sticky nav
height so a section is only considered active once it's genuinely in
view beneath the bar.

Active link gets .sectionNavLinkActive — coral background + white text,
matching the phase tab active style used elsewhere in the product.
Observer is cleaned up on unmount.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 15:42:20 +01:00
Tudor Sitaru e72345bad5 refactor(school-detail): remove hero summary, red oversubscribed chip
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 12s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 47s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 12s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
- Drop the auto-generated italic summary sentence from the hero — adds
  little beyond what the chips and stats already convey.
- Oversubscribed hero chip: tone-gold → tone-coral so it reads as a
  warning rather than a neutral highlight.
- Remove unused buildSchoolSummary import and .heroSummary CSS.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 15:27:03 +01:00
Tudor Sitaru dfa8058efc feat(school-detail): page-wide improvements across 5 sections
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 12s
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 12s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
History chart
- Strip the redundant school-name title (already the page heading)
- Default to 2 visible lines: Reading, Writing & Maths expected % (teal,
  bold) + Exceeding (gold, lighter); progress score lines hidden by
  default, togglable via legend
- Add dashed national average reference line for RWM (primary) or
  Attainment 8 (secondary) so the school's trajectory is always in
  context
- Add trend summary chip above the chart computed from the data
  ("↓ Peaked at 90% (2016/17), currently 70%")
- Add COVID footnote when 2019/20 and 2020/21 data is absent

Ofsted section
- Collapse the four identical "Outstanding / Outstanding / Outstanding /
  Outstanding" boxes into a single prose line when all sub-grades match
  the overall verdict; show individual cards only when grades differ

SATs sub-metrics
- DeltaChip vs national average on Expected level row for Reading,
  Writing and Maths (national averages already in the API response)

Admissions
- Fix label: "Year 3 places per year" → "Reception places per year" for
  primary schools

Pupils & Inclusion
- DeltaChip + national avg hint on Eligible for pupil premium and
  Pupils receiving SEN support (both keys present in /api/national-averages)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 15:13:13 +01:00
Tudor Sitaru 41cefeedf6 polish(school-detail): align hero stat numbers on a shared baseline
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 12s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 8s
The three at-a-glance stats were misaligned — the serif "Outstanding" tile
sat noticeably above the "70%" and "64%" numerals because the serif variant
used a smaller font. That pushed its label row ("INSPECTED NOVEMBER 2023")
up too, breaking the horizontal rhythm across the row.

- Give .heroStatNumber and .heroStatNumberSerif a shared min-height tied
  to the largest clamp value, plus display: flex; align-items: flex-end.
  Content bottom-aligns inside the box, so every stat's label sits at the
  same Y regardless of how tall the actual glyph is.
- Bump the serif variant up slightly (1.75rem → 2.25rem clamp) so it
  feels closer in weight to the numerals while still leaving room for
  longer words like "Requires Improvement".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 12:00:45 +01:00
Tudor Sitaru 3458195865 polish(school-detail): align hero chips to fixed width, free hero summary
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 12s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 44s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 11s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
- heroChip: swap ``min-width: 180px; flex: 0 1 auto`` for
  ``flex: 0 0 240px`` so every chip in the strip is the same width
  regardless of content. Title gets nowrap + ellipsis as insurance
  against accidental overflow.
- heroChipTitle / Sub / Detail: align line-heights (1.3 / 1.4 / 1.4)
  so an OEIF chip (title + sub) and a Report Card chip
  (title + sub + detail) sit on the same vertical rhythm.
- heroSummary: drop the 64ch max-width — the sentence should read at
  the natural hero width.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 11:18:07 +01:00
Tudor Sitaru 24b3688df0 polish(school-detail): tighten hero layout and drop redundant chip
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 12s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 43s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 12s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
- Drop the "Above national average" chip — the DeltaChip under the 70% /
  Attainment 8 number already carries the same signal, so the chip was
  duplicative and added noise.
- At-a-glance stats: switch from grid(auto-fit) to flex with a fixed
  3rem column gap so the numbers cluster at the start of the row rather
  than spreading across the full width of the header card.
- Add to Compare button: larger padding, bumped font, soft shadow, and
  self-align centre so it sits in balance with the bigger headline
  rather than floating tiny in the top-right corner.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 11:04:01 +01:00
Tudor Sitaru 2d6e39eebc fix(school-detail): hero Ofsted chip mislabels OEIF schools as Report Card
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 13s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 45s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 12s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
The API returns ``framework`` as the literal string "NULL" for older OEIF
inspections (it comes from the upstream ``event_type_grouping`` column),
not real null. The original render path checks ``=== 'ReportCard'`` and
correctly treats anything else as OEIF — but buildOfstedHeroChip inverted
that and treated anything not exactly equal to ``'OEIF'`` as Report Card,
so OLQH (inspected Nov 2023, Outstanding) was being labelled as a Report
Card school in the hero strip and the at-a-glance tile.

- Invert the helper: only branch into Report Card when framework is
  explicitly ``'ReportCard'``; treat OEIF / null / "NULL" / anything else
  as OEIF, and require ``overall_effectiveness`` to render the grade word.
- Replace the toneClass field (which reused .ofstedGrade{N} / .rcGrade{N}
  badge classes and dragged in their backgrounds) with a clean tone enum
  ``teal | green | gold | coral | neutral``. The serif Ofsted heroStat
  picked up the badge background and rendered as a green box around
  "Report Card" — gone now.
- Hero chip backgrounds use color-mix() against the tone variable so all
  five tones share one rule.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 10:44:37 +01:00
Tudor Sitaru c749d72a6a feat(school-detail): editorial hero with signal chips, at-a-glance stats, summary
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 15s
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 12s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 0s
Elevates the primary school detail hero from a flat report header into a
scannable editorial block. Parents can read the headline signal in seconds.

- A1: bump .schoolName to clamp(2rem, 5vw, 3.25rem) Playfair.
- A2: framework-aware signal chip strip via new buildOfstedHeroChip() helper.
  Branches on ofsted.framework so Report Card schools never show a fake
  overall grade — they get "Ofsted Report Card" + inspection date +
  Safeguarding: Met/Not met. OEIF schools keep the grade word.
- A3: oversized Playfair stats — Reading, Writing & Maths % (primary) or
  Attainment 8 (secondary) with inline DeltaChip vs national, Ofsted
  verdict with tone colouring, and first-choice offer rate.
- B1: italic serif one-sentence summary via buildSchoolSummary() helper,
  also framework-aware so Report Card schools are described by framework,
  not a synthetic grade.
- C1: new DeltaChip component reused in the two headline KS2 metric cards
  (rwm_expected_pct, rwm_high_pct).

All copy uses "Reading, Writing & Maths" in full. Secondary detail view
untouched in this slice.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 10:32:33 +01:00
Tudor Sitaru ed244ef743 fix(mobile): address iPhone layout issues across rankings, detail, compare
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 14s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 45s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 11s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
- rankings: hide Type/Action columns on mobile so metric value stays visible;
  ensure filter selects and table wrapper stay within viewport
- school detail: add min-width:0 / max-width:100% containment so internal
  overflow-x wrappers actually clip rather than pushing the page wider;
  explicit line-height on Ofsted grade badges to fix glyph clipping
- compare: sticky first column on the Detailed Comparison table so the Year
  labels remain visible while horizontally scrolling school columns
- search: shorten placeholder to "School name or postcode" so it fits mobile
  input width
- globals: overflow-x:clip safety net on .main wrapper

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 20:29:15 +01:00
tudor 8aca0a7a53 feat(ui): site-wide UX/UI audit — unified buttons, tokens, accessibility
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 35s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m10s
Build and Push Docker Images / Build Integrator (push) Successful in 57s
Build and Push Docker Images / Build Kestra Init (push) Successful in 31s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 0s
- Add shared button system (.btn-primary/secondary/tertiary/active) in globals.css
- Replace 40+ hardcoded rgba() values with design tokens across all CSS modules
- Add skip link, :focus-visible indicators, and ARIA landmarks
- Standardise button labels ("+ Compare" / "✓ Comparing") across all components
- Add collapse/minimize toggle to ComparisonToast
- Fix heading hierarchy (h3→h2 in ComparisonView)
- Add aria-live on search results, aria-label on trend SVGs
- Add "Search" nav link, fix footer empty section, unify max-widths
- Darken --text-muted for WCAG AA compliance (4.6:1 contrast ratio)
- Net reduction of ~180 lines through button style deduplication

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 20:28:03 +00:00
tudor 5cdafc887e fix(ui): render safeguarding as a standard metric card for visual consistency
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 32s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m10s
Build and Push Docker Images / Build Integrator (push) Successful in 56s
Build and Push Docker Images / Build Kestra Init (push) Successful in 32s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 15:17:45 +00:00
tudor 1c49a135c4 feat(ofsted): add Report Card system support alongside legacy OEIF grades
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 47s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m11s
Build and Push Docker Images / Build Integrator (push) Successful in 58s
Build and Push Docker Images / Build Kestra Init (push) Successful in 32s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
Ofsted replaced single overall grades with Report Cards from Nov 2025.
Both systems are retained during the transition period.

- DB: new framework + 9 RC columns on ofsted_inspections (schema v4)
- Integrator: auto-detect OEIF vs Report Card from CSV column headers;
  parse 5-level RC grades and safeguarding met/not-met
- API: expose all new fields in the ofsted response dict
- Frontend: branch on framework='ReportCard' to show safeguarding badge
  + 8-category grid; fall back to legacy OEIF layout otherwise;
  always show inspection date in both layouts
- CSS: rcGrade1–5 and safeguardingMet/NotMet classes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 13:03:04 +00:00
tudor f5aceb1b54 feat(ui): add Ofsted overall judgement disclaimer
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 33s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m17s
Build and Push Docker Images / Build Integrator (push) Successful in 58s
Build and Push Docker Images / Build Kestra Init (push) Successful in 32s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
2026-03-25 12:00:12 +00:00
tudor 59ed92b63c fix(ui): contain map z-index so it doesn't overlap sticky header/nav
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 2m29s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m4s
Build and Push Docker Images / Build Integrator (push) Successful in 57s
Build and Push Docker Images / Build Kestra Init (push) Successful in 33s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 0s
2026-03-25 11:52:08 +00:00
tudor 2998ae2568 fix(ui): increase sticky nav top offset to clear site header
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 33s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m4s
Build and Push Docker Images / Build Integrator (push) Successful in 57s
Build and Push Docker Images / Build Kestra Init (push) Successful in 32s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
2026-03-25 11:44:54 +00:00
tudor 0f7c68c0c3 fix(ui): move back button into sticky nav, fix sticky nav offset
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 2m31s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m6s
Build and Push Docker Images / Build Integrator (push) Successful in 58s
Build and Push Docker Images / Build Kestra Init (push) Successful in 33s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
- Remove standalone back button div (looked out of place)
- Back button now lives in the sticky section nav bar, styled as a
  bordered pill with coral accent — consistent with page design
- Fix sticky nav top offset from 0 to 3rem so it sticks below the
  site-wide header instead of sliding behind it
- Increase scroll-margin-top on cards to 6rem to account for both
  site header and section nav height

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 11:13:55 +00:00
tudor ce470ca342 fix(ui): remove duplicate data, merge sections, add sticky nav
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 34s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m12s
Build and Push Docker Images / Build Integrator (push) Successful in 59s
Build and Push Docker Images / Build Kestra Init (push) Successful in 32s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
UX audit round 2:
- Remove Summary Strip (duplicated Ofsted grade + parent happy/safe/recommend)
- Fold "% would recommend" into Ofsted section header
- Merge SATs Results + Subject Breakdown into one section
- Merge Results Over Time chart + Year-by-Year table into one section
- Add sticky section nav with dynamic pills based on available data
- Unify colour system: replace ad-hoc pill colours with semantic status classes
- Guard Pupils & Inclusion so it only renders with actual data
- Add year to Admissions section title
- Fix progress score 0.0 colour (was neutral gap at ±0.1, now at 0)
- Remove unused .metricTrend CSS class

Page reduced from 16 to 13 sections.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 10:34:19 +00:00
tudor b68063c9b9 fix(admissions): switch to EES content API + correct publication slug and columns
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 50s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m12s
Build and Push Docker Images / Build Integrator (push) Successful in 57s
Build and Push Docker Images / Build Kestra Init (push) Successful in 33s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
The EES statistics API only exposes ~13 publications; admissions data is not
among them. Switch to the EES content API (content.explore-education-statistics.
service.gov.uk) which covers all publications.

- ees.py: add get_content_release_id() and download_release_zip_csv() that
  fetch the release ZIP and extract a named CSV member from it
- admissions.py: use corrected slug (primary-and-secondary-school-applications-
  and-offers), correct column names from actual CSV (school_urn,
  total_number_places_offered, times_put_as_1st_preference, etc.), derive
  first_preference_offers_pct from offer/application ratio, filter to primary
  schools only, keep most recent year per URN

Also includes SchoolDetailView UX redesign: parent-first section ordering,
plain-English labels, national average benchmarks, progress score colour
coding, expanded header, quick summary strip, and CSS consolidation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 10:06:36 +00:00
tudor dd49ef28b2 feat(data): integrate 9 UK government data sources via Kestra
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 47s
Build and Push Docker Images / Trigger Portainer Update (push) Has been cancelled
Build and Push Docker Images / Build Frontend (Next.js) (push) Has been cancelled
Adds a full data integration pipeline for enriching school profiles with
supplementary data from Ofsted, GIAS, EES, IDACI, and FBIT.

Backend:
- Bump SCHEMA_VERSION to 3; add 8 new DB tables (ofsted_inspections,
  ofsted_parent_view, school_census, admissions, sen_detail, phonics,
  school_deprivation, school_finance) plus GIAS columns on schools
- Expose all supplementary data via GET /api/schools/{urn}
- Enrich school list responses with ofsted_grade + ofsted_date

Integrator (new service):
- FastAPI HTTP microservice; Kestra calls POST /run/{source}
- 9 source modules: ofsted, gias, parent_view, census, admissions,
  sen_detail, phonics, idaci, finance
- 9 Kestra flow YAMLs with scheduled triggers and 3× retry

Frontend:
- SchoolRow: colour-coded Ofsted badge (Outstanding/Good/RI/Inadequate)
- SchoolDetailView: 7 new sections — Ofsted sub-judgements, Parent View
  survey bars, Admissions, Pupils & Inclusion / SEN, Phonics, Deprivation
  Context, Finances
- types.ts: 8 new interfaces + extended School/SchoolDetailsResponse

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 11:44:04 +00:00
tudor b3892c1629 style(buttons): standardise button sizes across all components
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 32s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m4s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 0s
Define two button tiers and apply consistently:
- sm (inline pairs): padding 0.5rem 1rem, font-size 0.875rem, radius 6px
- md (standalone CTAs): padding 0.625rem 1.25rem, font-size 0.9rem, radius 8px

RankingsView: viewButton was 0.25rem/0.8rem/4px vs addButton 0.5rem/0.875rem/8px
— biggest mismatch, both now sm with same radius.
SchoolCard: horizontal padding 0.75rem → 1rem, font-size 0.8125rem → 0.875rem.
SchoolRow: padding 0.4375rem → 0.5rem to match sm exactly.
SchoolDetailView: font-size 0.8125rem → 0.875rem.
ComparisonView/Modal: addButton and shareButton aligned to md spec.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 22:53:09 +00:00
tudor 3d24050d11 feat(ux): implement comprehensive UX audit fixes across all pages
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 1m8s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m5s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
Addresses 28 issues identified in UX audit (P0–P3 severity):

P0 — Critical:
- Fix compare URL sharing: seed ComparisonContext from SSR initialData
  when localStorage is empty, making /compare?urns=... links shareable
- Remove permanently broken "Avg. Scaled Score" column from school
  detail historical data table

P1 — High priority:
- Add radius selector (0.5–10 mi) to postcode search in FilterBar
- Make Add to Compare a toggle (remove) on SchoolCards
- Hide hero title/description once a search is active
- Show school count + quick-search prompts on empty landing page
- Compare empty state opens in-page school search modal directly
- Remove URN from school detail header (irrelevant to end users)
- Move map above performance chart in school detail page
- Add ← Back navigation to school detail page
- Add sort controls to search results (RWM%, distance, A–Z)
- Show metric descriptions below metric selector
- Expand ComparisonToast to list school names with per-school remove
- Add progress score explainer (0 = national average) throughout

P2 — Medium:
- Remove console.log statements from ComparisonView
- Colour-code comparison school cards to match chart line colours
- Replace plain loading text with LoadingSkeleton in ComparisonView
- Rankings empty state uses shared EmptyState component
- Rankings year filter shows actual year e.g. "2023 (Latest)"
- Rankings subtitle shows top-N count
- Add View link alongside Add button in rankings table
- Remove placeholder Privacy Policy / Terms links from footer
- Replace untappable 10px info icons with visible metric hint text
- Show active filter chips in search results header

P3 — Polish:
- Remove redundant "Home" nav link (logo already links home)
- Add / and Ctrl+K keyboard shortcut to focus search input
- Add Share button to compare page (copies URL to clipboard)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 21:31:28 +00:00
Tudor ec61e16c9d Condense school detail page layout for better space efficiency
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 34s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m13s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
- Reduced section padding from 2rem to 1rem-1.25rem
- Reduced margin-bottom from 2rem to 1rem
- Smaller chart height (400px → 280px) and map height (400px → 250px)
- Detailed metrics now in 3-column grid layout
- Condensed font sizes and spacing throughout
- Applied design system colors consistently
- Shortened metric labels (e.g., "Expected Standard" → "Expected")

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 12:14:28 +00:00
Tudor ff7f5487e6 Complete Next.js migration with SSR and Docker deployment
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 1m26s
Build and Push Docker Images / Build Frontend (Next.js) (push) Failing after 1m48s
Build and Push Docker Images / Trigger Portainer Update (push) Has been skipped
- Migrate from vanilla JavaScript SPA to Next.js 16 with App Router
- Add server-side rendering for all pages (Home, Compare, Rankings)
- Create individual school pages with dynamic routing (/school/[urn])
- Implement Chart.js and Leaflet map integrations
- Add comprehensive SEO with sitemap, robots.txt, and JSON-LD
- Set up Docker multi-service architecture (PostgreSQL, FastAPI, Next.js)
- Update CI/CD pipeline to build both backend and frontend images
- Fix Dockerfile to include devDependencies for TypeScript compilation
- Add Jest testing configuration
- Implement performance optimizations (code splitting, caching)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 20:34:35 +00:00