One component for all four families: they differ in what fills the registry, not in what the page shows, so a second would be a second place to forget the same change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015mWQnpye9F299NVRCCSRvj
58 lines
1.7 KiB
TypeScript
58 lines
1.7 KiB
TypeScript
/**
|
|
* Client for the places API.
|
|
*
|
|
* Two namespaces, matching the backend: towns and localities share
|
|
* /schools/[place]; authorities take /schools/authority/[la]. 67 town names
|
|
* collide with an authority name and neither set contains the other, so one
|
|
* namespace would publish near-duplicate pages.
|
|
*/
|
|
import type { School } from '@/lib/types';
|
|
|
|
export interface PlaceSummary {
|
|
kind: string;
|
|
slug: string;
|
|
name: string;
|
|
count: number;
|
|
}
|
|
|
|
export interface PlaceDetail {
|
|
place: PlaceSummary & { parent_authority: string | null };
|
|
schools: School[];
|
|
averages: {
|
|
rwm_expected_pct: number | null;
|
|
attainment_8_score: number | null;
|
|
};
|
|
}
|
|
|
|
export function placeUrl(kind: string, slug: string, phase?: string): string {
|
|
const base =
|
|
kind === 'authority' ? `/schools/authority/${slug}`
|
|
: kind === 'outcode' ? `/schools/near/${slug}`
|
|
: `/schools/${slug}`;
|
|
return phase ? `${base}/${phase}` : base;
|
|
}
|
|
|
|
/** An authority name as it appears in a URL. */
|
|
export function authoritySlug(name: string): string {
|
|
return name.toLowerCase().trim().replace(/[^\w\s-]/g, '').replace(/\s+/g, '-');
|
|
}
|
|
|
|
const API = process.env.FASTAPI_URL || process.env.NEXT_PUBLIC_API_URL
|
|
|| 'http://localhost:8000/api';
|
|
|
|
export async function fetchPlaces(): Promise<PlaceSummary[]> {
|
|
const res = await fetch(`${API}/places`, { next: { revalidate: 604800 } });
|
|
if (!res.ok) return [];
|
|
return (await res.json()).places ?? [];
|
|
}
|
|
|
|
export async function fetchPlace(
|
|
kind: string, slug: string, phase?: string,
|
|
): Promise<PlaceDetail | null> {
|
|
const q = phase ? `?phase=${encodeURIComponent(phase)}` : '';
|
|
const res = await fetch(`${API}/places/${kind}/${slug}${q}`,
|
|
{ next: { revalidate: 604800 } });
|
|
if (!res.ok) return null;
|
|
return res.json();
|
|
}
|