Lots of improvements
This commit is contained in:
parent
205302dbb8
commit
eb02b5832b
39 changed files with 699 additions and 271 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import { useCallback, useRef, useState, useMemo, useEffect } from 'react';
|
||||
import { H3HexagonLayer } from '@deck.gl/geo-layers';
|
||||
import { GeoJsonLayer, IconLayer, TextLayer } from '@deck.gl/layers';
|
||||
import { cellToBoundary } from 'h3-js';
|
||||
import type { PickingInfo } from '@deck.gl/core';
|
||||
import type {
|
||||
HexagonData,
|
||||
|
|
@ -80,13 +81,13 @@ export function useDeckLayers({
|
|||
|
||||
// Marching ants animation
|
||||
const [marchTime, setMarchTime] = useState(0);
|
||||
const hasPostcodeGeometry = selectedPostcodeGeometry != null;
|
||||
const hasSelection = selectedPostcodeGeometry != null || selectedHexagonId != null;
|
||||
useEffect(() => {
|
||||
if (!hasPostcodeGeometry) return;
|
||||
if (!hasSelection) return;
|
||||
setMarchTime(0);
|
||||
const id = setInterval(() => setMarchTime((t) => t + 0.3), 50);
|
||||
return () => clearInterval(id);
|
||||
}, [hasPostcodeGeometry]);
|
||||
}, [hasSelection]);
|
||||
|
||||
const isDark = theme === 'dark';
|
||||
const densityGradient = isDark ? DENSITY_GRADIENT_DARK : DENSITY_GRADIENT;
|
||||
|
|
@ -332,14 +333,11 @@ export function useDeckLayers({
|
|||
);
|
||||
},
|
||||
getLineColor: (d) => {
|
||||
if (d.h3 === selectedHexagonIdRef.current)
|
||||
return [255, 255, 255, 255] as [number, number, number, number];
|
||||
if (d.h3 === hoveredHexagonIdRef.current)
|
||||
return [29, 228, 195, 200] as [number, number, number, number];
|
||||
return [0, 0, 0, 0] as [number, number, number, number];
|
||||
},
|
||||
getLineWidth: (d) => {
|
||||
if (d.h3 === selectedHexagonIdRef.current) return 3;
|
||||
if (d.h3 === hoveredHexagonIdRef.current) return 2;
|
||||
return 0;
|
||||
},
|
||||
|
|
@ -481,15 +479,22 @@ export function useDeckLayers({
|
|||
[pois, stablePoiHover]
|
||||
);
|
||||
|
||||
// Marching ants highlight layer for selected postcode
|
||||
// Marching ants highlight layer for selected hexagon or postcode
|
||||
const marchingAntsLayer = useMemo(() => {
|
||||
if (!selectedPostcodeGeometry) return null;
|
||||
let geometry: PostcodeGeometry | null = null;
|
||||
if (selectedPostcodeGeometry) {
|
||||
geometry = selectedPostcodeGeometry;
|
||||
} else if (selectedHexagonId) {
|
||||
const boundary = cellToBoundary(selectedHexagonId, true);
|
||||
geometry = { type: 'Polygon', coordinates: [boundary] };
|
||||
}
|
||||
if (!geometry) return null;
|
||||
return new GeoJsonLayer({
|
||||
id: 'marching-ants',
|
||||
data: [
|
||||
{
|
||||
type: 'Feature' as const,
|
||||
geometry: selectedPostcodeGeometry,
|
||||
geometry,
|
||||
properties: {},
|
||||
},
|
||||
],
|
||||
|
|
@ -502,7 +507,7 @@ export function useDeckLayers({
|
|||
marchTime,
|
||||
extensions: [new MarchingAntsExtension()],
|
||||
});
|
||||
}, [selectedPostcodeGeometry, marchTime]);
|
||||
}, [selectedPostcodeGeometry, selectedHexagonId, marchTime]);
|
||||
|
||||
const layers = useMemo(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ export function useFilters({ initialFilters, features }: UseFiltersOptions) {
|
|||
if (!meta) return;
|
||||
if (meta.type === 'enum' && meta.values) {
|
||||
setFilters((prev) => ({ ...prev, [name]: [...meta.values!] }));
|
||||
} else if (meta.type === 'numeric' && meta.histogram) {
|
||||
setFilters((prev) => ({ ...prev, [name]: [meta.histogram!.min, meta.histogram!.max] }));
|
||||
} else if (meta.min != null && meta.max != null) {
|
||||
setFilters((prev) => ({ ...prev, [name]: [meta.min!, meta.max!] }));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ export interface TravelTimeEntry {
|
|||
slug: string;
|
||||
label: string;
|
||||
timeRange: [number, number] | null;
|
||||
/** Use best-case (5th percentile) travel time instead of median. Transit only. */
|
||||
useBest: boolean;
|
||||
}
|
||||
|
||||
/** Field key matching the backend response: tt_{mode}_{slug} */
|
||||
|
|
@ -33,7 +35,7 @@ export function useTravelTime(initial?: TravelTimeInitial) {
|
|||
const handleAddEntry = useCallback((mode: TransportMode) => {
|
||||
setEntries((prev) => [
|
||||
...prev,
|
||||
{ mode, slug: '', label: '', timeRange: null },
|
||||
{ mode, slug: '', label: '', timeRange: null, useBest: false },
|
||||
]);
|
||||
}, []);
|
||||
|
||||
|
|
@ -63,6 +65,17 @@ export function useTravelTime(initial?: TravelTimeInitial) {
|
|||
[]
|
||||
);
|
||||
|
||||
const handleToggleBest = useCallback(
|
||||
(index: number) => {
|
||||
setEntries((prev) =>
|
||||
prev.map((entry, i) =>
|
||||
i === index ? { ...entry, useBest: !entry.useBest, timeRange: null } : entry
|
||||
)
|
||||
);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
/** Entries that have a destination selected (slug is set) */
|
||||
const activeEntries = useMemo(
|
||||
() => entries.filter((e) => e.slug !== ''),
|
||||
|
|
@ -76,5 +89,6 @@ export function useTravelTime(initial?: TravelTimeInitial) {
|
|||
handleRemoveEntry,
|
||||
handleSetDestination,
|
||||
handleTimeRangeChange,
|
||||
handleToggleBest,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const STEPS: Step[] = [
|
|||
target: '[data-tutorial="filters"]',
|
||||
title: 'Filter Properties',
|
||||
content:
|
||||
'Use filters to narrow down properties by price, energy rating, floor area, and more. Pin a filter to colour the map by that feature.',
|
||||
'Use filters to narrow down to areas which contain matching properties. Filter by crime rate, number of schools around, or filter to an area with detached houses. Pin a filter with the eye icon to colour the map by that feature.',
|
||||
placement: 'right',
|
||||
disableBeacon: true,
|
||||
},
|
||||
|
|
@ -17,7 +17,7 @@ const STEPS: Step[] = [
|
|||
target: '[data-tutorial="map"]',
|
||||
title: 'Explore the Map',
|
||||
content:
|
||||
'Pan and zoom to explore property data across the UK. Click any hexagon to see detailed stats and individual properties.',
|
||||
'Pan and zoom to explore property data across England. Click any area (hexagon or postcode boundary) to see detailed stats of historical or currently sold properties matching your filters.',
|
||||
placement: 'bottom',
|
||||
disableBeacon: true,
|
||||
},
|
||||
|
|
@ -44,6 +44,11 @@ const STEPS: Step[] = [
|
|||
'Toggle points of interest like schools, shops, and transport stops to see what amenities are nearby.',
|
||||
placement: 'left',
|
||||
disableBeacon: true,
|
||||
styles: {
|
||||
tooltip: {
|
||||
transform: 'translateY(-50px)',
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue