516 lines
15 KiB
TypeScript
516 lines
15 KiB
TypeScript
import type { ReactNode, ReactElement } from 'react';
|
|
|
|
/**
|
|
* Per-feature SVG icon paths. Each feature gets a unique icon within its group.
|
|
* All paths render inside a shared 24x24 viewBox with stroke="currentColor".
|
|
*/
|
|
const FEATURE_ICON_PATHS: Record<string, ReactNode> = {
|
|
// ── Properties in the area ───────────────────
|
|
'Last known price': (
|
|
<>
|
|
<path d="M7 20h10" />
|
|
<path d="M10 20V9a4 4 0 018 0" />
|
|
<path d="M6 14h8" />
|
|
</>
|
|
),
|
|
'Estimated current price': (
|
|
<>
|
|
<polyline points="4 16 8 12 13 15 20 6" />
|
|
<polyline points="15 6 21 6 21 12" />
|
|
</>
|
|
),
|
|
'Price per sqm': (
|
|
<>
|
|
<rect x="3" y="3" width="7" height="7" />
|
|
<rect x="14" y="3" width="7" height="7" />
|
|
<rect x="14" y="14" width="7" height="7" />
|
|
<rect x="3" y="14" width="7" height="7" />
|
|
</>
|
|
),
|
|
'Est. price per sqm': (
|
|
<>
|
|
<rect x="3" y="7" width="18" height="10" rx="1" />
|
|
<path d="M7 7v4m4-4v6m4-6v4m4-4v6" />
|
|
</>
|
|
),
|
|
'Total floor area (sqm)': (
|
|
<>
|
|
<polyline points="15 3 21 3 21 9" />
|
|
<polyline points="9 21 3 21 3 15" />
|
|
<line x1="21" y1="3" x2="14" y2="10" />
|
|
<line x1="3" y1="21" x2="10" y2="14" />
|
|
</>
|
|
),
|
|
'Interior height (m)': (
|
|
<>
|
|
<line x1="12" y1="2" x2="12" y2="22" />
|
|
<polyline points="8 6 12 2 16 6" />
|
|
<polyline points="8 18 12 22 16 18" />
|
|
</>
|
|
),
|
|
'Number of bedrooms & living rooms': (
|
|
<>
|
|
<rect x="5" y="2" width="14" height="20" rx="1" />
|
|
<circle cx="15" cy="12" r="1" fill="currentColor" />
|
|
</>
|
|
),
|
|
'Estimated monthly rent': (
|
|
<>
|
|
<circle cx="8" cy="15" r="5" />
|
|
<path d="M12 11l9-9" />
|
|
<path d="M17 2h4v4" />
|
|
</>
|
|
),
|
|
'Date of last transaction': (
|
|
<>
|
|
<rect x="3" y="4" width="18" height="18" rx="2" />
|
|
<line x1="16" y1="2" x2="16" y2="6" />
|
|
<line x1="8" y1="2" x2="8" y2="6" />
|
|
<line x1="3" y1="10" x2="21" y2="10" />
|
|
</>
|
|
),
|
|
'Construction year': (
|
|
<>
|
|
<path d="M14.7 6.3a1 1 0 000 1.4l1.6 1.6a1 1 0 001.4 0l3.77-3.77a6 6 0 01-7.94 7.94l-6.91 6.91a2.12 2.12 0 01-3-3l6.91-6.91a6 6 0 017.94-7.94l-3.76 3.76z" />
|
|
</>
|
|
),
|
|
'Asking price': (
|
|
<>
|
|
<path d="M20.59 13.41l-7.17 7.17a2 2 0 01-2.83 0L2 12V2h10l8.59 8.59a2 2 0 010 2.82z" />
|
|
<line x1="7" y1="7" x2="7.01" y2="7" />
|
|
</>
|
|
),
|
|
'Asking rent (monthly)': (
|
|
<>
|
|
<circle cx="9" cy="9" r="7" />
|
|
<path d="M15.58 8.42A7 7 0 0122 15a7 7 0 01-7 7 7 7 0 01-6.58-4.58" />
|
|
</>
|
|
),
|
|
Bedrooms: (
|
|
<>
|
|
<path d="M2 4v16" />
|
|
<path d="M2 8h18a2 2 0 012 2v10" />
|
|
<path d="M2 17h20" />
|
|
<path d="M6 4v4" />
|
|
</>
|
|
),
|
|
Bathrooms: (
|
|
<>
|
|
<path d="M4 12h16a1 1 0 011 1v3a4 4 0 01-4 4H7a4 4 0 01-4-4v-3a1 1 0 011-1z" />
|
|
<path d="M6 12V5a2 2 0 012-2h3" />
|
|
<line x1="14" y1="4" x2="17" y2="4" />
|
|
</>
|
|
),
|
|
'Listing date': (
|
|
<>
|
|
<circle cx="12" cy="12" r="10" />
|
|
<polyline points="12 6 12 12 16 14" />
|
|
</>
|
|
),
|
|
'Listing status': (
|
|
<>
|
|
<line x1="8" y1="6" x2="21" y2="6" />
|
|
<line x1="8" y1="12" x2="21" y2="12" />
|
|
<line x1="8" y1="18" x2="21" y2="18" />
|
|
<line x1="3" y1="6" x2="3.01" y2="6" />
|
|
<line x1="3" y1="12" x2="3.01" y2="12" />
|
|
<line x1="3" y1="18" x2="3.01" y2="18" />
|
|
</>
|
|
),
|
|
'Leasehold/Freehold': (
|
|
<>
|
|
<path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z" />
|
|
<polyline points="14 2 14 8 20 8" />
|
|
</>
|
|
),
|
|
'Property type': (
|
|
<>
|
|
<path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z" />
|
|
<polyline points="9 22 9 12 15 12 15 22" />
|
|
</>
|
|
),
|
|
'Current energy rating': (
|
|
<>
|
|
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />
|
|
</>
|
|
),
|
|
'Potential energy rating': (
|
|
<>
|
|
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" />
|
|
</>
|
|
),
|
|
|
|
// ── Transport ────────────────────────────────
|
|
'Train or tube stations within 1km': (
|
|
<>
|
|
<rect x="4" y="3" width="16" height="14" rx="2" />
|
|
<path d="M4 11h16" />
|
|
<circle cx="8" cy="15" r="1" fill="currentColor" />
|
|
<circle cx="16" cy="15" r="1" fill="currentColor" />
|
|
<path d="M8 21l-2-4h12l-2 4" />
|
|
</>
|
|
),
|
|
'Distance to nearest train or tube station (km)': (
|
|
<>
|
|
<path d="M12 2v8" />
|
|
<path d="M4.93 10.93l2.83 2.83" />
|
|
<path d="M2 18h2" />
|
|
<path d="M20 18h2" />
|
|
<path d="M19.07 10.93l-2.83 2.83" />
|
|
<circle cx="12" cy="18" r="4" />
|
|
<line x1="12" y1="18" x2="12" y2="15" />
|
|
</>
|
|
),
|
|
|
|
// ── Education ────────────────────────────────
|
|
'Education, Skills and Training Score': (
|
|
<>
|
|
<path d="M2 3h6a4 4 0 014 4 4 4 0 014-4h6v18a2 2 0 01-2 2h-4a4 4 0 00-4 4 4 4 0 00-4-4H4a2 2 0 01-2-2z" />
|
|
</>
|
|
),
|
|
'Good+ primary schools within 5km': (
|
|
<>
|
|
<path d="M4 19V9l8-6 8 6v10" />
|
|
<path d="M9 19v-6h6v6" />
|
|
<line x1="4" y1="19" x2="20" y2="19" />
|
|
</>
|
|
),
|
|
'Good+ secondary schools within 5km': (
|
|
<>
|
|
<path d="M22 10v6M2 10l10-5 10 5-10 5z" />
|
|
<path d="M6 12v5c0 2.5 3 4 6 4s6-1.5 6-4v-5" />
|
|
</>
|
|
),
|
|
|
|
// ── Deprivation ──────────────────────────────
|
|
'Income Score (rate)': (
|
|
<>
|
|
<rect x="2" y="6" width="20" height="14" rx="2" />
|
|
<path d="M2 10h20" />
|
|
<path d="M6 14h4m4 0h4" />
|
|
</>
|
|
),
|
|
'Employment Score (rate)': (
|
|
<>
|
|
<rect x="2" y="7" width="20" height="14" rx="2" />
|
|
<path d="M16 3h-8a2 2 0 00-2 2v2h12V5a2 2 0 00-2-2z" />
|
|
<path d="M12 12v4" />
|
|
</>
|
|
),
|
|
'Health Deprivation and Disability Score': (
|
|
<>
|
|
<path d="M20.42 4.58a5.4 5.4 0 00-7.65 0L12 5.34l-.77-.76a5.4 5.4 0 00-7.65 7.65L12 20.65l8.42-8.42a5.4 5.4 0 000-7.65z" />
|
|
</>
|
|
),
|
|
'Living Environment Score': (
|
|
<>
|
|
<path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z" />
|
|
<path d="M9 16l2 2 4-4" />
|
|
</>
|
|
),
|
|
'Indoors Sub-domain Score': (
|
|
<>
|
|
<path d="M20 9V6a2 2 0 00-2-2H6a2 2 0 00-2 2v3" />
|
|
<path d="M2 11v5a2 2 0 002 2h1v3h2v-3h10v3h2v-3h1a2 2 0 002-2v-5a3 3 0 00-3-3H5a3 3 0 00-3 3z" />
|
|
</>
|
|
),
|
|
'Outdoors Sub-domain Score': (
|
|
<>
|
|
<path d="M11 20A7 7 0 019.8 6.9C15.5 4.9 20 9 20 9s-3.4 5.4-3.4 9c0 .6 0 1.2-.1 1.8" />
|
|
<path d="M12 10a3.5 3.5 0 00-5 5" />
|
|
</>
|
|
),
|
|
|
|
// ── Crime summary ────────────────────────────
|
|
'Serious crime (avg/yr)': (
|
|
<>
|
|
<path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z" />
|
|
<line x1="12" y1="9" x2="12" y2="13" />
|
|
<line x1="12" y1="17" x2="12.01" y2="17" />
|
|
</>
|
|
),
|
|
'Minor crime (avg/yr)': (
|
|
<>
|
|
<circle cx="12" cy="12" r="10" />
|
|
<line x1="12" y1="8" x2="12" y2="12" />
|
|
<line x1="12" y1="16" x2="12.01" y2="16" />
|
|
</>
|
|
),
|
|
'Serious crime per 1k residents (avg/yr)': (
|
|
<>
|
|
<line x1="12" y1="3" x2="12" y2="15" />
|
|
<circle cx="12" cy="18" r="3" />
|
|
<path d="M8 3h8" />
|
|
</>
|
|
),
|
|
'Minor crime per 1k residents (avg/yr)': (
|
|
<>
|
|
<path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2" />
|
|
<circle cx="9" cy="7" r="4" />
|
|
<path d="M23 21v-2a4 4 0 00-3-3.87" />
|
|
<path d="M16 3.13a4 4 0 010 7.75" />
|
|
</>
|
|
),
|
|
|
|
// ── Crime ────────────────────────────────────
|
|
'Anti-social behaviour (avg/yr)': (
|
|
<>
|
|
<path d="M3 11l18-5v12L3 13v-2z" />
|
|
<path d="M11.6 16.8a3 3 0 015.8 0" />
|
|
</>
|
|
),
|
|
'Violence and sexual offences (avg/yr)': (
|
|
<>
|
|
<path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z" />
|
|
<line x1="12" y1="9" x2="12" y2="13" />
|
|
<line x1="12" y1="17" x2="12.01" y2="17" />
|
|
</>
|
|
),
|
|
'Criminal damage and arson (avg/yr)': (
|
|
<>
|
|
<path d="M12 12c2-2.67 4-4 4-6.5a4 4 0 10-8 0c0 2.5 2 3.83 4 6.5z" />
|
|
<path d="M10 17c0 1.1.9 2 2 2s2-.9 2-2c0-1.33-1-2-2-3-1 1-2 1.67-2 3z" />
|
|
</>
|
|
),
|
|
'Burglary (avg/yr)': (
|
|
<>
|
|
<rect x="3" y="11" width="18" height="11" rx="2" />
|
|
<path d="M7 11V7a5 5 0 0110 0v4" />
|
|
<path d="M12 17v-2" />
|
|
</>
|
|
),
|
|
'Vehicle crime (avg/yr)': (
|
|
<>
|
|
<path d="M5 17h14v-5l-2-5H7L5 12z" />
|
|
<circle cx="7.5" cy="17.5" r="2.5" />
|
|
<circle cx="16.5" cy="17.5" r="2.5" />
|
|
</>
|
|
),
|
|
'Robbery (avg/yr)': (
|
|
<>
|
|
<circle cx="12" cy="12" r="10" />
|
|
<line x1="4" y1="8" x2="20" y2="8" />
|
|
<line x1="4" y1="16" x2="20" y2="16" />
|
|
<line x1="12" y1="2" x2="12" y2="8" />
|
|
</>
|
|
),
|
|
'Other theft (avg/yr)': (
|
|
<>
|
|
<path d="M18 8a6 6 0 00-12 0c0 7-3 9-3 9h18s-3-2-3-9" />
|
|
<path d="M13.73 21a2 2 0 01-3.46 0" />
|
|
</>
|
|
),
|
|
'Shoplifting (avg/yr)': (
|
|
<>
|
|
<path d="M6 2L3 6v14a2 2 0 002 2h14a2 2 0 002-2V6l-3-4z" />
|
|
<line x1="3" y1="6" x2="21" y2="6" />
|
|
<path d="M16 10a4 4 0 01-8 0" />
|
|
</>
|
|
),
|
|
'Drugs (avg/yr)': (
|
|
<>
|
|
<path d="M10.5 1.5H8a6.5 6.5 0 000 13h8a6.5 6.5 0 000-13h-2.5" />
|
|
<line x1="12" y1="1" x2="12" y2="14" />
|
|
</>
|
|
),
|
|
'Possession of weapons (avg/yr)': (
|
|
<>
|
|
<circle cx="12" cy="12" r="10" />
|
|
<line x1="22" y1="12" x2="18" y2="12" />
|
|
<line x1="6" y1="12" x2="2" y2="12" />
|
|
<line x1="12" y1="6" x2="12" y2="2" />
|
|
<line x1="12" y1="22" x2="12" y2="18" />
|
|
</>
|
|
),
|
|
'Public order (avg/yr)': (
|
|
<>
|
|
<line x1="1" y1="12" x2="3" y2="12" />
|
|
<polyline points="8 8 12 4 16 8" />
|
|
<line x1="12" y1="4" x2="12" y2="20" />
|
|
<polyline points="8 16 12 20 16 16" />
|
|
<line x1="21" y1="12" x2="23" y2="12" />
|
|
</>
|
|
),
|
|
'Bicycle theft (avg/yr)': (
|
|
<>
|
|
<circle cx="6" cy="17" r="3" />
|
|
<circle cx="18" cy="17" r="3" />
|
|
<path d="M6 17l4-8h4l2 4 2-4" />
|
|
</>
|
|
),
|
|
'Theft from the person (avg/yr)': (
|
|
<>
|
|
<rect x="2" y="6" width="20" height="14" rx="2" />
|
|
<path d="M2 10h20" />
|
|
<path d="M6 14h4m4 0h4" />
|
|
</>
|
|
),
|
|
'Other crime (avg/yr)': (
|
|
<>
|
|
<path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z" />
|
|
<polyline points="14 2 14 8 20 8" />
|
|
<line x1="12" y1="12" x2="12" y2="16" />
|
|
<line x1="12" y1="18" x2="12.01" y2="18" />
|
|
</>
|
|
),
|
|
|
|
// ── Demographics ─────────────────────────────
|
|
'% White': (
|
|
<>
|
|
<path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2" />
|
|
<circle cx="9" cy="7" r="4" />
|
|
<path d="M23 21v-2a4 4 0 00-3-3.87" />
|
|
<path d="M16 3.13a4 4 0 010 7.75" />
|
|
</>
|
|
),
|
|
'% South Asian': (
|
|
<>
|
|
<path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2" />
|
|
<circle cx="9" cy="7" r="4" />
|
|
<path d="M23 21v-2a4 4 0 00-3-3.87" />
|
|
<path d="M16 3.13a4 4 0 010 7.75" />
|
|
</>
|
|
),
|
|
'% East Asian': (
|
|
<>
|
|
<path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2" />
|
|
<circle cx="9" cy="7" r="4" />
|
|
<path d="M23 21v-2a4 4 0 00-3-3.87" />
|
|
<path d="M16 3.13a4 4 0 010 7.75" />
|
|
</>
|
|
),
|
|
'% Black': (
|
|
<>
|
|
<path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2" />
|
|
<circle cx="9" cy="7" r="4" />
|
|
<path d="M23 21v-2a4 4 0 00-3-3.87" />
|
|
<path d="M16 3.13a4 4 0 010 7.75" />
|
|
</>
|
|
),
|
|
'% Mixed': (
|
|
<>
|
|
<path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2" />
|
|
<circle cx="9" cy="7" r="4" />
|
|
<path d="M23 21v-2a4 4 0 00-3-3.87" />
|
|
<path d="M16 3.13a4 4 0 010 7.75" />
|
|
</>
|
|
),
|
|
'% Other': (
|
|
<>
|
|
<path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2" />
|
|
<circle cx="9" cy="7" r="4" />
|
|
<path d="M23 21v-2a4 4 0 00-3-3.87" />
|
|
<path d="M16 3.13a4 4 0 010 7.75" />
|
|
</>
|
|
),
|
|
|
|
// ── Amenities ────────────────────────────────
|
|
'Number of restaurants within 2km': (
|
|
<>
|
|
<path d="M3 2v8c0 1.1.9 2 2 2h2v10h2V12h2a2 2 0 002-2V2" />
|
|
<path d="M7 2v4" />
|
|
<path d="M19 2v20" />
|
|
<path d="M19 8a3 3 0 00-3-3" />
|
|
</>
|
|
),
|
|
'Number of grocery shops and supermarkets within 2km': (
|
|
<>
|
|
<circle cx="9" cy="21" r="1" />
|
|
<circle cx="20" cy="21" r="1" />
|
|
<path d="M1 1h4l2.68 13.39a2 2 0 002 1.61h9.72a2 2 0 002-1.61L23 6H6" />
|
|
</>
|
|
),
|
|
'Number of parks within 2km': (
|
|
<>
|
|
<path d="M12 22v-7" />
|
|
<path d="M17 15H7l2-4H5l7-9 7 9h-4l2 4z" />
|
|
</>
|
|
),
|
|
|
|
// ── Environment ──────────────────────────────
|
|
'Noise (dB)': (
|
|
<>
|
|
<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" />
|
|
<path d="M19.07 4.93a10 10 0 010 14.14" />
|
|
<path d="M15.54 8.46a5 5 0 010 7.07" />
|
|
</>
|
|
),
|
|
'Max available download speed (Mbps)': (
|
|
<>
|
|
<path d="M5 12.55a11 11 0 0114.08 0" />
|
|
<path d="M1.42 9a16 16 0 0121.16 0" />
|
|
<path d="M8.53 16.11a6 6 0 016.95 0" />
|
|
<line x1="12" y1="20" x2="12.01" y2="20" />
|
|
</>
|
|
),
|
|
'Environmental risk': (
|
|
<>
|
|
<path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z" />
|
|
<line x1="12" y1="9" x2="12" y2="13" />
|
|
<line x1="12" y1="17" x2="12.01" y2="17" />
|
|
</>
|
|
),
|
|
'Collapsible deposits risk': (
|
|
<>
|
|
<polyline points="12 2 2 7 12 12 22 7 12 2" />
|
|
<polyline points="2 17 12 22 22 17" />
|
|
<polyline points="2 12 12 17 22 12" />
|
|
</>
|
|
),
|
|
'Compressible ground risk': (
|
|
<>
|
|
<line x1="12" y1="2" x2="12" y2="22" />
|
|
<polyline points="16 6 12 2 8 6" />
|
|
<polyline points="16 18 12 22 8 18" />
|
|
<line x1="4" y1="12" x2="20" y2="12" />
|
|
</>
|
|
),
|
|
'Landslide risk': (
|
|
<>
|
|
<path d="M8 3l4 8 5-5 5 15H2L8 3z" />
|
|
</>
|
|
),
|
|
'Running sand risk': (
|
|
<>
|
|
<path d="M2 6c2-1 4-1 6 0s4 1 6 0 4-1 6 0" />
|
|
<path d="M2 12c2-1 4-1 6 0s4 1 6 0 4-1 6 0" />
|
|
<path d="M2 18c2-1 4-1 6 0s4 1 6 0 4-1 6 0" />
|
|
</>
|
|
),
|
|
'Shrink-swell risk': (
|
|
<>
|
|
<line x1="2" y1="12" x2="22" y2="12" />
|
|
<polyline points="6 8 2 12 6 16" />
|
|
<polyline points="18 8 22 12 18 16" />
|
|
</>
|
|
),
|
|
'Soluble rocks risk': (
|
|
<>
|
|
<path d="M12 2.69l5.66 5.66a8 8 0 11-11.31 0z" />
|
|
</>
|
|
),
|
|
};
|
|
|
|
/**
|
|
* Returns a complete SVG icon element for a given feature name, or null if unmapped.
|
|
*/
|
|
export function getFeatureIcon(
|
|
featureName: string,
|
|
className: string,
|
|
): ReactElement | null {
|
|
const paths = FEATURE_ICON_PATHS[featureName];
|
|
if (!paths) return null;
|
|
return (
|
|
<svg
|
|
className={className}
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth={2}
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
{paths}
|
|
</svg>
|
|
);
|
|
}
|