perfect-postcode/frontend/src/hooks/useTravelDestinations.ts

47 lines
1.5 KiB
TypeScript

import { useState, useEffect, useRef } from 'react';
import { authHeaders, logNonAbortError } from '../lib/api';
import type { TransportMode } from './useTravelTime';
export interface Destination {
name: string;
slug: string;
place_type: string;
city?: string;
}
/** Fetches all travel-time destinations for a mode once, with client-side caching. */
export function useTravelDestinations(mode: TransportMode) {
const [destinations, setDestinations] = useState<Destination[]>([]);
const [loading, setLoading] = useState(false);
const cacheRef = useRef<Partial<Record<TransportMode, Destination[]>>>({});
useEffect(() => {
if (cacheRef.current[mode]) {
setDestinations(cacheRef.current[mode]!);
return;
}
const controller = new AbortController();
setLoading(true);
fetch(`/api/travel-destinations?mode=${mode}`, authHeaders({ signal: controller.signal }))
.then((res) => {
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
})
.then((data: { destinations: Destination[] }) => {
const normalized = data.destinations.map((d) => ({
...d,
city: d.city === 'City of London' ? 'London' : d.city,
}));
cacheRef.current[mode] = normalized;
setDestinations(normalized);
})
.catch((err) => logNonAbortError('travel destinations', err))
.finally(() => setLoading(false));
return () => controller.abort();
}, [mode]);
return { destinations, loading };
}