From 1c0e6298f22b063d7848b0b84421d4757760a2ed Mon Sep 17 00:00:00 2001 From: Tudor Date: Mon, 2 Feb 2026 22:21:55 +0000 Subject: [PATCH] Fix: Improve UX with empty state, miles, and metric labels 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 --- nextjs-app/app/page.tsx | 26 ++++++++++++++++++++------ nextjs-app/components/FilterBar.tsx | 21 ++++++++++++--------- nextjs-app/components/HomeView.tsx | 26 +++++++++++++++++--------- nextjs-app/lib/api.ts | 15 ++++++++++++++- 4 files changed, 63 insertions(+), 25 deletions(-) diff --git a/nextjs-app/app/page.tsx b/nextjs-app/app/page.tsx index 43cc328..b1c80f6 100644 --- a/nextjs-app/app/page.tsx +++ b/nextjs-app/app/page.tsx @@ -31,12 +31,24 @@ export default async function HomePage({ searchParams }: HomePageProps) { // Parse search params const page = parseInt(params.page || '1'); - const radius = params.radius ? parseInt(params.radius) : undefined; + const radius = params.radius ? parseFloat(params.radius) : undefined; + + // Check if user has performed a search + const hasSearchParams = !!( + params.search || + params.local_authority || + params.school_type || + params.postcode + ); // Fetch data on server with error handling try { - const [schoolsData, filtersData] = await Promise.all([ - fetchSchools({ + const filtersData = await fetchFilters(); + + // Only fetch schools if there are search parameters + let schoolsData; + if (hasSearchParams) { + schoolsData = await fetchSchools({ search: params.search, local_authority: params.local_authority, school_type: params.school_type, @@ -44,9 +56,11 @@ export default async function HomePage({ searchParams }: HomePageProps) { radius, page, page_size: 50, - }), - fetchFilters(), - ]); + }); + } else { + // Empty state by default + schoolsData = { schools: [], page: 1, page_size: 50, total: 0, total_pages: 0 }; + } return ( ) => { const params = new URLSearchParams(searchParams); @@ -77,7 +79,7 @@ export function FilterBar({ filters, showLocationSearch = true }: FilterBarProps e.preventDefault(); const formData = new FormData(e.target as HTMLFormElement); const postcode = formData.get('postcode') as string; - const radius = formData.get('radius') as string; + const radiusMiles = formData.get('radius') as string; if (!postcode.trim()) { alert('Please enter a postcode'); @@ -89,7 +91,10 @@ export function FilterBar({ filters, showLocationSearch = true }: FilterBarProps return; } - updateURL({ postcode, radius, search: '' }); + // Convert miles to km for API (backend expects km) + const radiusKm = (parseFloat(radiusMiles) * 1.60934).toFixed(1); + + updateURL({ postcode, radius: radiusKm, search: '' }); }; const handleClearFilters = () => { @@ -138,12 +143,10 @@ export function FilterBar({ filters, showLocationSearch = true }: FilterBarProps className={styles.postcodeInput} required /> - + + +