/** * Client for /api/suggest. * * No `cache: "no-store"`. The compare modal's search uses it, and copying that * here would discard both the browser cache and the ETag 304s the backend's * CacheAndETagMiddleware already provides — on the one endpoint where prefix * queries repeat most. */ export interface Suggestion { urn: number; school_name: string; local_authority: string; postcode: string; phase: string; school_type: string; } /** Below this the response is thousands of schools and worth no round trip. */ export const SUGGEST_MIN_QUERY = 2; const API = process.env.NEXT_PUBLIC_API_URL || '/api'; /** Suggestions for `q`. Never throws: no suggestions is a fine outcome. */ export async function fetchSuggestions( q: string, signal?: AbortSignal, ): Promise { if (q.trim().length < SUGGEST_MIN_QUERY) return []; try { const res = await fetch(`${API}/suggest?q=${encodeURIComponent(q.trim())}`, { signal }); if (!res.ok) return []; const body = await res.json(); return body.suggestions ?? []; } catch { // Includes AbortError, which is the normal path on every keystroke. return []; } }