This commit is contained in:
Andras Schmelczer 2026-02-14 12:53:29 +00:00
parent 3a3f899ea2
commit 128b3191e7
68 changed files with 28060 additions and 1152 deletions

View file

@ -3,10 +3,11 @@ import type {
FeatureMeta,
FeatureFilters,
Property,
PostcodeGeometry,
HexagonPropertiesResponse,
HexagonStatsResponse,
} from '../types';
import { buildFilterString, apiUrl, logNonAbortError, authHeaders } from '../lib/api';
import { buildFilterString, apiUrl, assertOk, logNonAbortError, authHeaders } from '../lib/api';
interface SelectedHexagon {
id: string;
@ -30,6 +31,8 @@ export function useHexagonSelection({ filters, features, resolution }: UseHexago
const [loadingAreaStats, setLoadingAreaStats] = useState(false);
const [hoveredHexagon, setHoveredHexagon] = useState<string | null>(null);
const [rightPaneTab, setRightPaneTab] = useState<'properties' | 'area'>('area');
const [selectedPostcodeGeometry, setSelectedPostcodeGeometry] =
useState<PostcodeGeometry | null>(null);
const fetchHexagonStats = useCallback(
async (h3: string, res: number, signal?: AbortSignal, fields?: string[]) => {
@ -43,6 +46,7 @@ export function useHexagonSelection({ filters, features, resolution }: UseHexago
params.set('fields', fields.join(','));
}
const response = await fetch(apiUrl('hexagon-stats', params), authHeaders({ signal }));
assertOk(response, 'hexagon-stats');
return (await response.json()) as HexagonStatsResponse;
},
[filters, features]
@ -54,6 +58,7 @@ export function useHexagonSelection({ filters, features, resolution }: UseHexago
const filterStr = buildFilterString(filters, features);
if (filterStr) params.append('filters', filterStr);
const response = await fetch(apiUrl('postcode-stats', params), authHeaders({ signal }));
assertOk(response, 'postcode-stats');
return (await response.json()) as HexagonStatsResponse;
},
[filters, features]
@ -74,6 +79,7 @@ export function useHexagonSelection({ filters, features, resolution }: UseHexago
if (filterStr) params.append('filters', filterStr);
const response = await fetch(apiUrl('hexagon-properties', params), authHeaders());
assertOk(response, 'hexagon-properties');
const data: HexagonPropertiesResponse = await response.json();
if (offset === 0) {
@ -84,7 +90,7 @@ export function useHexagonSelection({ filters, features, resolution }: UseHexago
setPropertiesTotal(data.total);
setPropertiesOffset(offset + data.properties.length);
} catch (err) {
console.error('Failed to fetch properties:', err);
logNonAbortError('Failed to fetch properties', err);
} finally {
setLoadingProperties(false);
}
@ -94,6 +100,7 @@ export function useHexagonSelection({ filters, features, resolution }: UseHexago
const handleHexagonClick = useCallback(
(id: string, isPostcode = false) => {
setSelectedPostcodeGeometry(null);
if (selectedHexagon?.id === id) {
setSelectedHexagon(null);
setProperties([]);
@ -154,8 +161,27 @@ export function useHexagonSelection({ filters, features, resolution }: UseHexago
setSelectedHexagon(null);
setProperties([]);
setAreaStats(null);
setSelectedPostcodeGeometry(null);
}, []);
const handleLocationSearch = useCallback(
(postcode: string, geometry: PostcodeGeometry) => {
setSelectedHexagon({ id: postcode, type: 'postcode', resolution });
setSelectedPostcodeGeometry(geometry);
setProperties([]);
setPropertiesTotal(0);
setPropertiesOffset(0);
setRightPaneTab('area');
setLoadingAreaStats(true);
fetchPostcodeStats(postcode)
.then((stats) => setAreaStats(stats))
.catch((error) => logNonAbortError('Failed to fetch postcode stats', error))
.finally(() => setLoadingAreaStats(false));
},
[resolution, fetchPostcodeStats]
);
return {
selectedHexagon,
properties,
@ -172,5 +198,7 @@ export function useHexagonSelection({ filters, features, resolution }: UseHexago
handlePropertiesTabClick,
handleLoadMoreProperties,
handleCloseSelection,
selectedPostcodeGeometry,
handleLocationSearch,
};
}