diff --git a/app/src/frontend/map/map.tsx b/app/src/frontend/map/map.tsx index 80447644..568573fc 100644 --- a/app/src/frontend/map/map.tsx +++ b/app/src/frontend/map/map.tsx @@ -1,153 +1,175 @@ - -import React, { FC, useCallback, useEffect, useMemo, useState, useRef } from 'react'; -import { AttributionControl, MapContainer, ZoomControl, useMapEvent, Pane, useMap } from 'react-leaflet'; +import React, { + FC, + useCallback, + useEffect, + useMemo, + useState, + useRef, +} from "react"; +import { + AttributionControl, + MapContainer, + ZoomControl, + useMapEvent, + Pane, + useMap, +} from "react-leaflet"; // import 'leaflet/dist/leaflet.css'; -import './map.css'; +import "./map.css"; -import { apiGet } from '../apiHelpers'; -import { initialMapViewport, mapBackgroundColor, MapTheme, LayerEnablementState } from '../config/map-config'; +import { apiGet } from "../apiHelpers"; +import { + initialMapViewport, + mapBackgroundColor, + MapTheme, + LayerEnablementState, +} from "../config/map-config"; -import mapboxgl from 'mapbox-gl'; +import mapboxgl from "mapbox-gl"; -import { Building } from '../models/building'; +import { Building } from "../models/building"; -import { CityMap } from './layers/city-base-map-layer'; -import { CityBoundaryLayer } from './layers/city-boundary-layer'; -import { BoroughBoundaryLayer } from './layers/borough-boundary-layer'; -import { BoroughLabelLayer } from './layers/borough-label-layer'; -import { ParcelBoundaryLayer } from './layers/parcel-boundary-layer'; -import { HistoricDataLayer } from './layers/historic-data-layer'; -import { HistoricMapLayer } from './layers/historic-map-layer'; -import { FloodBoundaryLayer } from './layers/flood-boundary-layer'; -import { ConservationAreaBoundaryLayer } from './layers/conservation-boundary-layer'; -import { VistaBoundaryLayer } from './layers/vista-boundary-layer'; -import { HousingBoundaryLayer } from './layers/housing-boundary-layer'; -import { CreativeBoundaryLayer } from './layers/creative-boundary-layer'; -import { BuildingBaseLayer } from './layers/building-base-layer'; -import { BuildingDataLayer } from './layers/building-data-layer'; -import { BuildingNumbersLayer } from './layers/building-numbers-layer'; -import { BuildingHighlightLayer } from './layers/building-highlight-layer'; +/*import { CityMap } from './layers/city-base-map-layer';*/ +import { CityBoundaryLayer } from "./layers/city-boundary-layer"; +import { BoroughBoundaryLayer } from "./layers/borough-boundary-layer"; +import { BoroughLabelLayer } from "./layers/borough-label-layer"; +import { ParcelBoundaryLayer } from "./layers/parcel-boundary-layer"; +import { HistoricDataLayer } from "./layers/historic-data-layer"; +import { HistoricMapLayer } from "./layers/historic-map-layer"; +import { FloodBoundaryLayer } from "./layers/flood-boundary-layer"; +import { ConservationAreaBoundaryLayer } from "./layers/conservation-boundary-layer"; +import { VistaBoundaryLayer } from "./layers/vista-boundary-layer"; +import { HousingBoundaryLayer } from "./layers/housing-boundary-layer"; +import { CreativeBoundaryLayer } from "./layers/creative-boundary-layer"; +import { BuildingBaseLayer } from "./layers/building-base-layer"; +import { BuildingDataLayer } from "./layers/building-data-layer"; +import { BuildingNumbersLayer } from "./layers/building-numbers-layer"; +import { BuildingHighlightLayer } from "./layers/building-highlight-layer"; -import { Legend } from './legend'; -import SearchBox from './search-box'; -import ThemeSwitcher from './theme-switcher'; -import DataLayerSwitcher from './data-switcher'; -import { BoroughSwitcher } from './borough-switcher'; -import { ParcelSwitcher } from './parcel-switcher'; -import { FloodSwitcher } from './flood-switcher'; -import { ConservationAreaSwitcher } from './conservation-switcher'; -import { HistoricDataSwitcher } from './historic-data-switcher'; -import { HistoricMapSwitcher } from './historic-map-switcher'; -import { VistaSwitcher } from './vista-switcher'; -import { CreativeSwitcher } from './creative-switcher'; -import { HousingSwitcher } from './housing-switcher'; -import { BuildingMapTileset } from '../config/tileserver-config'; -import { useDisplayPreferences } from '../displayPreferences-context'; -import { CategoryMapDefinition } from '../config/category-maps-config'; - -mapboxgl.accessToken = 'pk.eyJ1IjoiYWxpLWFkbGkiLCJhIjoiY2xuM2JtYjV1MGE5djJrb2d5OGp1ZWNyNiJ9.gENyP4xX6ElLAeZFlE0aDg'; +import { Legend } from "./legend"; +import SearchBox from "./search-box"; +import ThemeSwitcher from "./theme-switcher"; +import DataLayerSwitcher from "./data-switcher"; +import { BoroughSwitcher } from "./borough-switcher"; +import { ParcelSwitcher } from "./parcel-switcher"; +import { FloodSwitcher } from "./flood-switcher"; +import { ConservationAreaSwitcher } from "./conservation-switcher"; +import { HistoricDataSwitcher } from "./historic-data-switcher"; +import { HistoricMapSwitcher } from "./historic-map-switcher"; +import { VistaSwitcher } from "./vista-switcher"; +import { CreativeSwitcher } from "./creative-switcher"; +import { HousingSwitcher } from "./housing-switcher"; +import { BuildingMapTileset } from "../config/tileserver-config"; +import { useDisplayPreferences } from "../displayPreferences-context"; +import { CategoryMapDefinition } from "../config/category-maps-config"; +mapboxgl.accessToken = + "pk.eyJ1IjoiYWxpLWFkbGkiLCJhIjoiY2xuM2JtYjV1MGE5djJrb2d5OGp1ZWNyNiJ9.gENyP4xX6ElLAeZFlE0aDg"; interface ColouringMapProps { - selectedBuildingId: number; - mode: 'basic' | 'view' | 'edit' | 'multi-edit'; - revisionId: string; - onBuildingAction: (building: Building) => void; - mapColourScale: BuildingMapTileset; - onMapColourScale: (x: BuildingMapTileset) => void; - categoryMapDefinitions: CategoryMapDefinition[] + selectedBuildingId: number; + mode: "basic" | "view" | "edit" | "multi-edit"; + revisionId: string; + onBuildingAction: (building: Building) => void; + mapColourScale: BuildingMapTileset; + onMapColourScale: (x: BuildingMapTileset) => void; + categoryMapDefinitions: CategoryMapDefinition[]; } -export const ColouringMap : FC = ({ - mode, - revisionId, - onBuildingAction, - selectedBuildingId, - mapColourScale, - onMapColourScale, - categoryMapDefinitions, - children +export const ColouringMap: FC = ({ + mode, + revisionId, + onBuildingAction, + selectedBuildingId, + mapColourScale, + onMapColourScale, + categoryMapDefinitions, + children, }) => { - const { darkLightTheme, darkLightThemeSwitch, showLayerSelection } = useDisplayPreferences(); - const [position, setPosition] = useState(initialMapViewport.position); - const [zoom, setZoom] = useState(initialMapViewport.zoom); + const { darkLightTheme, darkLightThemeSwitch, showLayerSelection } = + useDisplayPreferences(); + const [position, setPosition] = useState(initialMapViewport.position); + const [zoom, setZoom] = useState(initialMapViewport.zoom); + const handleLocate = useCallback((lat: number, lng: number, zoom: number) => { + setPosition([lat, lng]); + setZoom(zoom); + }, []); - const handleLocate = useCallback( - (lat: number, lng: number, zoom: number) => { - setPosition([lat, lng]); - setZoom(zoom); - }, - [] - ); + const handleClick = useCallback( + async (e) => { + const { lat, lng } = e.latlng; + const data = await apiGet(`/api/buildings/locate?lat=${lat}&lng=${lng}`); + const building = data?.[0]; + onBuildingAction(building); + }, + [onBuildingAction] + ); - const handleClick = useCallback( - async (e) => { - const {lat, lng} = e.latlng; - const data = await apiGet(`/api/buildings/locate?lat=${lat}&lng=${lng}`); - const building = data?.[0]; - onBuildingAction(building); - }, - [onBuildingAction], - ) + const mapContainer = useRef(null); + const map = useRef(null); + const [lng, setLng] = useState(-73.5801403); + const [lat, setLat] = useState(45.4962261); - const mapContainer = useRef(null); - const map = useRef(null); - const [lng, setLng] = useState(-73.5801403); - const [lat, setLat] = useState(45.4962261); - - useEffect(() => { - if (map.current) return; // initialize map only once - map.current = new mapboxgl.Map({ - container: mapContainer.current, - style: 'mapbox://styles/mapbox/streets-v12', - center: [lng, lat], - zoom: zoom - }); - - map.current.on('move', () => { - setLng(map.current.getCenter().lng.toFixed(4)); - setLat(map.current.getCenter().lat.toFixed(4)); - setZoom(map.current.getZoom().toFixed(2)); - }); - }) - - return ( -
- -
- ); -} - -function ClickHandler({ onClick }: {onClick: (e) => void}) { - useMapEvent('click', (e) => onClick(e)); - - return null; -} - -function MapBackgroundColor({ theme}: {theme: MapTheme}) { - const map = useMap(); - useEffect(() => { - map.getContainer().style.backgroundColor = mapBackgroundColor[theme]; + useEffect(() => { + if (map.current) return; // initialize map only once + map.current = new mapboxgl.Map({ + container: mapContainer.current, + style: "mapbox://styles/mapbox/streets-v12", + center: [lng, lat], + zoom: zoom, }); - return null; + map.current.on("move", () => { + setLng(map.current.getCenter().lng.toFixed(4)); + setLat(map.current.getCenter().lat.toFixed(4)); + setZoom(map.current.getZoom().toFixed(2)); + }); + }); + + return ( +
+ ); +}; + +function ClickHandler({ onClick }: { onClick: (e) => void }) { + useMapEvent("click", (e) => onClick(e)); + + return null; +} + +function MapBackgroundColor({ theme }: { theme: MapTheme }) { + const map = useMap(); + useEffect(() => { + map.getContainer().style.backgroundColor = mapBackgroundColor[theme]; + }); + + return null; } function MapViewport({ - position, - zoom + position, + zoom, }: { - position: [number, number]; - zoom: number; + position: [number, number]; + zoom: number; }) { - const map = useMap(); + const map = useMap(); - useEffect(() => { - map.setView(position, zoom) - }, [position, zoom]); + useEffect(() => { + map.setView(position, zoom); + }, [position, zoom]); - return null; + return null; } -