Commit Graph

19 Commits

Author SHA1 Message Date
daf24e4739 fix(search): fix load-more silently failing due to missing page_size param
All checks were successful
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 47s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m12s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 31s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
Load-more requests read URL params (postcode, radius, etc.) but page_size
is never in the URL — it's hardcoded in page.tsx. Without it the backend
received page_size=None, hit a TypeError on (page-1)*None, returned 500,
and the silent catch left the user stuck on page 1.

In a dense area (e.g. Wimbledon SW19) 50 schools fit within ~1.8 miles,
so page 1 never shows anything beyond that regardless of selected radius.

Fix:
- Backend: give page_size a safe default of 25 instead of None
- Frontend: explicitly pass initialSchools.page_size in load-more params

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 09:08:15 +01:00
5615458223 feat(ui): consolidate search/filter area into cleaner 2-row layout
All checks were successful
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 / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 31s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
Before: 7 visual rows (search, radius row, phase row, advanced toggle,
teal location banner, results count, filter chips).
After: 2 rows in card + 1 unified results toolbar.

- FilterBar: merge radius, phase, and Advanced toggle into a single
  .controlsRow below the search bar; removed orphaned stacked rows
- HomeView: remove separate teal location banner; merge location info
  into results heading ("16 schools within 1.0 miles of SW196AR");
  move List/Map toggle inline with sort in one results header row
- Remove "Near postcode (Xmi)" chip (now redundant with heading)
- Sort select hidden in map view (sorting is meaningless there)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 20:46:38 +01:00
790b12a7f3 changes to order of display and text
Some checks failed
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 32s
Build and Push Docker Images / Build Frontend (Next.js) (push) Failing after 55s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 31s
Build and Push Docker Images / Trigger Portainer Update (push) Has been skipped
2026-03-29 20:14:42 +01:00
6315f366c8 fix(build): single-brace JSX for schoolUrl, migrate images.domains to remotePatterns
All checks were successful
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 Pipeline (Meltano + dbt + Airflow) (push) Successful in 32s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 14:15:06 +01:00
784febc162 feat(seo): add school name to URLs, fix sticky nav, collapse compare widget
Some checks failed
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 32s
Build and Push Docker Images / Build Frontend (Next.js) (push) Failing after 57s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 31s
Build and Push Docker Images / Trigger Portainer Update (push) Has been skipped
- URLs now /school/138267-school-name instead of /school/138267
- Bare URN URLs redirect to canonical slug (backward compat)
- Remove overflow-x:hidden that broke sticky tab nav on secondary pages
- ComparisonToast starts collapsed — user must click to open

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 12:41:28 +01:00
1d22877aec feat(ux): 8 UX improvements — simpler home, advanced filters, phase tabs, 4-line rows
All checks were successful
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 48s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m13s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 32s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
1. Simpler home page: only search box on landing, no filter dropdowns
2. Advanced filters: hidden behind toggle on results page, auto-open if active
3. Per-school phase rendering: each row renders based on its own data
4. Taller 4-line rows with context line (type, age range, denomination, gender)
5. Result-scoped filters: dropdown values reflect current search results
6. Fix blank filter values: exclude empty strings and "Not applicable"
7. Rankings: Primary/Secondary phase tabs with phase-specific metrics
8. Compare: Primary/Secondary tabs with school counts and phase metrics

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 08:57:06 +01:00
e8175561d5 updates for secondary schools
All checks were successful
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 46s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m15s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 32s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
2026-03-28 22:36:00 +00:00
5eff9af69c feat: add secondary school support with KS4 data and metric tooltips
Some checks failed
Build and Push Docker Images / Build Frontend (Next.js) (push) Has been cancelled
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Has been cancelled
Build and Push Docker Images / Trigger Portainer Update (push) Has been cancelled
Build and Push Docker Images / Build Backend (FastAPI) (push) Has been cancelled
- Backend: replace INNER JOIN ks2 with UNION ALL (ks2 + ks4) so primary
  and secondary schools both appear in the main DataFrame
- Backend: add /api/national-averages endpoint computing means from live
  data, replacing the hardcoded NATIONAL_AVG constant on the frontend
- Backend: add phase filter param to /api/schools; return phases from
  /api/filters; fix hardcoded "phase": "Primary" in school detail endpoint
- Backend: add KS4 metric definitions (Attainment 8, Progress 8, EBacc,
  English & Maths pass rates) to METRIC_DEFINITIONS and RANKING_COLUMNS
- Frontend: SchoolDetailView is now phase-aware — secondary schools show
  a GCSE Results section (Att8, P8, E&M, EBacc) instead of SATs; phonics
  tab hidden for secondary; admissions says Year 7 instead of Year 3;
  history table shows KS4 columns; chart datasets switch for secondary
- Frontend: new MetricTooltip component (CSS-only ⓘ icon) backed by
  METRIC_EXPLANATIONS — added to RWM, GPS, SEN, EAL, IDACI, progress
  scores and all KS4 metrics throughout SchoolDetailView and SchoolCard
- Frontend: METRIC_EXPLANATIONS extended with KS4 terms (Attainment 8,
  Progress 8, EBacc) and previously missing terms (SEN, EHCP, EAL, IDACI)
- Frontend: SchoolCard expands "RWM" to "Reading, Writing & Maths" and
  shows Attainment 8 / English & Maths Grade 4+ for secondary schools
- Frontend: FilterBar adds Phase dropdown (Primary / Secondary / All-through)
- Frontend: HomeView hero copy updated; compact list shows phase-aware metric
- Global metadata updated to remove "primary only" framing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 14:59:40 +00:00
8aca0a7a53 feat(ui): site-wide UX/UI audit — unified buttons, tokens, accessibility
All checks were successful
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
6ddfcadbde fix(search): correct radius units and distance display for postcode search
All checks were successful
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
FilterBar was sending radius in km (e.g. 1.6) but the backend expects miles,
causing the "Showing schools within X miles" banner to display the wrong value.
Change option values to miles (0.5, 1, 3, 5, 10) and default from 1.6 to 1.

school.distance from the API is already in miles (backend haversine uses
R=3959). SchoolRow was dividing by 1609.34 giving 0.0 mi; CompactSchoolItem
was dividing by 1.60934. Both now display school.distance directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 22:39:50 +00:00
0f29397253 feat(ui): replace card grid with row-based results and plain-language metric labels
All checks were successful
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 32s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m2s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
Replace the school card grid with a scannable row list that shows 3x more
results per screen. Each row shows: school name + R,W&M % with trend,
area/type meta, and reading/writing/maths progress scores with plain-English
band labels (e.g. "above average") instead of raw numbers.

Add lib/metrics.ts as a single source of truth for plain-language metric
explanations and the progressBand() helper. Map view toggle is unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 22:32:33 +00:00
3d24050d11 feat(ux): implement comprehensive UX audit fixes across all pages
All checks were successful
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
d4abb56c22 feat(ui): redesign landing page search and empty states
All checks were successful
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 42s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m12s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
- Hide empty state placeholder on initial load

- Add prominent hero mode to FilterBar when no search is active

- Fix SchoolCard test TypeScript and assertion errors
2026-03-05 13:00:34 +00:00
Tudor
ad7380dba5 feat(ux): implement UX audit recommendations
All checks were successful
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 1m10s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m12s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
- Redesign landing page with unified Omnibox search

- Add ComparisonToast for better comparison flow visibility

- Add visual 'Added' state to SchoolCard

- Add info tooltips to educational metrics

- Optimize mobile map view with Bottom Sheet

- Standardize distance display to miles
2026-03-05 09:33:47 +00:00
Tudor
1b0d6edb98 Add map view for location search results
All checks were successful
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 0s
Implemented split-view map layout for postcode searches:
- List/Map toggle appears when doing location search
- Map view shows interactive map with school markers on left
- Compact school list on right with distance badges, stats, actions
- Mobile responsive: stacks vertically with map on top
- Updated School type to include distance and total_pupils fields

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 10:05:31 +00:00
Tudor
ea6820f1c4 Combine hero and filter sections into unified search block
All checks were successful
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 35s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m17s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 0s
Merged the hero title/description into FilterBar component to save
vertical space. The combined block has a gradient background flowing
from cream to white with the search controls below the header.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 09:54:27 +00:00
Tudor
19e5199443 Improve professional appearance: logo, favicon, and remove emoji icons
All checks were successful
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 / Trigger Portainer Update (push) Successful in 1s
1. Added original favicon
   - Copied favicon.svg from original frontend
   - Added favicon reference to layout metadata
   - Professional icon with brand colors

2. Updated logo in navigation
   - Replaced emoji with proper SVG logo from original design
   - Uses circular target design with crosshairs
   - Matches brand identity with coral accent color

3. Removed emoji icons throughout app for professional look
   - Removed 📍 (location pin) from school locations
   - Removed 🏫 (school building) from school types
   - Removed 🔢 from URN labels and section headings
   - Kept meaningful symbols (✓, +) in buttons only
   - Updated map popup button color to brand coral (#e07256)

Components updated:
- Navigation: Professional SVG logo
- HomeView: Clean location banner
- SchoolDetailView: No decorative emojis in metadata
- ComparisonView: Text-only school information
- SchoolSearchModal: Clean school listings
- LeafletMapInner: Professional map popups

Result: More polished, professional appearance suitable for
educational data platform

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 22:34:14 +00:00
Tudor
1c0e6298f2 Fix: Improve UX with empty state, miles, and metric labels
All checks were successful
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 / Trigger Portainer Update (push) Successful in 0s
1. Show empty state by default on home page
   - Don't fetch or display schools until user searches
   - Show helpful message prompting users to search
   - Only fetch schools when search params are present

2. Change distance search to miles
   - Display 0.5, 1, and 2 mile options instead of km
   - Convert miles to km when sending to API (backend expects km)
   - Convert km back to miles for display in location banner
   - Maintains backend compatibility while improving UX

3. Fix metric labels in rankings dropdown
   - Backend returns 'name' and 'type' fields
   - Frontend expects 'label' and 'format' fields
   - Added transformation in fetchMetrics to map fields
   - Dropdown now shows proper labels like "RWM Combined %"
     instead of technical codes like "rwm_expected_pct"

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 22:21:55 +00:00
Tudor
ff7f5487e6 Complete Next.js migration with SSR and Docker deployment
Some checks failed
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