More improvements
This commit is contained in:
parent
e0798b24f7
commit
72653a4ddf
7 changed files with 146 additions and 33 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { useState, useCallback } from 'react';
|
||||
import { useState, useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import { trackEvent } from '../lib/analytics';
|
||||
import type {
|
||||
FeatureMeta,
|
||||
|
|
@ -99,6 +99,39 @@ export function useHexagonSelection({ filters, features, resolution }: UseHexago
|
|||
[filters, features]
|
||||
);
|
||||
|
||||
const fetchPostcodeProperties = useCallback(
|
||||
async (postcode: string, offset = 0) => {
|
||||
setLoadingProperties(true);
|
||||
try {
|
||||
const params = new URLSearchParams({
|
||||
postcode,
|
||||
limit: '100',
|
||||
offset: offset.toString(),
|
||||
});
|
||||
|
||||
const filterStr = buildFilterString(filters, features);
|
||||
if (filterStr) params.append('filters', filterStr);
|
||||
|
||||
const response = await fetch(apiUrl('postcode-properties', params), authHeaders());
|
||||
assertOk(response, 'postcode-properties');
|
||||
const data: HexagonPropertiesResponse = await response.json();
|
||||
|
||||
if (offset === 0) {
|
||||
setProperties(data.properties);
|
||||
} else {
|
||||
setProperties((prev) => [...prev, ...data.properties]);
|
||||
}
|
||||
setPropertiesTotal(data.total);
|
||||
setPropertiesOffset(offset + data.properties.length);
|
||||
} catch (err) {
|
||||
logNonAbortError('Failed to fetch postcode properties', err);
|
||||
} finally {
|
||||
setLoadingProperties(false);
|
||||
}
|
||||
},
|
||||
[filters, features]
|
||||
);
|
||||
|
||||
const handleHexagonClick = useCallback(
|
||||
(id: string, isPostcode = false, geometry?: PostcodeGeometry) => {
|
||||
if (selectedHexagon?.id === id) {
|
||||
|
|
@ -139,27 +172,37 @@ export function useHexagonSelection({ filters, features, resolution }: UseHexago
|
|||
}, []);
|
||||
|
||||
const handleViewPropertiesFromArea = useCallback(() => {
|
||||
if (selectedHexagon && selectedHexagon.type === 'hexagon') {
|
||||
trackEvent('View Properties');
|
||||
setRightPaneTab('properties');
|
||||
setPropertiesOffset(0);
|
||||
if (!selectedHexagon) return;
|
||||
trackEvent('View Properties');
|
||||
setRightPaneTab('properties');
|
||||
setPropertiesOffset(0);
|
||||
if (selectedHexagon.type === 'postcode') {
|
||||
fetchPostcodeProperties(selectedHexagon.id, 0);
|
||||
} else {
|
||||
fetchHexagonProperties(selectedHexagon.id, selectedHexagon.resolution, 0);
|
||||
}
|
||||
}, [selectedHexagon, fetchHexagonProperties]);
|
||||
}, [selectedHexagon, fetchHexagonProperties, fetchPostcodeProperties]);
|
||||
|
||||
const handlePropertiesTabClick = useCallback(() => {
|
||||
setRightPaneTab('properties');
|
||||
if (selectedHexagon?.type === 'hexagon' && properties.length === 0 && !loadingProperties) {
|
||||
if (selectedHexagon && properties.length === 0 && !loadingProperties) {
|
||||
setPropertiesOffset(0);
|
||||
fetchHexagonProperties(selectedHexagon.id, selectedHexagon.resolution, 0);
|
||||
if (selectedHexagon.type === 'postcode') {
|
||||
fetchPostcodeProperties(selectedHexagon.id, 0);
|
||||
} else {
|
||||
fetchHexagonProperties(selectedHexagon.id, selectedHexagon.resolution, 0);
|
||||
}
|
||||
}
|
||||
}, [selectedHexagon, properties.length, loadingProperties, fetchHexagonProperties]);
|
||||
}, [selectedHexagon, properties.length, loadingProperties, fetchHexagonProperties, fetchPostcodeProperties]);
|
||||
|
||||
const handleLoadMoreProperties = useCallback(() => {
|
||||
if (selectedHexagon && selectedHexagon.type === 'hexagon') {
|
||||
if (!selectedHexagon) return;
|
||||
if (selectedHexagon.type === 'postcode') {
|
||||
fetchPostcodeProperties(selectedHexagon.id, propertiesOffset);
|
||||
} else {
|
||||
fetchHexagonProperties(selectedHexagon.id, selectedHexagon.resolution, propertiesOffset);
|
||||
}
|
||||
}, [selectedHexagon, propertiesOffset, fetchHexagonProperties]);
|
||||
}, [selectedHexagon, propertiesOffset, fetchHexagonProperties, fetchPostcodeProperties]);
|
||||
|
||||
const handleCloseSelection = useCallback(() => {
|
||||
setSelectedHexagon(null);
|
||||
|
|
@ -168,6 +211,53 @@ export function useHexagonSelection({ filters, features, resolution }: UseHexago
|
|||
setSelectedPostcodeGeometry(null);
|
||||
}, []);
|
||||
|
||||
// Re-fetch stats when filters change while a hexagon is selected
|
||||
const filterStr = useMemo(() => buildFilterString(filters, features), [filters, features]);
|
||||
const prevFilterStr = useRef(filterStr);
|
||||
|
||||
useEffect(() => {
|
||||
if (prevFilterStr.current === filterStr) return;
|
||||
prevFilterStr.current = filterStr;
|
||||
|
||||
if (!selectedHexagon) return;
|
||||
|
||||
// Clear stale properties
|
||||
setProperties([]);
|
||||
setPropertiesTotal(0);
|
||||
setPropertiesOffset(0);
|
||||
|
||||
setLoadingAreaStats(true);
|
||||
let cancelled = false;
|
||||
|
||||
const fetchStats =
|
||||
selectedHexagon.type === 'postcode'
|
||||
? fetchPostcodeStats(selectedHexagon.id)
|
||||
: fetchHexagonStats(selectedHexagon.id, selectedHexagon.resolution);
|
||||
|
||||
fetchStats
|
||||
.then((stats) => {
|
||||
if (cancelled) return;
|
||||
if (stats.count === 0) {
|
||||
setSelectedHexagon(null);
|
||||
setAreaStats(null);
|
||||
setSelectedPostcodeGeometry(null);
|
||||
} else {
|
||||
setAreaStats(stats);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
if (cancelled) return;
|
||||
logNonAbortError('Failed to refresh stats', error);
|
||||
})
|
||||
.finally(() => {
|
||||
if (!cancelled) setLoadingAreaStats(false);
|
||||
});
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [filterStr, selectedHexagon, fetchHexagonStats, fetchPostcodeStats]);
|
||||
|
||||
const handleLocationSearch = useCallback(
|
||||
(postcode: string, geometry: PostcodeGeometry) => {
|
||||
trackEvent('Postcode Search');
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue