From 687e79b3c444d968a4c95acdd5cda165367c6fb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20L=C3=B6tzsch?= Date: Mon, 14 Mar 2022 19:22:17 +0100 Subject: [PATCH] frontend: visualize markers on map --- .../components/ngo/HostOfferLookupWrapper.tsx | 29 ++++++++++++++----- frontend/search/components/ngo/LeafletMap.tsx | 26 ++++++++++++++--- .../search/components/ngo/LeafletStore.tsx | 19 ++++++++++++ 3 files changed, 63 insertions(+), 11 deletions(-) create mode 100644 frontend/search/components/ngo/LeafletStore.tsx diff --git a/frontend/search/components/ngo/HostOfferLookupWrapper.tsx b/frontend/search/components/ngo/HostOfferLookupWrapper.tsx index 4b06b33..ade3e8a 100644 --- a/frontend/search/components/ngo/HostOfferLookupWrapper.tsx +++ b/frontend/search/components/ngo/HostOfferLookupWrapper.tsx @@ -1,9 +1,11 @@ -import React from 'react' +import React, { useEffect } from 'react' import { useGetOffersQuery, useGetRwQuery } from "../../codegen/generates" import HostOfferLookupTable, {HostOfferLookupTableProps} from "./HostOfferLookupTable" import { Box } from "@mui/material" import { useTranslation } from 'react-i18next' import { Login, useAuthStore } from '../Login' +import { useLeafletStore } from './LeafletStore' +import { filterUndefOrNull } from '../util/notEmpty' type HostOfferLookupWrapperProps = Partial @@ -13,8 +15,21 @@ const HostOfferLookupWrapper = (props: HostOfferLookupWrapperProps) => { const staleTimeMinutes_ro = 5 const staleTimeMinutes_rw = 1 - const queryResult_ro = useGetOffersQuery({auth}, {staleTime: staleTimeMinutes_ro * 60 * 1000}) - const queryResult_rw = useGetRwQuery({auth}, {staleTime: staleTimeMinutes_rw * 60 * 1000}) + const queryResult_ro = useGetOffersQuery({auth}, {enabled: !!auth.jwt, staleTime: staleTimeMinutes_ro * 60 * 1000}) + const queryResult_rw = useGetRwQuery({auth}, {enabled: !!auth.jwt, staleTime: staleTimeMinutes_rw * 60 * 1000}) + const {data: data_ro} = queryResult_ro + const {data: data_rw} = queryResult_rw + + const leafletStore = useLeafletStore() + useEffect(() => { + const markers = data_ro?.get_offers?.map(row => (row.id && row.place_lon && row.place_lat + && ({id: row.id, + lat: row.place_lat, + lng: row.place_lon, + radius: 1000, // TODO + content: 'TODO'}) || undefined)) + leafletStore.setMarkers(filterUndefOrNull(markers)) + }, [data_ro]) return <> {
{ (queryResult_ro.isFetching || queryResult_rw.isFetching) && t('loading…') } { (queryResult_ro.error || queryResult_rw.error) && t('An error occurred while trying to get data from the backend.') } - { (queryResult_ro.data && !queryResult_ro.data.get_offers || queryResult_rw.data && !queryResult_rw.data.get_rw) + { (data_ro && !data_ro.get_offers || data_rw && !data_rw.get_rw) && t('Seems like you have no permissions. Please try to login again.') }
- {queryResult_ro.data &&
} diff --git a/frontend/search/components/ngo/LeafletMap.tsx b/frontend/search/components/ngo/LeafletMap.tsx index e5b389f..8ee9e93 100644 --- a/frontend/search/components/ngo/LeafletMap.tsx +++ b/frontend/search/components/ngo/LeafletMap.tsx @@ -5,15 +5,18 @@ import 'leaflet/dist/leaflet.css' import { LayersControl, MapContainer, - Marker, - Polygon, - Polyline, + //Marker, + //Polygon, + //Polyline, Popup, + Circle, TileLayer, useMap, useMapEvent } from '@monsonjeremy/react-leaflet' import * as L from 'leaflet' +import { useLeafletStore } from './LeafletStore' + type LeafletMapProps = {onBoundsChange?: (bounds: L.LatLngBounds) => void} const BoundsChangeListener = ({onBoundsChange}: {onBoundsChange?: (bounds: L.LatLngBounds) => void}) => { @@ -26,7 +29,7 @@ const BoundsChangeListener = ({onBoundsChange}: {onBoundsChange?: (bounds: L.Lat ) }, [map, onBoundsChange], - ); + ) useEffect(() => { updateBounds() @@ -36,12 +39,14 @@ const BoundsChangeListener = ({onBoundsChange}: {onBoundsChange?: (bounds: L.Lat useMapEvent('load', (e) => updateBounds()) return null } + const LeafletMap = ({onBoundsChange}: LeafletMapProps) => { const [zoom, setZoom] = useState( 8 ) const [position, setPosition] = useState( { lat: 51.0833, lng: 13.73126, } ) + const leafletStore = useLeafletStore() return ( <> @@ -80,6 +85,19 @@ const LeafletMap = ({onBoundsChange}: LeafletMapProps) => { maxNativeZoom={20} /> + + + {leafletStore.markers.map(m => + /** TODO: Maybe a clustered marker would be helpfull, but we loose the possibility of showing the radius (display accuracy of the coordinate). + * Probably the best solution is showing Circle and clustered marker. + **/ + + { m.content } + + )} ) diff --git a/frontend/search/components/ngo/LeafletStore.tsx b/frontend/search/components/ngo/LeafletStore.tsx new file mode 100644 index 0000000..46a2b26 --- /dev/null +++ b/frontend/search/components/ngo/LeafletStore.tsx @@ -0,0 +1,19 @@ +import create from 'zustand' + +export interface Marker + {id: string, + lat: number, + lng: number, + radius: number, // in meters + content: string // TODO react-child? + } + +export interface LeafletState { + markers: Marker[] + setMarkers: (markers: Marker[]) => void +} + +export const useLeafletStore = create(set => ({ + markers: [], + setMarkers: (markers: Marker[]) => set( _orig => ({markers}) ) +}))