frontend: visualize markers on map
This commit is contained in:
parent
13e493f5d1
commit
687e79b3c4
|
@ -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<HostOfferLookupTableProps>
|
||||
|
||||
|
@ -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 <>
|
||||
<Box sx={{
|
||||
|
@ -25,16 +40,16 @@ const HostOfferLookupWrapper = (props: HostOfferLookupWrapperProps) => {
|
|||
<div style={{minHeight: '2em', display: 'flex'}}>
|
||||
{ (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.') }
|
||||
<Login/>
|
||||
</div>
|
||||
{queryResult_ro.data && <div
|
||||
{data_ro && <div
|
||||
style={{flex: '1 1', height: '100%'}}>
|
||||
<HostOfferLookupTable
|
||||
{...props}
|
||||
data_ro={queryResult_ro.data.get_offers}
|
||||
data_rw={queryResult_rw.data?.get_rw}
|
||||
data_ro={data_ro.get_offers}
|
||||
data_rw={data_rw?.get_rw}
|
||||
refetch_rw={queryResult_rw.refetch}
|
||||
/>
|
||||
</div>}
|
||||
|
|
|
@ -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<number>( 8 )
|
||||
const [position, setPosition] = useState<L.LatLngExpression>( {
|
||||
lat: 51.0833,
|
||||
lng: 13.73126,
|
||||
} )
|
||||
const leafletStore = useLeafletStore()
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -80,6 +85,19 @@ const LeafletMap = ({onBoundsChange}: LeafletMapProps) => {
|
|||
maxNativeZoom={20}
|
||||
/>
|
||||
</LayersControl.BaseLayer>
|
||||
|
||||
|
||||
{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.
|
||||
**/
|
||||
<Circle key={m.id}
|
||||
center={[m.lat, m.lng]}
|
||||
radius={m.radius}
|
||||
pathOptions={{color: 'grey'}}>
|
||||
<Popup><a href={`#${m.id}`}>{ m.content }</a></Popup>
|
||||
</Circle>
|
||||
)}
|
||||
</LayersControl>
|
||||
</MapContainer>
|
||||
</>)
|
||||
|
|
|
@ -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<LeafletState>(set => ({
|
||||
markers: [],
|
||||
setMarkers: (markers: Marker[]) => set( _orig => ({markers}) )
|
||||
}))
|
Loading…
Reference in New Issue