2020-11-14 00:44:26 +03:00
|
|
|
import { FC } from 'react';
|
2019-01-09 22:30:59 +03:00
|
|
|
import { Modal, ModalBody } from 'reactstrap';
|
2020-11-14 13:00:41 +03:00
|
|
|
import { MapContainer, TileLayer, Marker, Popup, MapContainerProps } from 'react-leaflet';
|
2019-03-04 22:24:28 +03:00
|
|
|
import { prop } from 'ramda';
|
2020-09-02 21:13:31 +03:00
|
|
|
import { CityStats } from '../types';
|
2019-01-07 15:35:14 +03:00
|
|
|
import './MapModal.scss';
|
|
|
|
|
2020-09-02 21:13:31 +03:00
|
|
|
interface MapModalProps {
|
|
|
|
toggle: () => void;
|
|
|
|
isOpen: boolean;
|
|
|
|
title: string;
|
|
|
|
locations?: CityStats[];
|
|
|
|
}
|
2019-01-07 15:35:14 +03:00
|
|
|
|
2020-09-02 21:13:31 +03:00
|
|
|
const OpenStreetMapTile: FC = () => (
|
2019-01-07 23:00:28 +03:00
|
|
|
<TileLayer
|
2022-12-03 14:15:36 +03:00
|
|
|
attribution='&copy <a href="https://osm.org/copyright">OpenStreetMap</a> contributors'
|
2019-01-07 23:00:28 +03:00
|
|
|
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
|
|
|
/>
|
|
|
|
);
|
2019-01-07 15:35:14 +03:00
|
|
|
|
2020-11-14 13:00:41 +03:00
|
|
|
const calculateMapProps = (locations: CityStats[]): MapContainerProps => {
|
2019-03-10 14:09:54 +03:00
|
|
|
if (locations.length === 0) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2019-03-04 22:24:28 +03:00
|
|
|
if (locations.length > 1) {
|
|
|
|
return { bounds: locations.map(prop('latLong')) };
|
|
|
|
}
|
|
|
|
|
|
|
|
// When there's only one location, an error is thrown if trying to calculate the bounds.
|
2022-05-28 12:16:59 +03:00
|
|
|
// When that happens, we use "zoom" and "center" as a workaround
|
2019-03-04 22:24:28 +03:00
|
|
|
const [{ latLong: center }] = locations;
|
|
|
|
|
2020-09-02 21:13:31 +03:00
|
|
|
return { zoom: 10, center };
|
2019-03-04 22:24:28 +03:00
|
|
|
};
|
2019-03-03 13:47:19 +03:00
|
|
|
|
2022-05-28 12:16:59 +03:00
|
|
|
export const MapModal = ({ toggle, isOpen, title, locations = [] }: MapModalProps) => (
|
2019-01-07 23:00:28 +03:00
|
|
|
<Modal toggle={toggle} isOpen={isOpen} className="map-modal__modal" contentClassName="map-modal__modal-content">
|
|
|
|
<ModalBody className="map-modal__modal-body">
|
2019-01-09 22:30:59 +03:00
|
|
|
<h3 className="map-modal__modal-title">
|
|
|
|
{title}
|
2022-06-11 19:10:08 +03:00
|
|
|
<button type="button" className="btn-close float-end" aria-label="Close" onClick={toggle} />
|
2019-01-09 22:30:59 +03:00
|
|
|
</h3>
|
2020-11-14 13:00:41 +03:00
|
|
|
<MapContainer {...calculateMapProps(locations)}>
|
2019-01-07 23:00:28 +03:00
|
|
|
<OpenStreetMapTile />
|
2019-01-07 23:11:09 +03:00
|
|
|
{locations.map(({ cityName, latLong, count }, index) => (
|
2019-01-07 23:00:28 +03:00
|
|
|
<Marker key={index} position={latLong}>
|
2019-01-07 23:11:09 +03:00
|
|
|
<Popup><b>{count}</b> visit{count > 1 ? 's' : ''} from <b>{cityName}</b></Popup>
|
2019-01-07 21:43:25 +03:00
|
|
|
</Marker>
|
2019-01-07 23:00:28 +03:00
|
|
|
))}
|
2020-11-14 13:00:41 +03:00
|
|
|
</MapContainer>
|
2019-01-07 23:00:28 +03:00
|
|
|
</ModalBody>
|
|
|
|
</Modal>
|
|
|
|
);
|