-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Ebubeker
committed
Nov 27, 2023
1 parent
5123330
commit 3f3beef
Showing
59 changed files
with
2,152 additions
and
1,955 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,123 +1,138 @@ | ||
"use client"; | ||
|
||
import type { XYZ_Layer } from "@/types/map/layer"; | ||
import { MAPBOX_TOKEN } from "@/lib/constants"; | ||
import { Box, useTheme } from "@mui/material"; | ||
import { Box, debounce, useTheme } from "@mui/material"; | ||
import "mapbox-gl/dist/mapbox-gl.css"; | ||
import React, { useCallback, useState } from "react"; | ||
import Map, { MapProvider, Layer, Source } from "react-map-gl"; | ||
import React, { useMemo } from "react"; | ||
import type { ViewStateChangeEvent } from "react-map-gl"; | ||
import Map, { MapProvider } from "react-map-gl"; | ||
import Layers from "@/components/map/Layers"; | ||
import Markers from "@/components/map/Markers"; | ||
import MobileDrawer from "@/components/map/panels/MobileDrawer"; | ||
|
||
import { useSelector, useDispatch } from "react-redux"; | ||
import { useSelector } from "react-redux"; | ||
import type { IStore } from "@/types/store"; | ||
import { selectMapLayer } from "@/lib/store/styling/selectors"; | ||
import ProjectNavigation from "@/components/map/panels/ProjectNavigation"; | ||
import Header from "@/components/header/Header"; | ||
import { useProject } from "@/lib/api/projects"; | ||
import { useFilterExpressions } from "@/hooks/map/FilteringHooks"; | ||
import { setMapLoading } from "@/lib/store/map/slice"; | ||
import { | ||
updateProjectInitialViewState, | ||
useProject, | ||
useProjectInitialViewState, | ||
useProjectLayers, | ||
} from "@/lib/api/projects"; | ||
import { LoadingPage } from "@/components/common/LoadingPage"; | ||
|
||
const sidebarWidth = 48; | ||
const sidebarWidth = 52; | ||
const toolbarHeight = 52; | ||
|
||
export default function MapPage({ params: { projectId } }) { | ||
const { basemaps, activeBasemapIndex, initialViewState } = useSelector( | ||
const theme = useTheme(); | ||
const { basemaps, activeBasemapIndex } = useSelector( | ||
(state: IStore) => state.styling, | ||
); | ||
const { project } = useProject(projectId); | ||
const mapLayer = useSelector(selectMapLayer); | ||
const dispatch = useDispatch(); | ||
const { layerToBeFiltered } = useSelector( | ||
(state: IStore) => state.mapFilters, | ||
); | ||
|
||
const { getFilterQueries } = useFilterExpressions(projectId); | ||
|
||
const { data: filters } = getFilterQueries(layerToBeFiltered); | ||
const { | ||
project, | ||
isLoading: isProjectLoading, | ||
isError: projectError, | ||
} = useProject(projectId); | ||
const { | ||
initialView, | ||
isLoading: isInitialViewLoading, | ||
isError: projectInitialViewError, | ||
} = useProjectInitialViewState(projectId); | ||
|
||
const [layers, setLayers] = useState<XYZ_Layer[] | []>([ | ||
{ | ||
id: "layer1", | ||
sourceUrl: | ||
"https://geoapi.goat.dev.plan4better.de/collections/user_data.84ca9acb3f30491d82ce938334164496/tiles/{z}/{x}/{y}", | ||
color: "#FF0000", | ||
}, | ||
]); | ||
const { isLoading: areProjectLayersLoading, isError: projectLayersError } = | ||
useProjectLayers(projectId); | ||
|
||
const theme = useTheme(); | ||
const isLoading = useMemo( | ||
() => isProjectLoading || isInitialViewLoading || areProjectLayersLoading, | ||
[isProjectLoading, isInitialViewLoading, areProjectLayersLoading], | ||
); | ||
|
||
const addLayer = useCallback( | ||
(newLayer: XYZ_Layer[]) => { | ||
dispatch(setMapLoading(false)); | ||
setLayers(newLayer); | ||
}, | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
[filters], | ||
const hasError = useMemo( | ||
() => projectError || projectInitialViewError || projectLayersError, | ||
[projectError, projectInitialViewError, projectLayersError], | ||
); | ||
const updateViewState = useMemo( | ||
() => | ||
debounce((e: ViewStateChangeEvent) => { | ||
updateProjectInitialViewState(projectId, { | ||
zoom: e.viewState.zoom, | ||
latitude: e.viewState.latitude, | ||
longitude: e.viewState.longitude, | ||
pitch: e.viewState.pitch, | ||
bearing: e.viewState.bearing, | ||
min_zoom: initialView?.min_zoom ?? 0, | ||
max_zoom: initialView?.max_zoom ?? 24, | ||
}); | ||
}, 2000), | ||
[initialView?.max_zoom, initialView?.min_zoom, projectId], | ||
); | ||
|
||
return ( | ||
<MapProvider> | ||
<Header | ||
title={`Project ${project?.name ?? ""}`} | ||
showHambugerMenu={false} | ||
tags={project?.tags} | ||
lastSaved={project?.updated_at} | ||
/> | ||
<Box | ||
sx={{ | ||
display: "flex", | ||
height: "100vh", | ||
width: `calc(100% - ${2 * sidebarWidth}px)`, | ||
marginLeft: `${sidebarWidth}px`, | ||
[theme.breakpoints.down("sm")]: { | ||
marginLeft: "0", | ||
width: `100%`, | ||
}, | ||
}} | ||
> | ||
<Box> | ||
<ProjectNavigation projectId={projectId} /> | ||
</Box> | ||
<Box | ||
sx={{ | ||
width: "100%", | ||
".mapboxgl-ctrl .mapboxgl-ctrl-logo": { | ||
display: "none", | ||
}, | ||
height: `calc(100% - ${toolbarHeight}px)`, | ||
}} | ||
> | ||
<Map | ||
id="map" | ||
style={{ width: "100%", height: "100%" }} | ||
initialViewState={initialViewState} | ||
mapStyle={basemaps[activeBasemapIndex[0]].url} | ||
attributionControl={false} | ||
mapboxAccessToken={MAPBOX_TOKEN} | ||
<> | ||
{isLoading && <LoadingPage />} | ||
{!isLoading && !hasError && ( | ||
<MapProvider> | ||
<Header | ||
title={`Project ${project?.name ?? ""}`} | ||
showHambugerMenu={false} | ||
tags={project?.tags} | ||
lastSaved={project?.updated_at} | ||
/> | ||
<Box | ||
sx={{ | ||
display: "flex", | ||
height: "100vh", | ||
width: `calc(100% - ${2 * sidebarWidth}px)`, | ||
marginLeft: `${sidebarWidth}px`, | ||
[theme.breakpoints.down("sm")]: { | ||
marginLeft: "0", | ||
width: `100%`, | ||
}, | ||
}} | ||
> | ||
{mapLayer ? ( | ||
<Source | ||
id={mapLayer.id} | ||
type="vector" | ||
url={mapLayer.sources.composite.url} | ||
<Box> | ||
<ProjectNavigation projectId={projectId} /> | ||
</Box> | ||
<Box | ||
sx={{ | ||
width: "100%", | ||
".mapboxgl-ctrl .mapboxgl-ctrl-logo": { | ||
display: "none", | ||
}, | ||
height: `calc(100% - ${toolbarHeight}px)`, | ||
}} | ||
> | ||
<Map | ||
id="map" | ||
style={{ width: "100%", height: "100%" }} | ||
onMoveEnd={updateViewState} | ||
initialViewState={{ | ||
zoom: initialView?.zoom ?? 3, | ||
latitude: initialView?.latitude ?? 48.13, | ||
longitude: initialView?.longitude ?? 11.57, | ||
pitch: initialView?.pitch ?? 0, | ||
bearing: initialView?.bearing ?? 0, | ||
fitBoundsOptions: { | ||
minZoom: initialView?.min_zoom ?? 0, | ||
maxZoom: initialView?.max_zoom ?? 24, | ||
}, | ||
}} | ||
mapStyle={basemaps[activeBasemapIndex[0]].url} | ||
attributionControl={false} | ||
mapboxAccessToken={MAPBOX_TOKEN} | ||
> | ||
<Layer {...mapLayer} source-layer={mapLayer["source-layer"]} /> | ||
</Source> | ||
) : null} | ||
{/* todo check */} | ||
<Layers | ||
layers={layers} | ||
filters={filters} | ||
addLayer={addLayer} | ||
projectId={projectId} | ||
/> | ||
</Map> | ||
</Box> | ||
</Box> | ||
<Box> | ||
<MobileDrawer /> | ||
</Box> | ||
</MapProvider> | ||
<Layers projectId={projectId} /> | ||
<Markers /> | ||
</Map> | ||
</Box> | ||
</Box> | ||
<Box> | ||
<MobileDrawer /> | ||
</Box> | ||
</MapProvider> | ||
)} | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { Box, useTheme } from "@mui/material"; | ||
import { Loading } from "@p4b/ui/components/Loading"; | ||
|
||
export function LoadingPage() { | ||
const theme = useTheme(); | ||
return ( | ||
<Box | ||
sx={{ | ||
display: "flex", | ||
justifyContent: "center", | ||
alignItems: "center", | ||
height: "100vh", | ||
width: "100vw", | ||
backgroundColor: theme.palette.background.default, | ||
}} | ||
> | ||
<Loading /> | ||
</Box> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.