diff --git a/src/frontend/src/components/GenerateMbTiles.jsx b/src/frontend/src/components/GenerateMbTiles.jsx index fa3e4023a3..09060212a3 100644 --- a/src/frontend/src/components/GenerateMbTiles.jsx +++ b/src/frontend/src/components/GenerateMbTiles.jsx @@ -21,7 +21,6 @@ const GenerateMbTiles = ({ setToggleGenerateModal, toggleGenerateModal, projectI border: '1px solid ', padding: '16px 32px 24px 32px', }); - console.log(projectInfo, 'projectInfo'); const downloadMbTiles = (tileId) => { dispatch(DownloadTile(`${import.meta.env.VITE_API_URL}/projects/download_tiles/?tile_id=${tileId}`, projectInfo)); }; diff --git a/src/frontend/src/components/MapComponent/OpenLayersComponent/LayerSwitcher/index.js b/src/frontend/src/components/MapComponent/OpenLayersComponent/LayerSwitcher/index.js index dec28db24b..410a620dfb 100644 --- a/src/frontend/src/components/MapComponent/OpenLayersComponent/LayerSwitcher/index.js +++ b/src/frontend/src/components/MapComponent/OpenLayersComponent/LayerSwitcher/index.js @@ -7,8 +7,8 @@ import LayerTile from 'ol/layer/Tile'; import SourceOSM from 'ol/source/OSM'; import LayerSwitcher from 'ol-layerswitcher'; import React, { useEffect } from 'react'; - import { XYZ } from 'ol/source'; +import { useLocation } from 'react-router-dom'; // const mapboxOutdoors = new MapboxVector({ // styleUrl: 'mapbox://styles/geovation/ckpicg3of094w17nyqyd2ziie', @@ -147,6 +147,33 @@ const LayerSwitcherControl = ({ map, visible = 'osm' }) => { }; }, [map, visible]); + const location = useLocation(); + if (location.pathname.includes('project_details')) { + const olZoom = document.querySelector('.ol-zoom'); + const layerSwitcher = document.querySelector('.layer-switcher'); + + if (olZoom) { + olZoom.style.display = 'none'; + } + + if (layerSwitcher) { + layerSwitcher.style.right = '19px'; + layerSwitcher.style.top = '250px'; + layerSwitcher.style.zIndex = '1000'; + + const layerSwitcherButton = layerSwitcher.querySelector('button'); + if (layerSwitcherButton) { + layerSwitcherButton.style.width = '40px'; + layerSwitcherButton.style.height = '40px'; + } + + layerSwitcher.style.backgroundColor = 'white'; + layerSwitcher.style.display = 'flex'; + layerSwitcher.style.justifyContent = 'center'; + layerSwitcher.style.alignItems = 'center'; + } + } + return null; }; diff --git a/src/frontend/src/components/MapComponent/OpenLayersComponent/Layers/VectorLayer.js b/src/frontend/src/components/MapComponent/OpenLayersComponent/Layers/VectorLayer.js index aa6c761fd4..2bcc1bc2bd 100644 --- a/src/frontend/src/components/MapComponent/OpenLayersComponent/Layers/VectorLayer.js +++ b/src/frontend/src/components/MapComponent/OpenLayersComponent/Layers/VectorLayer.js @@ -47,6 +47,8 @@ const VectorLayer = ({ setStyle, onModify, onDraw, + getTaskStatusStyle, + layerProperties, }) => { const [vectorLayer, setVectorLayer] = useState(null); @@ -157,9 +159,8 @@ const VectorLayer = ({ // Perform an action if a feature is found if (feature) { // Do something with the feature - console.log('Clicked feature:', feature.getProperties()); // dispatch() - mapOnClick(feature.getProperties()); + mapOnClick(feature.getProperties(), feature); } }); setVectorLayer(vectorLyr); @@ -183,6 +184,11 @@ const VectorLayer = ({ vectorLayer.setStyle(setStyle); }, [map, setStyle, vectorLayer, visibleOnMap]); + useEffect(() => { + if (!map || !vectorLayer || !getTaskStatusStyle) return; + vectorLayer.setStyle((feature) => getTaskStatusStyle(feature)); + }, [map, vectorLayer, getTaskStatusStyle]); + useEffect(() => { if (!vectorLayer || !style.visibleOnMap) return; vectorLayer.setStyle((feature, resolution) => getStyles({ style, feature, resolution })); @@ -209,6 +215,11 @@ const VectorLayer = ({ }); }, [vectorLayer, properties]); + useEffect(() => { + if (!map || !vectorLayer || !layerProperties) return; + vectorLayer.setProperties(layerProperties); + }, [map, vectorLayer, layerProperties]); + // style on hover useEffect(() => { if (!map) return null; diff --git a/src/frontend/src/components/MapLegends.jsx b/src/frontend/src/components/MapLegends.jsx index 8da0e8c7f1..9361c9afa4 100755 --- a/src/frontend/src/components/MapLegends.jsx +++ b/src/frontend/src/components/MapLegends.jsx @@ -89,8 +89,8 @@ const MapLegends = ({ direction, spacing, iconBtnProps, defaultTheme, valueStatu // ); // })} // -
-
+
+

Map Legend

diff --git a/src/frontend/src/components/ProjectDetails/MapControlComponent.tsx b/src/frontend/src/components/ProjectDetails/MapControlComponent.tsx new file mode 100644 index 0000000000..930510b602 --- /dev/null +++ b/src/frontend/src/components/ProjectDetails/MapControlComponent.tsx @@ -0,0 +1,116 @@ +import React, { useEffect, useState } from 'react'; +import AssetModules from '../../shared/AssetModules'; +import { transform } from 'ol/proj'; +import * as ol from 'ol'; +import { Point } from 'ol/geom'; +import Vector from 'ol/layer/Vector'; +import VectorSource from 'ol/source/Vector'; +import { Style } from 'ol/style'; +import { Icon } from 'ol/style'; +import LocationImage from '../../assets/images/location.png'; +import VectorLayer from 'ol/layer/Vector'; + +const MapControlComponent = ({ map }) => { + const btnList = [ + { + id: 'add', + icon: , + }, + { + id: 'minus', + icon: , + }, + { + id: 'currentLocation', + icon: , + }, + { + id: 'taskBoundries', + icon: , + }, + ]; + const [toggleCurrentLoc, setToggleCurrentLoc] = useState(false); + const [currentLocLayer, setCurrentLocLayer] = useState(null); + useEffect(() => { + if (!map) return; + if (!currentLocLayer) return; + map.addLayer(currentLocLayer); + map.getView().fit(currentLocLayer.getSource().getExtent(), { + maxZoom: 18, + duration: 500, + }); + return () => { + map.removeLayer(currentLocLayer); + }; + }, [map, currentLocLayer]); + const handleOnClick = (btnId) => { + if (btnId === 'add') { + const actualZoom = map.getView().getZoom(); + map.getView().setZoom(actualZoom + 1); + } else if (btnId === 'minus') { + const actualZoom = map.getView().getZoom(); + map.getView().setZoom(actualZoom - 1); + } else if (btnId === 'currentLocation') { + setToggleCurrentLoc(!toggleCurrentLoc); + const sourceProjection = 'EPSG:4326'; // The current projection of the coordinates + const targetProjection = 'EPSG:3857'; // The desired projection + var markerStyle = new Style({ + image: new Icon({ + src: LocationImage, // Path to your marker icon image + anchor: [0.5, 1], // Anchor point of the marker icon (center bottom) + scale: 2, // Scale factor for the marker icon + }), + }); + if ('geolocation' in navigator) { + if (!toggleCurrentLoc) { + navigator.geolocation.getCurrentPosition((position) => { + const lat = position.coords.latitude; + const lng = position.coords.longitude; + const convertedCoordinates = transform([lng, lat], sourceProjection, targetProjection); + const positionFeature = new ol.Feature(new Point(convertedCoordinates)); + const positionLayer = new Vector({ + source: new VectorSource({ + features: [positionFeature], + }), + }); + positionFeature.setStyle(markerStyle); + setCurrentLocLayer(positionLayer); + }); + } else { + setCurrentLocLayer(null); + } + } + } else if (btnId === 'taskBoundries') { + const layers = map.getAllLayers(); + let extent; + layers.map((layer) => { + if (layer instanceof VectorLayer) { + const layerName = layer.getProperties().name; + if (layerName === 'project-area') { + extent = layer.getSource().getExtent(); + } + } + }); + map.getView().fit(extent, { + padding: [10, 10, 10, 10], + }); + } + }; + + return ( +
+ {btnList.map((btn) => ( +
+
handleOnClick(btn.id)} + > + {btn.icon} +
+
+ ))} +
+ ); +}; + +export default MapControlComponent; diff --git a/src/frontend/src/components/ProjectDetails/MobileFooter.tsx b/src/frontend/src/components/ProjectDetails/MobileFooter.tsx index 8bd86d5f32..25717fdfab 100644 --- a/src/frontend/src/components/ProjectDetails/MobileFooter.tsx +++ b/src/frontend/src/components/ProjectDetails/MobileFooter.tsx @@ -91,7 +91,7 @@ const MobileFooter = () => { ); }; return ( -
+
diff --git a/src/frontend/src/components/ProjectDetails/TaskSectionPopup.tsx b/src/frontend/src/components/ProjectDetails/TaskSectionPopup.tsx index 06c704ef55..2f91da89f9 100644 --- a/src/frontend/src/components/ProjectDetails/TaskSectionPopup.tsx +++ b/src/frontend/src/components/ProjectDetails/TaskSectionPopup.tsx @@ -9,7 +9,7 @@ const TaskSectionPopup = ({ body }) => { return (
{ ); }, [selectedTask]); - const taskOnSelect = (properties) => { + const taskOnSelect = (properties, feature) => { dispatch(CoreModules.TaskActions.SetSelectedTask(properties.uid)); }; diff --git a/src/frontend/src/components/TasksLayer.jsx b/src/frontend/src/components/TasksLayer.jsx index 88e66ee35b..a0542bd281 100755 --- a/src/frontend/src/components/TasksLayer.jsx +++ b/src/frontend/src/components/TasksLayer.jsx @@ -35,8 +35,6 @@ const TasksLayer = (map, view, feature) => { properties: { centroid: task.bbox }, }); }); - console.log(geojsonObject, 'geojsonObject'); - console.log(state.projectTaskBoundries, 'projectTaskBoundries'); const vectorSource = new VectorSource({ features: new GeoJSON().readFeatures(geojsonObject, { featureProjection: get('EPSG:3857'), diff --git a/src/frontend/src/components/common/Accordion.tsx b/src/frontend/src/components/common/Accordion.tsx index a0e460d3bc..9cbc69296a 100644 --- a/src/frontend/src/components/common/Accordion.tsx +++ b/src/frontend/src/components/common/Accordion.tsx @@ -32,7 +32,7 @@ export default function Accordion({
{ if (disableHeaderClickToggle) return; diff --git a/src/frontend/src/components/common/BottomSheet.tsx b/src/frontend/src/components/common/BottomSheet.tsx index 2cb349f925..5bcfb6eec0 100644 --- a/src/frontend/src/components/common/BottomSheet.tsx +++ b/src/frontend/src/components/common/BottomSheet.tsx @@ -71,7 +71,7 @@ const BottomSheet = ({ body, onClose }) => { }, [currSheetHeight]); return ( -
+
import('./views/ProjectDetails')); const Submissions = React.lazy(() => import('./views/Submissions')); @@ -120,13 +121,25 @@ const routes = createBrowserRouter([ ), }, + // { + // path: '/project_details/:id', + // element: ( + // + // Loading...
}> + // + // + // + // + // + // ), + // }, { path: '/project_details/:id', element: ( Loading...
}> - + diff --git a/src/frontend/src/shared/AssetModules.js b/src/frontend/src/shared/AssetModules.js index 1c42f19b05..fb3994124a 100755 --- a/src/frontend/src/shared/AssetModules.js +++ b/src/frontend/src/shared/AssetModules.js @@ -46,6 +46,7 @@ import { Info as InfoIcon, MoreVert as MoreVertIcon, LocationOn as LocationOnIcon, + CropFree as CropFreeIcon, LegendToggle as LegendToggleIcon, } from '@mui/icons-material'; import LockPng from '../assets/images/lock.png'; @@ -103,5 +104,6 @@ export default { InfoIcon, MoreVertIcon, LocationOnIcon, + CropFreeIcon, LegendToggleIcon, }; diff --git a/src/frontend/src/utilfunctions/getTaskStatusStyle.js b/src/frontend/src/utilfunctions/getTaskStatusStyle.js new file mode 100644 index 0000000000..9e19cbc52f --- /dev/null +++ b/src/frontend/src/utilfunctions/getTaskStatusStyle.js @@ -0,0 +1,108 @@ +import { Fill, Icon, Stroke, Style } from 'ol/style'; +import { transform } from 'ol/proj'; +import { Point } from 'ol/geom'; +import AssetModules from '../shared/AssetModules'; + +function createPolygonStyle(fillColor, strokeColor) { + return new Style({ + stroke: new Stroke({ + color: strokeColor, + width: 3, + }), + fill: new Fill({ + color: fillColor, + }), + }); +} +function createIconStyle(iconSrc) { + return new Style({ + image: new Icon({ + anchor: [0.5, 1], + scale: 0.8, + anchorXUnits: 'fraction', + anchorYUnits: 'pixels', + src: iconSrc, + }), + geometry: function (feature) { + const convertedCenter = transform(feature.values_.centroid, 'EPSG:4326', 'EPSG:3857'); + return new Point(convertedCenter); + }, + }); +} + +const strokeColor = 'rgb(0,0,0,0.5)'; + +const getTaskStatusStyle = (feature, mapTheme) => { + let id = feature.getId().toString().replace('_', ','); + const status = id.split(',')[1]; + const lockedPolygonStyle = createPolygonStyle(mapTheme.palette.mapFeatureColors.locked_for_mapping_rgb, strokeColor); + const lockedValidationStyle = createPolygonStyle( + mapTheme.palette.mapFeatureColors.locked_for_validation_rgb, + strokeColor, + ); + const iconStyle = createIconStyle(AssetModules.LockPng); + const redIconStyle = createIconStyle(AssetModules.RedLockPng); + + const geojsonStyles = { + READY: new Style({ + stroke: new Stroke({ + color: strokeColor, + width: 3, + }), + fill: new Fill({ + color: mapTheme.palette.mapFeatureColors.ready_rgb, + }), + }), + LOCKED_FOR_MAPPING: [lockedPolygonStyle, iconStyle], + MAPPED: new Style({ + stroke: new Stroke({ + color: strokeColor, + width: 3, + }), + fill: new Fill({ + color: mapTheme.palette.mapFeatureColors.mapped_rgb, + }), + }), + LOCKED_FOR_VALIDATION: [lockedValidationStyle, redIconStyle], + + VALIDATED: new Style({ + stroke: new Stroke({ + color: strokeColor, + width: 3, + }), + fill: new Fill({ + color: mapTheme.palette.mapFeatureColors.validated_rgb, + }), + }), + INVALIDATED: new Style({ + stroke: new Stroke({ + color: strokeColor, + width: 3, + }), + fill: new Fill({ + color: mapTheme.palette.mapFeatureColors.invalidated_rgb, + }), + }), + BAD: new Style({ + stroke: new Stroke({ + color: strokeColor, + width: 3, + }), + fill: new Fill({ + color: mapTheme.palette.mapFeatureColors.bad_rgb, + }), + }), + SPLIT: new Style({ + stroke: new Stroke({ + color: strokeColor, + width: 3, + }), + fill: new Fill({ + color: mapTheme.palette.mapFeatureColors.split_rgb, + }), + }), + }; + return geojsonStyles[status]; +}; + +export default getTaskStatusStyle; diff --git a/src/frontend/src/views/NewProjectDetails.jsx b/src/frontend/src/views/NewProjectDetails.jsx new file mode 100644 index 0000000000..4014de3565 --- /dev/null +++ b/src/frontend/src/views/NewProjectDetails.jsx @@ -0,0 +1,426 @@ +import React, { useEffect, useState } from 'react'; +import '../../node_modules/ol/ol.css'; +import '../styles/home.scss'; +import WindowDimension from '../hooks/WindowDimension'; +import MapDescriptionComponents from '../components/MapDescriptionComponents'; +import ActivitiesPanel from '../components/ActivitiesPanel'; +import environment from '../environment'; +import { ProjectById } from '../api/Project'; +import { ProjectActions } from '../store/slices/ProjectSlice'; +import CustomizedSnackbar from '../utilities/CustomizedSnackbar'; +import OnScroll from '../hooks/OnScroll'; +import { HomeActions } from '../store/slices/HomeSlice'; +import CoreModules from '../shared/CoreModules'; +import AssetModules from '../shared/AssetModules'; +import FmtmLogo from '../assets/images/hotLog.png'; +import GenerateMbTiles from '../components/GenerateMbTiles'; +import { ProjectBuildingGeojsonService } from '../api/SubmissionService'; +import TaskSectionPopup from '../components/ProjectDetails/TaskSectionPopup'; +import DialogTaskActions from '../components/DialogTaskActions'; +import QrcodeComponent from '../components/QrcodeComponent'; +import MobileFooter from '../components/ProjectDetails/MobileFooter'; +import MobileActivitiesContents from '../components/ProjectDetails/MobileActivitiesContents'; +import BottomSheet from '../components/common/BottomSheet'; +import MobileProjectInfoContent from '../components/ProjectDetails/MobileProjectInfoContent'; +import { useNavigate } from 'react-router-dom'; +import ProjectOptions from '../components/ProjectDetails/ProjectOptions'; +import { MapContainer as MapComponent, useOLMap } from '../components/MapComponent/OpenLayersComponent'; +import LayerSwitcherControl from '../components/MapComponent/OpenLayersComponent/LayerSwitcher/index'; +import MapControlComponent from '../components/ProjectDetails/MapControlComponent'; +import { VectorLayer } from '../components/MapComponent/OpenLayersComponent/Layers'; +import { geojsonObjectModel } from '../constants/geojsonObjectModal'; +import { basicGeojsonTemplate } from '../utilities/mapUtils'; +import getTaskStatusStyle from '../utilfunctions/getTaskStatusStyle'; +import { defaultStyles } from '../components/MapComponent/OpenLayersComponent/helpers/styleUtils'; +import MapLegends from '../components/MapLegends'; +import Accordion from '../components/common/Accordion'; + +const Home = () => { + const dispatch = CoreModules.useAppDispatch(); + const params = CoreModules.useParams(); + const navigate = useNavigate(); + const { windowSize, type } = WindowDimension(); + + const [taskId, setTaskId] = useState(); + const [mainView, setView] = useState(); + const [featuresLayer, setFeaturesLayer] = useState(); + const [toggleGenerateModal, setToggleGenerateModal] = useState(false); + const [taskBuildingGeojson, setTaskBuildingGeojson] = useState(null); + const [initialFeaturesLayer, setInitialFeaturesLayer] = useState(null); + + const encodedId = params.id; + const decodedId = environment.decode(encodedId); + const defaultTheme = CoreModules.useAppSelector((state) => state.theme.hotTheme); + const state = CoreModules.useAppSelector((state) => state.project); + const projectInfo = CoreModules.useAppSelector((state) => state.home.selectedProject); + const stateSnackBar = CoreModules.useAppSelector((state) => state.home.snackbar); + const projectBuildingGeojson = CoreModules.useAppSelector((state) => state.project.projectBuildingGeojson); + const mobileFooterSelection = CoreModules.useAppSelector((state) => state.project.mobileFooterSelection); + const mapTheme = CoreModules.useAppSelector((state) => state.theme.hotTheme); + + //snackbar handle close funtion + const handleClose = (event, reason) => { + if (reason === 'clickaway') { + return; + } + dispatch( + HomeActions.SetSnackBar({ + open: false, + message: stateSnackBar.message, + variant: stateSnackBar.variant, + duration: 0, + }), + ); + }; + //Fetch project for the first time + useEffect(() => { + dispatch(ProjectActions.SetNewProjectTrigger()); + if (state.projectTaskBoundries.findIndex((project) => project.id == environment.decode(encodedId)) == -1) { + dispatch(ProjectActions.SetProjectTaskBoundries([])); + + dispatch( + ProjectById( + `${import.meta.env.VITE_API_URL}/projects/${environment.decode(encodedId)}`, + state.projectTaskBoundries, + environment.decode(encodedId), + ), + state.projectTaskBoundries, + ); + // dispatch(ProjectBuildingGeojsonService(`${import.meta.env.VITE_API_URL}/projects/${environment.decode(encodedId)}/features`)) + } else { + dispatch(ProjectActions.SetProjectTaskBoundries([])); + dispatch( + ProjectById( + `${import.meta.env.VITE_API_URL}/projects/${environment.decode(encodedId)}`, + state.projectTaskBoundries, + environment.decode(encodedId), + ), + state.projectTaskBoundries, + ); + } + if (Object.keys(state.projectInfo)?.length == 0) { + dispatch(ProjectActions.SetProjectInfo(projectInfo)); + } else { + if (state.projectInfo.id != environment.decode(encodedId)) { + dispatch(ProjectActions.SetProjectInfo(projectInfo)); + } + } + return () => { + dispatch(ProjectActions.SetProjectBuildingGeojson(null)); + }; + }, [params.id]); + + const { mapRef, map } = useOLMap({ + center: [0, 0], + zoom: 4, + // maxZoom: 17, + }); + + const { y } = OnScroll(map, windowSize.width); + + useEffect(() => { + if (!map) return; + + const features = state.projectTaskBoundries[0]?.taskBoundries?.map((feature) => ({ + type: 'Feature', + geometry: { ...feature.outline_geojson.geometry }, + properties: { + ...feature.outline_geojson.properties, + centroid: feature.bbox, + }, + id: `${feature.project_task_name}_${feature.task_status_str}`, + })); + const taskBuildingGeojsonFeatureCollection = { + ...geojsonObjectModel, + features: features, + }; + setInitialFeaturesLayer(taskBuildingGeojsonFeatureCollection); + }, [state.projectTaskBoundries[0]?.taskBoundries?.length]); + + useEffect(() => { + if (!map) return; + if (!projectBuildingGeojson) return; + + const taskBuildingGeojsonFeatureCollection = { + ...basicGeojsonTemplate, + features: [ + ...projectBuildingGeojson?.map((feature) => ({ + ...feature.geometry, + id: feature.id, + })), + ], + }; + + setTaskBuildingGeojson(taskBuildingGeojsonFeatureCollection); + }, [map, projectBuildingGeojson]); + + // TasksLayer(map, mainView, featuresLayer); + const projectClickOnMap = (properties, feature) => { + setFeaturesLayer(feature, 'feature'); + let extent = properties.geometry.getExtent(); + dispatch( + ProjectBuildingGeojsonService( + `${import.meta.env.VITE_API_URL}/projects/${decodedId}/features?task_id=${properties.uid}`, + ), + ); + mapRef.current?.scrollIntoView({ + block: 'center', + behavior: 'smooth', + }); + setTaskId(properties.uid); + dispatch(ProjectActions.ToggleTaskModalStatus(true)); + if (windowSize.width < 768) { + map.getView().fit(extent, { + padding: [10, 20, 300, 20], + }); + } else { + map.getView().fit(extent, { + padding: [20, 350, 50, 10], + }); + } + }; + + const buildingStyle = { + ...defaultStyles, + lineColor: '#FF0000', + fillOpacity: '0', + }; + + return ( +
+ {/* Customized Modal For Generate Tiles */} +
+ + + {/* Home snackbar */} + +
+ + {/* Top project details heading medium dimension*/} + {windowSize.width >= 640 && ( +
+ + + } + > + + + {state.projectInfo.title} + + + + + {`#${state.projectInfo.id}`} + + + + + + {state.projectInfo.priority_str} + + + + + {/* project Details Title */} + + + + {state.projectInfo.title} + + + + + {`#${state.projectInfo.id}`} + + + + + + {state.projectInfo.priority_str} + + + +
+ )} + + {/* Center description and map */} + + {windowSize.width >= 640 && ( +
+ + +
+ )} + + {/* */} + {params?.id && ( +
+ + + + {initialFeaturesLayer && initialFeaturesLayer?.features?.length > 0 && ( + getTaskStatusStyle(feature, mapTheme)} + /> + )} + {taskBuildingGeojson && taskBuildingGeojson?.features?.length > 0 && ( + + )} +
+ } + header={ +
+ +

Legend

+
+ } + onToggle={() => {}} + className="fmtm-py-0 !fmtm-pb-0 fmtm-rounded-lg hover:fmtm-bg-gray-50" + collapsed={true} + /> +
+ +
+
navigate('/')} + > + +
+ {mobileFooterSelection === 'projectInfo' && ( + } + onClose={() => dispatch(ProjectActions.SetMobileFooterSelection('explore'))} + /> + )} + {mobileFooterSelection === 'activities' && ( + } + onClose={() => dispatch(ProjectActions.SetMobileFooterSelection('explore'))} + /> + )} + {mobileFooterSelection === 'explore' && ( +
+ Hot Fmtm Logo +
+ )} + {mobileFooterSelection === 'mapLegend' && ( + + +
+ } + onClose={() => dispatch(ProjectActions.SetMobileFooterSelection('explore'))} + /> + )} + {mobileFooterSelection === 'others' && ( + + +
+ } + onClose={() => dispatch(ProjectActions.SetMobileFooterSelection('explore'))} + /> + )} + + +
+ )} + + + {windowSize.width >= 640 && ( +
+ + + +
+ )} + {featuresLayer != undefined && ( + + + +
+ } + /> + )} +
+ ); +}; + +export default Home;