diff --git a/app/src/frontend/config/map-config.ts b/app/src/frontend/config/map-config.ts index 5dcc1f09..f5fffa3b 100644 --- a/app/src/frontend/config/map-config.ts +++ b/app/src/frontend/config/map-config.ts @@ -20,6 +20,12 @@ export type ConservationAreasEnablementState = 'enabled' | 'disabled'; export type HistoricDataEnablementState = 'enabled' | 'disabled'; +export type VistaEnablementState = 'enabled' | 'disabled'; + +export type HousingEnablementState = 'enabled' | 'disabled'; + +export type CreativeEnablementState = 'enabled' | 'disabled'; + export const mapBackgroundColor: Record = { light: '#F0EEEB', night: '#162639', diff --git a/app/src/frontend/globalContext.ts b/app/src/frontend/globalContext.ts new file mode 100644 index 00000000..6a312410 --- /dev/null +++ b/app/src/frontend/globalContext.ts @@ -0,0 +1,13 @@ +type UserContextType = { + context: string | null, + setContext: React.Dispatch> +} + +const iUserContextState = { + context: null, + setContext: () => {} +} + +const UserContext = createContext(iUserContextState) + +export default UserContext \ No newline at end of file diff --git a/app/src/frontend/map/creative-switcher.css b/app/src/frontend/map/creative-switcher.css new file mode 100644 index 00000000..1c2cc2e3 --- /dev/null +++ b/app/src/frontend/map/creative-switcher.css @@ -0,0 +1,37 @@ +.creative-theme { + filter: grayscale(100%) invert(1); +} + +.creative-theme { + filter: none; +} + +.creative-switcher { + z-index: 1000; + position: absolute; + top: 397px; + right: 10px; + float: right; + background: white; + border-radius: 4px; +} +.creative-switcher .btn { + margin: 0; + min-width: 280px; +} +.creative-switcher.night .btn { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} +.creative-switcher.night .btn:hover { + color: #343a40; + background-color: transparent; + background-image: none; + border-color: #343a40; +} +@media (max-width: 990px){ + .creative-switcher { + visibility: hidden; + } +} diff --git a/app/src/frontend/map/creative-switcher.tsx b/app/src/frontend/map/creative-switcher.tsx new file mode 100644 index 00000000..f7d9e1d7 --- /dev/null +++ b/app/src/frontend/map/creative-switcher.tsx @@ -0,0 +1,19 @@ +import React from 'react'; + +import './creative-switcher.css'; + +interface CreativeSwitcherProps { + currentDisplay: string; + onSubmit: (e: React.FormEvent) => void; +} + +const CreativeSwitcherProps: React.FC = (props) => ( +
+ +
+); + +export default CreativeSwitcherProps; diff --git a/app/src/frontend/map/housing-switcher.css b/app/src/frontend/map/housing-switcher.css new file mode 100644 index 00000000..747442dd --- /dev/null +++ b/app/src/frontend/map/housing-switcher.css @@ -0,0 +1,37 @@ +.housing-theme { + filter: grayscale(100%) invert(1); +} + +.housing-theme { + filter: none; +} + +.housing-switcher { + z-index: 1000; + position: absolute; + top: 357px; + right: 10px; + float: right; + background: white; + border-radius: 4px; +} +.housing-switcher .btn { + margin: 0; + min-width: 280px; +} +.housing-switcher.night .btn { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} +.housing-switcher.night .btn:hover { + color: #343a40; + background-color: transparent; + background-image: none; + border-color: #343a40; +} +@media (max-width: 990px){ + .housing-switcher { + visibility: hidden; + } +} diff --git a/app/src/frontend/map/housing-switcher.tsx b/app/src/frontend/map/housing-switcher.tsx new file mode 100644 index 00000000..2eef9c02 --- /dev/null +++ b/app/src/frontend/map/housing-switcher.tsx @@ -0,0 +1,19 @@ +import React from 'react'; + +import './housing-switcher.css'; + +interface HousingSwitcherProps { + currentDisplay: string; + onSubmit: (e: React.FormEvent) => void; +} + +const HousingSwitcherProps: React.FC = (props) => ( +
+ +
+); + +export default HousingSwitcherProps; diff --git a/app/src/frontend/map/layers/creative-boundary-layer.tsx b/app/src/frontend/map/layers/creative-boundary-layer.tsx new file mode 100644 index 00000000..43daa4ab --- /dev/null +++ b/app/src/frontend/map/layers/creative-boundary-layer.tsx @@ -0,0 +1,25 @@ +import { GeoJsonObject } from 'geojson'; +import React, { useEffect, useState } from 'react'; +import { GeoJSON } from 'react-leaflet'; +import { CreativeEnablementState } from '../../config/map-config'; +import { apiGet } from '../../apiHelpers'; + +export function CreativeBoundaryLayer({enablement}: {enablement: CreativeEnablementState}) { + const [boundaryGeojson, setBoundaryGeojson] = useState(null); + + useEffect(() => { + apiGet('/geometries/creative_enterprise_zones.geojson') + .then(data => setBoundaryGeojson(data as GeoJsonObject)); + }, []); + + if(enablement == "enabled") { + return boundaryGeojson && + ; + } else if (enablement == "disabled") { + return
+ } +} diff --git a/app/src/frontend/map/layers/housing-boundary-layer.tsx b/app/src/frontend/map/layers/housing-boundary-layer.tsx new file mode 100644 index 00000000..0757c942 --- /dev/null +++ b/app/src/frontend/map/layers/housing-boundary-layer.tsx @@ -0,0 +1,25 @@ +import { GeoJsonObject } from 'geojson'; +import React, { useEffect, useState } from 'react'; +import { GeoJSON } from 'react-leaflet'; +import { HousingEnablementState } from '../../config/map-config'; +import { apiGet } from '../../apiHelpers'; + +export function HousingBoundaryLayer({enablement}: {enablement: HousingEnablementState}) { + const [boundaryGeojson, setBoundaryGeojson] = useState(null); + + useEffect(() => { + apiGet('/geometries/housing_zones.geojson') + .then(data => setBoundaryGeojson(data as GeoJsonObject)); + }, []); + + if(enablement == "enabled") { + return boundaryGeojson && + ; + } else if (enablement == "disabled") { + return
+ } +} diff --git a/app/src/frontend/map/layers/vista-boundary-layer.tsx b/app/src/frontend/map/layers/vista-boundary-layer.tsx new file mode 100644 index 00000000..5dec2d14 --- /dev/null +++ b/app/src/frontend/map/layers/vista-boundary-layer.tsx @@ -0,0 +1,25 @@ +import { GeoJsonObject } from 'geojson'; +import React, { useEffect, useState } from 'react'; +import { GeoJSON } from 'react-leaflet'; +import { FloodEnablementState } from '../../config/map-config'; +import { apiGet } from '../../apiHelpers'; + +export function VistaBoundaryLayer({enablement}: {enablement: FloodEnablementState}) { + const [boundaryGeojson, setBoundaryGeojson] = useState(null); + + useEffect(() => { + apiGet('/geometries/protected_vistas.geojson') + .then(data => setBoundaryGeojson(data as GeoJsonObject)); + }, []); + + if(enablement == "enabled") { + return boundaryGeojson && + ; + } else if (enablement == "disabled") { + return
+ } +} diff --git a/app/src/frontend/map/map.tsx b/app/src/frontend/map/map.tsx index 659063e3..3347ab0c 100644 --- a/app/src/frontend/map/map.tsx +++ b/app/src/frontend/map/map.tsx @@ -8,7 +8,7 @@ import { apiGet } from '../apiHelpers'; import { HelpIcon } from '../components/icons'; import { categoryMapsConfig } from '../config/category-maps-config'; import { Category } from '../config/categories-config'; -import { initialMapViewport, mapBackgroundColor, MapTheme, BoroughEnablementState, ParcelEnablementState, FloodEnablementState, ConservationAreasEnablementState, HistoricDataEnablementState } from '../config/map-config'; +import { initialMapViewport, mapBackgroundColor, MapTheme, BoroughEnablementState, ParcelEnablementState, FloodEnablementState, ConservationAreasEnablementState, HistoricDataEnablementState, CreativeEnablementState, HousingEnablementState, VistaEnablementState } from '../config/map-config'; import { Building } from '../models/building'; import { CityBaseMapLayer } from './layers/city-base-map-layer'; @@ -18,6 +18,9 @@ import { ParcelBoundaryLayer } from './layers/parcel-boundary-layer'; import { HistoricDataLayer } from './layers/historic-data-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'; @@ -31,6 +34,9 @@ import ParcelSwitcher from './parcel-switcher'; import FloodSwitcher from './flood-switcher'; import ConservationAreaSwitcher from './conservation-switcher'; import HistoricDataSwitcher from './historic-data-switcher'; +import VistaSwitcher from './vista-switcher'; +import CreativeSwitcher from './creative-switcher'; +import HousingSwitcher from './housing-switcher'; import { BuildingMapTileset } from '../config/tileserver-config'; interface ColouringMapProps { @@ -56,6 +62,9 @@ export const ColouringMap : FC = ({ const [flood, setFlood] = useState('disabled'); const [conservation, setConservation] = useState('disabled'); const [historicData, setHistoricData] = useState('disabled'); + const [creative, setCreative] = useState('disabled'); + const [housing, setHousing] = useState('disabled'); + const [vista, setVista] = useState('disabled'); const [position, setPosition] = useState(initialMapViewport.position); const [zoom, setZoom] = useState(initialMapViewport.zoom); @@ -133,6 +142,33 @@ export const ColouringMap : FC = ({ [historicData], ) + const vistaSwitch = useCallback( + (e) => { + e.preventDefault(); + const newVista = (vista === 'enabled')? 'disabled' : 'enabled'; + setVista(newVista); + }, + [vista], + ) + + const housingSwitch = useCallback( + (e) => { + e.preventDefault(); + const newHousing = (housing === 'enabled')? 'disabled' : 'enabled'; + setHousing(newHousing); + }, + [housing], + ) + + const creativeSwitch = useCallback( + (e) => { + e.preventDefault(); + const newCreative = (creative === 'enabled')? 'disabled' : 'enabled'; + setCreative(newCreative); + }, + [creative], + ) + const categoryMapDefinitions = useMemo(() => categoryMapsConfig[category], [category]); useEffect(() => { @@ -186,6 +222,9 @@ export const ColouringMap : FC = ({ + + + { selectedBuildingId && @@ -215,6 +254,9 @@ export const ColouringMap : FC = ({ + + + } diff --git a/app/src/frontend/map/vista-switcher.css b/app/src/frontend/map/vista-switcher.css new file mode 100644 index 00000000..b8d87255 --- /dev/null +++ b/app/src/frontend/map/vista-switcher.css @@ -0,0 +1,37 @@ +.vista-theme { + filter: grayscale(100%) invert(1); +} + +.vista-theme { + filter: none; +} + +.vista-switcher { + z-index: 1000; + position: absolute; + top: 317px; + right: 10px; + float: right; + background: white; + border-radius: 4px; +} +.vista-switcher .btn { + margin: 0; + min-width: 280px; +} +.vista-switcher.night .btn { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} +.vista-switcher.night .btn:hover { + color: #343a40; + background-color: transparent; + background-image: none; + border-color: #343a40; +} +@media (max-width: 990px){ + .vista-switcher { + visibility: hidden; + } +} diff --git a/app/src/frontend/map/vista-switcher.tsx b/app/src/frontend/map/vista-switcher.tsx new file mode 100644 index 00000000..62d0deb6 --- /dev/null +++ b/app/src/frontend/map/vista-switcher.tsx @@ -0,0 +1,19 @@ +import React from 'react'; + +import './vista-switcher.css'; + +interface VistaSwitcherProps { + currentDisplay: string; + onSubmit: (e: React.FormEvent) => void; +} + +const VistaSwitcherProps: React.FC = (props) => ( +
+ +
+); + +export default VistaSwitcherProps; diff --git a/app/src/frontend/mapContext.ts b/app/src/frontend/mapContext.ts new file mode 100644 index 00000000..c5c5b316 --- /dev/null +++ b/app/src/frontend/mapContext.ts @@ -0,0 +1,15 @@ +import React from 'react' + +type UserContextType = { + context: string | null, + setContext: React.Dispatch> +} + +const iUserContextState = { + context: null, + setContext: () => {} +} + +const UserContext = React.createContext(iUserContextState) + +export default UserContext \ No newline at end of file diff --git a/app/src/frontend/mapLayerContext.ts b/app/src/frontend/mapLayerContext.ts new file mode 100644 index 00000000..f07f8a51 --- /dev/null +++ b/app/src/frontend/mapLayerContext.ts @@ -0,0 +1,15 @@ +import React from 'react' + +type MapLayerContextType = { + context: 'enabled' | 'disabled', + setContext: React.Dispatch> +} + +const iMapLayerContextType = { + context: null, + setContext: () => {} +} + +const MapLayerContext = React.createContext(iMapLayerContextType) + +export default MapLayerContext \ No newline at end of file