Improve UI
This commit is contained in:
parent
5fe192d25a
commit
ae29662c92
14 changed files with 221 additions and 313 deletions
|
|
@ -5,10 +5,10 @@ import type { ViewState } from '../types';
|
|||
// =============================================================================
|
||||
|
||||
/** Geographic bounds constraining map panning [west, south, east, north] */
|
||||
export const MAP_BOUNDS: [number, number, number, number] = [-12, 49, 4, 62];
|
||||
export const MAP_BOUNDS: [number, number, number, number] = [-9.5, 49, 5, 57];
|
||||
|
||||
/** Minimum zoom level (can't zoom out further) */
|
||||
export const MAP_MIN_ZOOM = 5;
|
||||
export const MAP_MIN_ZOOM = 5.5;
|
||||
|
||||
/** Maximum zoom level for tile fetching (map extrapolates beyond this) */
|
||||
export const TILE_MAX_ZOOM = 15;
|
||||
|
|
@ -74,3 +74,43 @@ export const TWEMOJI_BASE = 'https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/
|
|||
|
||||
/** OpenStreetMap attribution HTML */
|
||||
export const OSM_ATTRIBUTION = '© <a href="https://openstreetmap.org">OpenStreetMap</a>';
|
||||
|
||||
// =============================================================================
|
||||
// Crime Category Breakdowns
|
||||
// =============================================================================
|
||||
|
||||
/** Component crimes that make up each aggregate crime metric */
|
||||
export const CRIME_BREAKDOWNS: Record<string, string[]> = {
|
||||
'Serious crime (avg/yr)': [
|
||||
'Violence and sexual offences (avg/yr)',
|
||||
'Robbery (avg/yr)',
|
||||
'Burglary (avg/yr)',
|
||||
'Possession of weapons (avg/yr)',
|
||||
],
|
||||
'Minor crime (avg/yr)': [
|
||||
'Anti-social behaviour (avg/yr)',
|
||||
'Criminal damage and arson (avg/yr)',
|
||||
'Shoplifting (avg/yr)',
|
||||
'Bicycle theft (avg/yr)',
|
||||
'Theft from the person (avg/yr)',
|
||||
'Other theft (avg/yr)',
|
||||
'Vehicle crime (avg/yr)',
|
||||
'Public order (avg/yr)',
|
||||
'Drugs (avg/yr)',
|
||||
'Other crime (avg/yr)',
|
||||
],
|
||||
};
|
||||
|
||||
/** Colors for crime breakdown segments (designed for 10 distinct categories) */
|
||||
export const CRIME_SEGMENT_COLORS = [
|
||||
'#ef4444', // red-500
|
||||
'#f97316', // orange-500
|
||||
'#eab308', // yellow-500
|
||||
'#22c55e', // green-500
|
||||
'#14b8a6', // teal-500
|
||||
'#06b6d4', // cyan-500
|
||||
'#3b82f6', // blue-500
|
||||
'#8b5cf6', // violet-500
|
||||
'#d946ef', // fuchsia-500
|
||||
'#ec4899', // pink-500
|
||||
];
|
||||
|
|
|
|||
|
|
@ -22,15 +22,3 @@ export function groupFeaturesByCategory(features: FeatureMeta[]): FeatureGroup[]
|
|||
|
||||
return groups;
|
||||
}
|
||||
|
||||
// Feature lookup utilities
|
||||
export function getFeatureByName(
|
||||
name: string,
|
||||
features: FeatureMeta[]
|
||||
): FeatureMeta | undefined {
|
||||
return features.find((f) => f.name === name);
|
||||
}
|
||||
|
||||
export function createFeatureMap(features: FeatureMeta[]): Map<string, FeatureMeta> {
|
||||
return new Map(features.map((f) => [f.name, f]));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,33 +1,5 @@
|
|||
import type { Property } from '../types';
|
||||
|
||||
// Field aliases: maps human-readable names to snake_case names
|
||||
// The server may return either depending on source
|
||||
const FIELD_ALIASES: Record<string, string[]> = {
|
||||
price: ['Last known price', 'latest_price'],
|
||||
pricePerSqm: ['Price per sqm', 'price_per_sqm'],
|
||||
floorArea: ['Total floor area (sqm)', 'total_floor_area'],
|
||||
rooms: ['Rooms (including bedrooms & bathrooms)', 'number_habitable_rooms'],
|
||||
constructionAge: ['Approximate construction age', 'construction_age_band'],
|
||||
councilTax: ['Council tax (£/yr)'],
|
||||
councilTaxD: ['Council tax Band D (£/yr)'],
|
||||
};
|
||||
|
||||
export function getPropertyNumber(
|
||||
property: Property,
|
||||
field: keyof typeof FIELD_ALIASES
|
||||
): number | undefined {
|
||||
const keys = FIELD_ALIASES[field];
|
||||
if (!keys) return undefined;
|
||||
|
||||
for (const key of keys) {
|
||||
const v = property[key];
|
||||
if (v !== undefined && v !== null && typeof v === 'number') {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Generic getter for any field names (for dynamic lookups)
|
||||
export function getNum(property: Property, ...keys: string[]): number | undefined {
|
||||
for (const key of keys) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue