More improvements

This commit is contained in:
Andras Schmelczer 2026-03-08 21:09:30 +00:00
parent e0798b24f7
commit 72653a4ddf
7 changed files with 146 additions and 33 deletions

View file

@ -89,7 +89,7 @@ Rust + Axum. Loads parquet into memory at startup.
**Structure** (uses Rust 2018 module style — `foo.rs` + `foo/` directory, not `foo/mod.rs`):
- `data.rs` + `data/` — Property and POI data loading
- `parsing.rs` + `parsing/` — Filter parsing and bounds parsing
- `routes.rs` + `routes/` — One file per endpoint
- `routes.rs` + `routes/` — One file per endpoint. `properties.rs` exports shared `build_property()` used by both hexagon and postcode property endpoints
- `utils.rs` + `utils/` — GridIndex, hashing, interned columns
- `consts.rs` — Key constants (histogram bins, H3 range, max enum cardinality, excluded columns)
@ -99,6 +99,7 @@ Rust + Axum. Loads parquet into memory at startup.
- `GET /api/postcodes?bounds=&filters=&fields=` — Postcode polygon aggregates, AABB-filtered to bounds
- `GET /api/postcode/:postcode` — Single postcode lookup (centroid + polygon)
- `GET /api/hexagon-properties?h3=&resolution=&filters=&limit=&offset=` — Paginated properties within a hexagon
- `GET /api/postcode-properties?postcode=&filters=&limit=&offset=` — Paginated properties within a postcode
- `GET /api/pois?bounds=&categories=` — POIs by bounds (max 5000)
- `GET /api/poi-categories` — Available POI category names
@ -120,7 +121,7 @@ React 18 + TypeScript. deck.gl `H3HexagonLayer` over MapLibre GL. TailwindCSS. N
- Custom hooks in `hooks/` encapsulate stateful logic:
- `useMapData` — Hexagon/postcode fetching, bounds, loading state, color range calculation
- `useFilters` — Filter state and handlers (add/remove/change/drag/pin)
- `useHexagonSelection` — Selection state, area stats, properties fetching
- `useHexagonSelection` — Selection state, area stats, properties fetching (supports both hexagons and postcodes)
- `usePOIData` — POI fetching with debounce
- `usePaneResize` — Reusable pane resize handlers
- `useTheme` — Theme state with localStorage persistence
@ -324,6 +325,7 @@ Follow these conventions in all Rust code:
- **Travel time is strict**: `mode` param is required (400) when `destination` is set — no silent default to "car". R5 failures return 502 Bad Gateway, not silent omission. `r5_url` is `Option<String>` — returns 503 if travel time requested without R5 configured.
- **Filter bounds format**: `south,west,north,east` (not standard bbox order)
- **Server-side AABB filtering**: Both `/api/hexagons` and `/api/postcodes` filter results by bounding-box intersection with query bounds. Hexagons use `h3_cell_bounds()` (h3o returns degrees, not radians). Postcodes compute polygon AABB from vertices. See `bounds_intersect()` in `parsing/bounds.rs`.
- **Postcode row matching**: Both `postcode-stats` and `postcode-properties` use the same pattern: look up centroid from `postcode_data`, search `GridIndex` within `POSTCODE_SEARCH_OFFSET` (0.02°) of centroid, then exact string match on `state.data.postcode(row)`. Simpler than hexagon matching (no H3 cell computation needed).
- **GridIndex returns slightly more than requested**: The 0.01° grid cells mean properties up to ~1km outside the viewport may be returned. The AABB filter in the route handlers catches these extras.
- **POI proximity**: Uses 0.05° grid (~5km cells) to reduce candidates before haversine distance check
- **OG tag injection**: Uses `<meta name="x-og-placeholder" content="__PERFECT_POSTCODES_OG_TAGS__"/>` placeholder in HTML, replaced at runtime by middleware