2020-11-06 15:09:35 +00:00
|
|
|
import React, { useEffect } from "react";
|
2020-11-30 07:23:05 +00:00
|
|
|
import { withGoogleMap, GoogleMap, Marker } from "react-google-maps";
|
2020-04-15 11:42:11 +00:00
|
|
|
import SearchBox from "react-google-maps/lib/components/places/SearchBox";
|
|
|
|
|
import { MarkerProps } from "widgets/MapWidget";
|
2020-05-20 11:57:02 +00:00
|
|
|
import PickMyLocation from "./PickMyLocation";
|
2020-05-22 06:29:26 +00:00
|
|
|
import styled from "styled-components";
|
2020-11-30 07:23:05 +00:00
|
|
|
import { useScript, ScriptStatus, AddScriptTo } from "utils/hooks/useScript";
|
2020-04-15 11:42:11 +00:00
|
|
|
|
|
|
|
|
interface MapComponentProps {
|
2020-07-10 07:35:27 +00:00
|
|
|
apiKey: string;
|
2020-04-15 11:42:11 +00:00
|
|
|
widgetId: string;
|
|
|
|
|
isDisabled?: boolean;
|
|
|
|
|
isVisible?: boolean;
|
|
|
|
|
enableSearch: boolean;
|
|
|
|
|
zoomLevel: number;
|
|
|
|
|
enablePickLocation: boolean;
|
|
|
|
|
allowZoom: boolean;
|
|
|
|
|
center: {
|
|
|
|
|
lat: number;
|
2020-05-07 10:51:37 +00:00
|
|
|
long: number;
|
2020-04-15 11:42:11 +00:00
|
|
|
};
|
|
|
|
|
markers?: Array<MarkerProps>;
|
2020-04-29 10:29:02 +00:00
|
|
|
selectedMarker?: {
|
|
|
|
|
lat: number;
|
|
|
|
|
long: number;
|
|
|
|
|
title?: string;
|
|
|
|
|
};
|
2020-04-15 11:42:11 +00:00
|
|
|
enableCreateMarker: boolean;
|
2020-05-07 10:51:37 +00:00
|
|
|
updateCenter: (lat: number, long: number) => void;
|
|
|
|
|
updateMarker: (lat: number, long: number, index: number) => void;
|
|
|
|
|
saveMarker: (lat: number, long: number) => void;
|
|
|
|
|
selectMarker: (lat: number, long: number, title: string) => void;
|
2020-11-24 08:43:45 +00:00
|
|
|
enableDrag: (e: any) => void;
|
2020-11-06 15:09:35 +00:00
|
|
|
unselectMarker: () => void;
|
2020-04-15 11:42:11 +00:00
|
|
|
}
|
|
|
|
|
|
2020-05-07 10:51:37 +00:00
|
|
|
const MapWrapper = styled.div`
|
|
|
|
|
position: relative;
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const MapContainerWrapper = styled.div`
|
|
|
|
|
width: 100%;
|
2020-05-08 04:02:28 +00:00
|
|
|
height: 100%;
|
2020-05-07 10:51:37 +00:00
|
|
|
`;
|
|
|
|
|
|
2020-04-15 11:42:11 +00:00
|
|
|
const StyledInput = styled.input`
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
border: 1px solid transparent;
|
|
|
|
|
width: 240px;
|
|
|
|
|
height: 32px;
|
|
|
|
|
margin-top: 27px;
|
|
|
|
|
padding: 0 12px;
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
outline: none;
|
|
|
|
|
text-overflow: ellipses;
|
|
|
|
|
`;
|
|
|
|
|
type PickMyLocationProps = {
|
|
|
|
|
allowZoom: boolean;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const PickMyLocationWrapper = styled.div<PickMyLocationProps>`
|
|
|
|
|
position: absolute;
|
|
|
|
|
bottom: ${props => (props.allowZoom ? 110 : 20)}px;
|
2020-05-20 11:57:02 +00:00
|
|
|
right: -90px;
|
2020-04-15 11:42:11 +00:00
|
|
|
width: 140px;
|
|
|
|
|
`;
|
|
|
|
|
|
2020-11-30 07:23:05 +00:00
|
|
|
const MyMapComponent = withGoogleMap((props: any) => {
|
|
|
|
|
const [mapCenter, setMapCenter] = React.useState<
|
|
|
|
|
| {
|
|
|
|
|
lat: number;
|
|
|
|
|
lng: number;
|
|
|
|
|
title?: string;
|
|
|
|
|
description?: string;
|
2020-11-06 15:09:35 +00:00
|
|
|
}
|
2020-11-30 07:23:05 +00:00
|
|
|
| undefined
|
|
|
|
|
>({
|
|
|
|
|
...props.center,
|
|
|
|
|
lng: props.center.long,
|
|
|
|
|
});
|
|
|
|
|
const searchBox = React.createRef<SearchBox>();
|
|
|
|
|
const onPlacesChanged = () => {
|
|
|
|
|
const node: any = searchBox.current;
|
|
|
|
|
if (node) {
|
|
|
|
|
const places: any = node.getPlaces();
|
|
|
|
|
if (
|
|
|
|
|
places &&
|
|
|
|
|
places.length &&
|
|
|
|
|
places[0].geometry &&
|
|
|
|
|
places[0].geometry.location
|
|
|
|
|
) {
|
|
|
|
|
const location = places[0].geometry.location;
|
|
|
|
|
const lat = location.lat();
|
|
|
|
|
const long = location.lng();
|
|
|
|
|
setMapCenter({ lat, lng: long });
|
|
|
|
|
props.updateCenter(lat, long);
|
|
|
|
|
props.unselectMarker();
|
2020-11-06 15:09:35 +00:00
|
|
|
}
|
2020-11-30 07:23:05 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (!props.selectedMarker) {
|
|
|
|
|
setMapCenter({
|
|
|
|
|
...props.center,
|
|
|
|
|
lng: props.center.long,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}, [props.center, props.selectedMarker]);
|
|
|
|
|
return (
|
|
|
|
|
<GoogleMap
|
|
|
|
|
options={{
|
|
|
|
|
zoomControl: props.allowZoom,
|
|
|
|
|
fullscreenControl: false,
|
|
|
|
|
mapTypeControl: false,
|
|
|
|
|
scrollwheel: false,
|
|
|
|
|
rotateControl: false,
|
|
|
|
|
streetViewControl: false,
|
|
|
|
|
}}
|
|
|
|
|
zoom={props.zoom}
|
|
|
|
|
center={mapCenter}
|
|
|
|
|
onClick={e => {
|
|
|
|
|
if (props.enableCreateMarker) {
|
|
|
|
|
props.saveMarker(e.latLng.lat(), e.latLng.lng());
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{props.enableSearch && (
|
|
|
|
|
<SearchBox
|
|
|
|
|
controlPosition={2}
|
|
|
|
|
onPlacesChanged={onPlacesChanged}
|
|
|
|
|
ref={searchBox}
|
|
|
|
|
>
|
|
|
|
|
<StyledInput type="text" placeholder="Enter location to search" />
|
|
|
|
|
</SearchBox>
|
|
|
|
|
)}
|
|
|
|
|
{props.markers.map((marker: any, index: number) => (
|
|
|
|
|
<Marker
|
|
|
|
|
key={index}
|
|
|
|
|
title={marker.title}
|
|
|
|
|
position={{ lat: marker.lat, lng: marker.long }}
|
|
|
|
|
clickable
|
|
|
|
|
draggable={
|
|
|
|
|
props.selectedMarker &&
|
|
|
|
|
props.selectedMarker.lat === marker.lat &&
|
|
|
|
|
props.selectedMarker.long === marker.long
|
2020-04-29 10:29:02 +00:00
|
|
|
}
|
2020-11-30 07:23:05 +00:00
|
|
|
onClick={e => {
|
|
|
|
|
setMapCenter({
|
|
|
|
|
...marker,
|
|
|
|
|
lng: marker.long,
|
|
|
|
|
});
|
|
|
|
|
props.selectMarker(marker.lat, marker.long, marker.title);
|
|
|
|
|
}}
|
|
|
|
|
onDragEnd={de => {
|
|
|
|
|
props.updateMarker(de.latLng.lat(), de.latLng.lng(), index);
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
))}
|
|
|
|
|
{props.enablePickLocation && (
|
|
|
|
|
<PickMyLocationWrapper
|
|
|
|
|
title="Pick My Location"
|
|
|
|
|
allowZoom={props.allowZoom}
|
|
|
|
|
>
|
|
|
|
|
<PickMyLocation updateCenter={props.updateCenter} />
|
|
|
|
|
</PickMyLocationWrapper>
|
|
|
|
|
)}
|
|
|
|
|
</GoogleMap>
|
|
|
|
|
);
|
|
|
|
|
});
|
2020-04-15 11:42:11 +00:00
|
|
|
|
2020-11-25 16:02:54 +00:00
|
|
|
const MapComponent = (props: MapComponentProps) => {
|
|
|
|
|
const zoom = Math.floor(props.zoomLevel / 5);
|
2020-11-30 07:23:05 +00:00
|
|
|
const status = useScript(
|
|
|
|
|
`https://maps.googleapis.com/maps/api/js?key=${props.apiKey}&v=3.exp&libraries=geometry,drawing,places`,
|
|
|
|
|
AddScriptTo.HEAD,
|
|
|
|
|
);
|
2020-11-25 16:02:54 +00:00
|
|
|
return (
|
|
|
|
|
<MapWrapper onMouseLeave={props.enableDrag}>
|
2020-11-30 07:23:05 +00:00
|
|
|
{status === ScriptStatus.READY && (
|
|
|
|
|
<MyMapComponent
|
|
|
|
|
loadingElement={<MapContainerWrapper />}
|
|
|
|
|
containerElement={<MapContainerWrapper />}
|
|
|
|
|
mapElement={<MapContainerWrapper />}
|
|
|
|
|
{...props}
|
|
|
|
|
zoom={zoom}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
2020-11-25 16:02:54 +00:00
|
|
|
</MapWrapper>
|
|
|
|
|
);
|
|
|
|
|
};
|
2020-04-15 11:42:11 +00:00
|
|
|
|
|
|
|
|
export default MapComponent;
|