Move into folders
This commit is contained in:
parent
ee73ab77fd
commit
5cbb180c57
24 changed files with 181 additions and 185 deletions
|
|
@ -1,16 +1,16 @@
|
|||
import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
|
||||
import { trackPageview } from './usePlausible';
|
||||
import Map from './components/Map';
|
||||
import type { SearchedPostcode } from './components/PostcodeSearch';
|
||||
import Filters from './components/Filters';
|
||||
import POIPane from './components/POIPane';
|
||||
import { PropertiesPane } from './components/PropertiesPane';
|
||||
import AreaPane from './components/AreaPane';
|
||||
import DataSources from './components/DataSources';
|
||||
import DataSourcesPage from './components/DataSourcesPage';
|
||||
import FAQPage from './components/FAQPage';
|
||||
import HomePage from './components/HomePage';
|
||||
import Header, { type Page } from './components/Header';
|
||||
import Map from './components/map/Map';
|
||||
import type { SearchedPostcode } from './components/map/PostcodeSearch';
|
||||
import Filters from './components/map/Filters';
|
||||
import POIPane from './components/map/POIPane';
|
||||
import { PropertiesPane } from './components/map/PropertiesPane';
|
||||
import AreaPane from './components/map/AreaPane';
|
||||
import DataSources from './components/data-sources/DataSources';
|
||||
import DataSourcesPage from './components/data-sources/DataSourcesPage';
|
||||
import FAQPage from './components/faq/FAQPage';
|
||||
import HomePage from './components/home/HomePage';
|
||||
import Header, { type Page } from './components/shared/Header';
|
||||
import { TabButton } from './components/ui/TabButton';
|
||||
import type {
|
||||
FeatureMeta,
|
||||
|
|
@ -18,7 +18,7 @@ import type {
|
|||
FeatureFilters,
|
||||
Bounds,
|
||||
HexagonData,
|
||||
PostcodeData,
|
||||
PostcodeFeature,
|
||||
ViewChangeParams,
|
||||
ApiResponse,
|
||||
POI,
|
||||
|
|
@ -58,7 +58,7 @@ export default function App() {
|
|||
const [dragValue, setDragValue] = useState<[number, number] | null>(null);
|
||||
const [pinnedFeature, setPinnedFeature] = useState<string | null>(null);
|
||||
const [rawData, setRawData] = useState<HexagonData[]>([]);
|
||||
const [postcodeData, setPostcodeData] = useState<PostcodeData[]>([]);
|
||||
const [postcodeData, setPostcodeData] = useState<PostcodeFeature[]>([]);
|
||||
const [dragData, setDragData] = useState<HexagonData[] | null>(null);
|
||||
const [resolution, setResolution] = useState<number>(8);
|
||||
const [bounds, setBounds] = useState<Bounds | null>(null);
|
||||
|
|
@ -251,7 +251,7 @@ export default function App() {
|
|||
const res = await fetch(apiUrl('postcodes', params), {
|
||||
signal: abortControllerRef.current.signal,
|
||||
});
|
||||
const json: { features: PostcodeData[] } = await res.json();
|
||||
const json: { features: PostcodeFeature[] } = await res.json();
|
||||
setPostcodeData(json.features || []);
|
||||
setRawData([]); // Clear hexagon data
|
||||
} else {
|
||||
|
|
@ -300,20 +300,30 @@ export default function App() {
|
|||
// If dragData hasn't loaded yet, return null to trigger fallback
|
||||
if (activeFeature && !dragData) return null;
|
||||
|
||||
// Choose the appropriate data source based on zoom level
|
||||
const sourceData = usePostcodeView ? postcodeData : data;
|
||||
if (sourceData.length === 0) return null;
|
||||
|
||||
// Only use min_<feature> values since that's what hexagon coloring uses
|
||||
let min = Infinity;
|
||||
let max = -Infinity;
|
||||
for (const item of sourceData) {
|
||||
const val = item[`min_${viewFeature}`];
|
||||
if (typeof val === 'number' && !isNaN(val)) {
|
||||
min = Math.min(min, val);
|
||||
max = Math.max(max, val);
|
||||
|
||||
if (usePostcodeView) {
|
||||
if (postcodeData.length === 0) return null;
|
||||
for (const feat of postcodeData) {
|
||||
const val = feat.properties[`min_${viewFeature}`];
|
||||
if (typeof val === 'number' && !isNaN(val)) {
|
||||
min = Math.min(min, val);
|
||||
max = Math.max(max, val);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (data.length === 0) return null;
|
||||
for (const item of data) {
|
||||
const val = item[`min_${viewFeature}`];
|
||||
if (typeof val === 'number' && !isNaN(val)) {
|
||||
min = Math.min(min, val);
|
||||
max = Math.max(max, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (min === Infinity || max === -Infinity) return null;
|
||||
return [min, max];
|
||||
}, [viewFeature, data, dragData, postcodeData, usePostcodeView, features, activeFeature]);
|
||||
|
|
@ -505,28 +515,29 @@ export default function App() {
|
|||
[filters, features]
|
||||
);
|
||||
|
||||
/** Build stats from already-loaded PostcodeData (min/max per feature). */
|
||||
/** Build stats from already-loaded PostcodeFeature (min/max per feature). */
|
||||
const buildPostcodeStats = useCallback(
|
||||
(postcode: string): HexagonStatsResponse | null => {
|
||||
const pc = postcodeData.find((d) => d.postcode === postcode);
|
||||
if (!pc) return null;
|
||||
const feat = postcodeData.find((f) => f.properties.postcode === postcode);
|
||||
if (!feat) return null;
|
||||
const props = feat.properties;
|
||||
|
||||
const numeric_features: NumericFeatureStats[] = [];
|
||||
for (const f of features) {
|
||||
if (f.type !== 'numeric') continue;
|
||||
const minVal = pc[`min_${f.name}`];
|
||||
const maxVal = pc[`max_${f.name}`];
|
||||
const minVal = props[`min_${f.name}`];
|
||||
const maxVal = props[`max_${f.name}`];
|
||||
if (typeof minVal !== 'number' || typeof maxVal !== 'number') continue;
|
||||
numeric_features.push({
|
||||
name: f.name,
|
||||
count: pc.count,
|
||||
count: props.count,
|
||||
min: minVal,
|
||||
max: maxVal,
|
||||
mean: (minVal + maxVal) / 2,
|
||||
});
|
||||
}
|
||||
|
||||
return { count: pc.count, numeric_features, enum_features: [] };
|
||||
return { count: props.count, numeric_features, enum_features: [] };
|
||||
},
|
||||
[postcodeData, features]
|
||||
);
|
||||
|
|
@ -815,19 +826,16 @@ export default function App() {
|
|||
<div className="flex border-b border-warm-200 dark:border-navy-700 text-sm">
|
||||
<TabButton
|
||||
label="Area"
|
||||
count={areaStats?.count}
|
||||
isActive={rightPaneTab === 'area'}
|
||||
onClick={() => setRightPaneTab('area')}
|
||||
/>
|
||||
<TabButton
|
||||
label="Properties"
|
||||
count={propertiesTotal > 0 ? propertiesTotal : undefined}
|
||||
isActive={rightPaneTab === 'properties'}
|
||||
onClick={handlePropertiesTabClick}
|
||||
/>
|
||||
<TabButton
|
||||
label="POIs"
|
||||
count={pois.length > 0 ? pois.length : undefined}
|
||||
isActive={rightPaneTab === 'pois'}
|
||||
onClick={() => setRightPaneTab('pois')}
|
||||
/>
|
||||
|
|
@ -843,7 +851,7 @@ export default function App() {
|
|||
isPostcode={selectedHexagon?.type === 'postcode'}
|
||||
postcodeData={
|
||||
selectedHexagon?.type === 'postcode'
|
||||
? postcodeData.find((d) => d.postcode === selectedHexagon.id) || null
|
||||
? postcodeData.find((f) => f.properties.postcode === selectedHexagon.id) || null
|
||||
: null
|
||||
}
|
||||
onViewProperties={handleViewPropertiesFromArea}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue