import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { compose, withStateHandlers } from 'recompose';
import {
withScriptjs,
withGoogleMap,
GoogleMap,
Marker,
InfoWindow
} from 'react-google-maps';
import { MarkerClusterer } from 'react-google-maps/lib/components/addons/MarkerClusterer';
// Custom Components
import LayerMapSwitches from './LayerMapSwitches';
// Helpers
import GOOGLE_MAPS_API from '../utils/constants';
import Client from '../utils/feathers';
// Images
import MerchantPin from '../assets/img/map/merchant_pin.png';
import AmbassadorPin from '../assets/img/map/ambassador_pin.png';
/**
* This object is used for type checking the props of the component.
*/
const propTypes = {
ambassadors: PropTypes.array,
merchants: PropTypes.array,
mapCenter: PropTypes.object,
mapZoom: PropTypes.number,
// Fix google maps modal problem
showControls: PropTypes.bool
};
/**
* This object sets default values to the optional props.
*/
const defaultProps = {
mapCenter: { lat: -22.9068, lng: -43.1729 },
mapZoom: 12,
googleMapURL:
`https://maps.googleapis.com/maps/api/js?key=${GOOGLE_MAPS_API}&v=3.exp&libraries=geometry,drawing,places`,
loadingElement:
,
containerElement: ,
mapElement: ,
// Fix google maps modal problem
showControls: true,
};
defaultProps['markers'] = [
defaultProps.mapCenter
];
/**
* Map that support Merchant Layer Markers and Ambassadors Layer Markers.
*/
const CustomLayerMap = compose(
withStateHandlers(() => ({
isOpenObj: {},
isOpenAmbassadorObj:{}
}), {
onToggleOpen: ({ isOpenObj }) => (index) => {
const openObj = isOpenObj;
openObj[index] = !openObj[index];
return openObj;
},
onToggleAmbassadorOpen: ({ isOpenAmbassadorObj }) => (index) => {
const openObj = isOpenAmbassadorObj;
openObj[index] = !openObj[index];
return openObj;
}
}),
withScriptjs,
withGoogleMap
)(props =>
{props.ambassadors.map( (marker, index) => (
marker.withInfo ? (
props.onToggleOpen(index)}
>
{props.isOpenObj[index] && props.onToggleOpen(index)}>
{marker.infoTitle}
{marker.infoDescription}
}
) : (
)
))}
{props.merchants.map( (marker, index) => (
marker.withInfo ? (
props.onToggleAmbassadorOpen(index)}
>
{props.isOpenAmbassadorObj[index] && props.onToggleAmbassadorOpen(index)}>
{marker.infoTitle}
{marker.infoDescription}
}
) : (
)
))}
);
// Type checking the props of the component
CustomLayerMap.propTypes = propTypes;
// Assign default values to the optional props
CustomLayerMap.defaultProps = defaultProps;
/**
* This object is used for type checking the props of the component.
*/
const propTypesLayerMap = {
ambassadorsLayer: PropTypes.bool,
merchantsLayer: PropTypes.bool,
showControls: PropTypes.bool,
mapHeight: PropTypes.string
};
class LayerMap extends Component {
constructor(props) {
super(props);
this.state = {
ambassadors: [],
merchants: [],
ambassadorLayer: this.props.ambassadorsLayer,
merchantLayer: this.props.merchantsLayer
};
}
/**
* @description Lifecycle event handler called just after the App loads into the DOM.
*/
UNSAFE_componentWillMount() {
this.getAmbassadors();
this.getMerchants();
}
/**
* @description Get the ambassadors list from the web service.
* @param {string} id - Merchant ID.
*/
getAmbassadors = () => {
const app = this;
const ambassadors = Client.service('api/v2/ambassadors');
this.setState({loading: true});
ambassadors.find().then( (results) => {
const markers = [];
results.data.forEach(ambassador => {
ambassador.cities.forEach(function(city) {
const marker = {
lat: city.lat,
lng: city.lon,
withInfo: true,
infoTitle: ambassador.nickname,
infoDescription: `${city.name} - ${city.country}`,
};
markers.push(marker);
});
});
// Once both return, update the state
app.setState({
ambassadors: markers,
loading: false
});
}).catch( error => {
app.setState({responseError: error.message, loading: false});
});
};
/**
* @description Get the merchants list from the web service.
* @param {string} id - Merchant ID.
*/
getMerchants = () => {
const app = this;
const merchants = Client.service('api/v1/merchants');
this.setState({loading: true});
merchants.find().then( (results) => {
const markers = results.data.map(merchant => {
const marker = {
lat: merchant.lat,
lng: merchant.lon,
withInfo: true,
infoTitle: merchant.name,
infoDescription: `${merchant.address}, ${merchant.city} - ${merchant.country}`,
};
return marker;
});
// Once both return, update the state
app.setState({
merchants: markers,
loading: false
});
}).catch( error => {
app.setState({responseError: error.message, loading: false});
});
};
handleLayerChange = name => event => {
this.setState({ [name]: event.target.checked });
// Update any time changes
this.getAmbassadors();
this.getMerchants();
};
render() {
// create an array with marker components
return (
{!this.props.showControls ? (
) : (
)}
}
containerElement={
}
mapElement={
}
/>
);
}
}
// Type checking the props of the component
LayerMap.propTypes = propTypesLayerMap;
export default LayerMap;