import React from 'react'
import { View, TouchableOpacity, Text, BackHandler } from 'react-native'
import MapView, { Callout } from 'react-native-maps'
import { connect } from 'react-redux'
//action
import { getAgentLocation } from '../../actions/Map'
import { MapCallout, CustomNavbar } from '../../components'
import styles from './styles'
import MCIcons from 'react-native-vector-icons/MaterialCommunityIcons'
import Modal from 'react-native-modal'
import { Metrics, Colors } from '../../themes'
import I18n from 'react-native-i18n'
import * as ConfigCode from '../../utils/ConfigCode'
import * as FIELD from '../../utils/CoreFieldMap'
import * as RequestField from '../../utils/RequestField'
import _ from 'lodash'
import MapViewDirections from 'react-native-maps-directions'
import Ionicons from 'react-native-vector-icons/Ionicons'
import { OpenMapDirections } from 'react-native-navigation-directions'
import Reactotron from 'reactotron-react-native'
const GOOGLE_MAPS_APIKEY = 'xxxxxx'
class MapScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
// const { params = {} } = navigation.state
return {
header:
<CustomNavbar
midTitle txtTitle={'findAgent'}
Nav={navigation}
backButton onBackLeft={() => navigation.state.params.handlePress()} />
}
}
constructor(props) {
super(props)
this.state = {
region: {
latitude: 21.027764,
longitude: 105.834160,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421
},
locations: [],
showUserLocation: true,
isShowBottom: false,
hackHeight: Metrics.height
}
this.renderMapMarkers = this.renderMapMarkers.bind(this)
this.onRegionChange = this.onRegionChange.bind(this)
this.handleBackButtonClick = this.handleBackButtonClick.bind(this)
}
componentWillMount() {
setTimeout(() => this.setState({ hackHeight: Metrics.height - Metrics.navBarHeight }), 500)
this.getCurrentLocation()
BackHandler.addEventListener('hardwareBackPress', this.handleBackButtonClick);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButtonClick);
}
handleBackButtonClick() {
this.setState({ ready: false })
}
componentDidMount() {
this.props.navigation.setParams({
handlePress: this.goBack.bind(this)
})
}
goBack() {
const { navigation } = this.props;
this.setState({ ready: false })
navigation.goBack()
}
getCurrentLocation() {
try {
const { region } = this.state
navigator.geolocation.getCurrentPosition(
(position) => {
const region = {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
latitudeDelta: 0.01,
longitudeDelta: 0.01
}
this.setRegion(region)
this.onGetAgentLocation(region.latitude, region.longitude)
},
(error) => this.setState({ error: error.message }),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
)
} catch (e) {
alert(e.message || "")
}
}
onMapReady() {
if (!this.state.ready) {
this.setState({ ready: true })
}
}
setRegion(region) {
// this.setState({latitude: region.latitude, longitude: region.longitude})
this.setState({ region })
try {
if (this.state.ready) {
this.map.animateToRegion(region)
}
} catch (e) {
alert(e)
}
}
onGetAgentLocation(lat, long) {
const { infoAccount } = this.props
RequestField.addToInitField(RequestField.addProcessCode(ConfigCode.SEARCH_TRANSACTION_DETAIL)) // 311003
RequestField.addToInitField(RequestField.addPhone(infoAccount.phoneNumber))
RequestField.addToInitField(RequestField.addLongitude(long))
RequestField.addToInitField(RequestField.addLatitude(lat))
let data = RequestField.addToInitField(RequestField.addAccountID(infoAccount.accountId))
data.fieldMap = _.orderBy(data.fieldMap, 'fieldID')
this.setState({ isGetAgentLocation: true, isLoading: true })
Reactotron.log('311003 ======================')
Reactotron.log(data)
this.props.getAgentLocation(data)
}
componentWillReceiveProps(nextProps) {
this.forceUpdate()
if (this.state.isGetAgentLocation && !nextProps.isFetching) {
this.setState({ isGetAgentLocation: false, isLoading: false })
if (nextProps.agentLocations && nextProps.agentLocations.error === '00000') {
if (nextProps.agentLocations.responseCode === '00000') {
// do something here
let dataStatement = RequestField.getValueField(nextProps.agentLocations.fieldMap, FIELD.MINI_STATEMENT_DATA)
if (dataStatement && dataStatement.agent) {
let arrDataStatement = dataStatement.agent
this.setState({ locations: arrDataStatement })
}
} else {
alert(I18n.t(`${nextProps.agentLocations.responseCode}`))
}
} else {
alert(I18n.t(nextProps.agentLocations && nextProps.agentLocations.responseCode
? `${nextProps.agentLocations.responseCode}` : 'systemBusy'))
}
}
}
onRegionChange(newRegion) {
/* ***********************************************************
* STEP 4
* If you wish to fetch new locations when the user changes the
* currently visible region, do something like this:
*************************************************************/
// const searchRegion = {
// ne_lat: newRegion.latitude + newRegion.latitudeDelta / 2,
// ne_long: newRegion.longitude + newRegion.longitudeDelta / 2,
// sw_lat: newRegion.latitude - newRegion.latitudeDelta / 2,
// sw_long: newRegion.longitude - newRegion.longitudeDelta / 2
// }
// Fetch new data...
}
calloutPress(location) {
alert('1')
console.tron.log('location') // Reactotron
console.tron.log(location) // Reactotron
}
onPressMarker(destination, location, rand) {
this.setState({ destination, selectedLocation: location, isShowBottom: true, rand })
Reactotron.log('xxxxxxxxxxxx')
Reactotron.log(destination)
}
renderMapMarkers(location) {
let rand = Math.floor(Math.random() * 100) + 1
let lat = parseInt(location.latitude.trim())
let long = parseInt(location.longitude.trim())
let destination = { latitude: lat, longitude: long }
return (
<MapView.Marker
key={location.title}
onPress={() => this.onPressMarker(destination, location, rand)}
coordinate={{ latitude: lat, longitude: long }}
>
<TouchableOpacity style={styles.markerContent}>
<MCIcons name='map-marker' size={30} color='red' />
</TouchableOpacity>
<Callout>
<MapCallout location={location} onPress={() => this.calloutPress()} />
</Callout>
</MapView.Marker>
)
}
onPressMap() {
this.setState({ isShowBottom: false })
}
navigateMap() {
const { region, destination } = this.state
const startPoint = {
longitude: region.longitude,
latitude: region.latitude
}
const endPoint = {
longitude: destination.longitude,
latitude: destination.latitude
}
// Available values: d => (by car), w => (by foot), r => (by public transit).
// If you don’t specify any value, Maps uses the user’s preferred transport type or the previous setting.
const transportPlan = 'w';
OpenMapDirections(startPoint, endPoint, transportPlan).then(res => {
console.log(res)
});
}
render() {
const { isShowBottom, region, destination, selectedLocation } = this.state
return (
// <View style={[styles.container, { height: this.state.hackHeight }]}>
<View style={[styles.container]}>
<MapView
ref={ref => { this.map = ref }}
onPress={() => this.onPressMap()}
style={styles.map}
initialRegion={this.state.region}
onRegionChangeComplete={this.onRegionChange}
showsUserLocation={this.state.showUserLocation}
onMapReady={() => this.onMapReady()}
showsMyLocationButton
>
{this.state.locations.map((location) => this.renderMapMarkers(location))}
{destination ? <MapViewDirections
origin={{ latitude: region.latitude, longitude: region.longitude }}
destination={{ latitude: destination.latitude, longitude: destination.longitude }}
apikey={GOOGLE_MAPS_APIKEY}
strokeWidth={3}
strokeColor="hotpink"
/> : null}
</MapView>
{
isShowBottom ? (
<View style={styles.buttonContainer}>
<View style={styles.bubble}>
<Text>{selectedLocation && selectedLocation.title}</Text>
<Text>{selectedLocation && selectedLocation.phone} {this.state.rand}</Text>
</View>
{destination ? <TouchableOpacity onPress={() => this.navigateMap()}>
<Ionicons name='ios-navigate' color={Colors.txtUpLight} size={40} style={styles.icNavigate} />
</TouchableOpacity>: null}
</View>
) : null
}
</View>
)
}
}
const mapStateToProps = (state) => {
return {
isFetching: state.map.isFetching,
infoAccount: state.auth.infoAccount,
agentLocations: state.map.agentLocations,
}
}
const mapDispatchToProps = (dispatch) => {
return {
getAgentLocation: (data) => { dispatch(getAgentLocation(data)) }
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MapScreen)
=====================================================================
import { StyleSheet, Dimensions } from 'react-native'
import { Metrics } from '../../themes'
const { width, height } = Dimensions.get('window')
// Enable this if you have app-wide application styles
// import { ApplicationStyles } from '../../Themes/'
export default StyleSheet.create({
// Merge in the screen styles from application styles
// ...ApplicationStyles.screen,
container: {
...StyleSheet.absoluteFillObject,
justifyContent: 'flex-end',
alignItems: 'center'
// flex: 1
},
map: {
// For Android :/
// position: 'absolute',
// top: 0,
// left: 0,
// right: 0,
// bottom: 0
...StyleSheet.absoluteFillObject
// width: width,
// height: height
},
markerContent: {
},
// bottom view
buttonContainer: {
flexDirection: 'row',
height: 100,
backgroundColor: 'white',
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: Metrics.doubleBaseMargin
},
bubble: {
flex: 1,
backgroundColor: 'rgba(255,255,255,0.7)'
},
icNavigate: {
}
})
=========================================================
MapCallout
import React from 'react'
import { Text, TouchableOpacity, Image } from 'react-native'
import { Callout } from 'react-native-maps'
import Styles from './styles'
export default class MapScreenCallout extends React.Component {
constructor (props) {
super(props)
this.onPress = this.props.onPress.bind(this, this.props.location)
}
render () {
/* ***********************************************************
* Customize the appearance of the callout that opens when the user interacts with a marker.
* Note: if you don't want your callout surrounded by the default tooltip, pass `tooltip={true}` to `Callout`
*************************************************************/
const { location } = this.props
return (
<Callout style={Styles.callout} >
<TouchableOpacity onPress={this.onPress}>
<Text>{location.title}</Text>
<Image source={{uri: 'http://i.stack.imgur.com/WCveg.jpg'}}
style={{height: '90%', width: '90%'}} />
</TouchableOpacity>
</Callout>
)
}
}
===============
import { StyleSheet } from 'react-native'
export default StyleSheet.create({
callout: {
height: 100,
width: 100,
position: 'relative'
// flex: 1
}
})