Skip to content

Commit

Permalink
feat (GLocationPicker): changed leaflet location picker to gmap
Browse files Browse the repository at this point in the history
  • Loading branch information
khavinshankar committed Jun 27, 2022
1 parent c283310 commit 2cec8ae
Show file tree
Hide file tree
Showing 6 changed files with 278 additions and 25 deletions.
70 changes: 70 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions package.json
Expand Up @@ -33,6 +33,8 @@
"@babel/core": "^7.14.3",
"@date-io/date-fns": "^1.3.13",
"@glennsl/bs-json": "^5.0.3",
"@googlemaps/react-wrapper": "^1.1.35",
"@googlemaps/typescript-guards": "^2.0.0",
"@headlessui/react": "^1.6.4",
"@loadable/component": "^5.15.0",
"@material-ui/core": "^4.11.4",
Expand All @@ -44,6 +46,7 @@
"@rescript/react": "^0.10.3",
"@sentry/browser": "^6.12.0",
"@types/echarts": "^4.9.9",
"@types/googlemaps": "^3.43.3",
"@types/loadable__component": "^5.13.3",
"@types/lodash": "^4.14.170",
"@types/node": "^15.6.1",
Expand All @@ -66,6 +69,7 @@
"date-fns-tz": "^1.0.10",
"echarts": "^5.1.2",
"echarts-for-react": "^3.0.1",
"fast-equals": "^4.0.1",
"i18next": "^20.3.1",
"i18next-browser-languagedetector": "^6.1.1",
"libphonenumber-js": "^1.9.19",
Expand Down
2 changes: 2 additions & 0 deletions src/Common/env.tsx
@@ -1 +1,3 @@
export const RECAPTCHA_SITE_KEY = "6Lc67IceAAAAADO2oNsVRxlCOdKpFJufdBiefGrf";

export const GMAPS_API_KEY = "AIzaSyDsBAc3y7deI5ZO3NtK5GuzKwtUzQNJNUk";
180 changes: 180 additions & 0 deletions src/Components/Common/GLocationPicker.tsx
@@ -0,0 +1,180 @@
import React from "react";
import { Wrapper, Status } from "@googlemaps/react-wrapper";
import { createCustomEqual } from "fast-equals";
import { isLatLngLiteral } from "@googlemaps/typescript-guards";

import { GMAPS_API_KEY } from "../../Common/env";

const render = (status: Status) => {
return <h1>{status}</h1>;
};

interface GLocationPickerProps {
lat: number;
lng: number;
handleOnChange: (location: google.maps.LatLng) => void;
}

const GLocationPicker = ({
lat,
lng,
handleOnChange,
}: GLocationPickerProps) => {
const [location, setLocation] = React.useState<google.maps.LatLng | null>(
null
);
const [zoom, setZoom] = React.useState(4);
const [center, setCenter] = React.useState<google.maps.LatLngLiteral>({
lat,
lng,
});

React.useEffect(() => {
(async function () {
const latLng = await new google.maps.LatLng(lat, lng);
setLocation(latLng);
})();
}, [lat, lng]);

const onClick = (e: google.maps.MapMouseEvent) => {
handleOnChange(e.latLng);
};

const onIdle = (m: google.maps.Map) => {
console.log("onIdle");
setZoom(m.getZoom()!);
setCenter(m.getCenter()!.toJSON());
};

return (
<div className="flex w-96 h-96">
<Wrapper apiKey={GMAPS_API_KEY} render={render}>
<Map
center={center}
onClick={onClick}
onIdle={onIdle}
zoom={zoom}
style={{ flexGrow: "1", height: "100%" }}
>
{location && <Marker position={location} />}
</Map>
</Wrapper>
</div>
);
};
interface MapProps extends google.maps.MapOptions {
style: { [key: string]: string };
onClick?: (e: google.maps.MapMouseEvent) => void;
onIdle?: (map: google.maps.Map) => void;
children?: React.ReactNode;
}

const Map: React.FC<MapProps> = ({
onClick,
onIdle,
children,
style,
...options
}) => {
const ref = React.useRef<HTMLDivElement>(null);
const [map, setMap] = React.useState<google.maps.Map>();

React.useEffect(() => {
if (ref.current && !map) {
setMap(new window.google.maps.Map(ref.current, {}));
}
}, [ref, map]);

useDeepCompareEffectForMaps(() => {
if (map) {
map.setOptions(options);
}
}, [map, options]);

React.useEffect(() => {
if (map) {
["click", "idle"].forEach((eventName) =>
google.maps.event.clearListeners(map, eventName)
);

if (onClick) {
map.addListener("click", onClick);
}

if (onIdle) {
map.addListener("idle", () => onIdle(map));
}
}
}, [map, onClick, onIdle]);

return (
<>
<div ref={ref} style={style} />
{React.Children.map(children, (child) => {
if (React.isValidElement(child)) {
return React.cloneElement(child, { map });
}
})}
</>
);
};

const Marker: React.FC<google.maps.MarkerOptions> = (options) => {
const [marker, setMarker] = React.useState<google.maps.Marker>();

React.useEffect(() => {
if (!marker) {
setMarker(new google.maps.Marker());
}

return () => {
if (marker) {
marker.setMap(null);
}
};
}, [marker]);

React.useEffect(() => {
if (marker) {
marker.setOptions(options);
}
}, [marker, options]);

return null;
};

const deepCompareEqualsForMaps = createCustomEqual(
// @ts-ignore
(deepEqual) => (a: any, b: any) => {
if (
isLatLngLiteral(a) ||
a instanceof google.maps.LatLng ||
isLatLngLiteral(b) ||
b instanceof google.maps.LatLng
) {
return new google.maps.LatLng(a).equals(new google.maps.LatLng(b));
}

// @ts-ignore
return deepEqual(a, b);
}
);

function useDeepCompareMemoize(value: any) {
const ref = React.useRef();

if (!deepCompareEqualsForMaps(value, ref.current)) {
ref.current = value;
}

return ref.current;
}

function useDeepCompareEffectForMaps(
callback: React.EffectCallback,
dependencies: any[]
) {
React.useEffect(callback, dependencies.map(useDeepCompareMemoize));
}

export default GLocationPicker;

0 comments on commit 2cec8ae

Please sign in to comment.