Skip to content

Instantly share code, notes, and snippets.

@galulex
Created August 22, 2018 09:46
Show Gist options
  • Save galulex/ed4274e4cb4b4f136778fc3c057952b6 to your computer and use it in GitHub Desktop.
Save galulex/ed4274e4cb4b4f136778fc3c057952b6 to your computer and use it in GitHub Desktop.
React Code sample
import React, { Component } from 'react'
import {
Platform,
AsyncStorage,
Alert,
Modal,
TextInput,
TouchableOpacity,
Keyboard
} from 'react-native'
import {
View,
Container,
Content,
Button as NBButton,
Icon,
Form,
Input
} from 'native-base'
import AppHeader from '../Components/AppHeader'
import { connect } from 'react-redux'
import firebase from 'react-native-firebase'
import SearchActions from '../Redux/SearchRedux'
import LocationActions from '../Redux/LocationRedux'
import MapActions from '../Redux/MapRedux'
import TripActions from '../Redux/TripRedux'
import TripsActions from '../Redux/TripsRedux'
import SearchPredictions from '../Components/SearchPredictions'
import SearchMap from '../Components/SearchMap'
import Button from '../Components/Button'
import { calculateRegion } from '../Lib/MapHelpers'
import I18n from 'react-native-i18n'
import reverseGeolocate from '../Services/GooglePlacesWebService'
import { Colors } from '../Themes'
import styles from './Styles/SearchScreenStyles'
const Analytics = firebase.analytics()
class SearchScreen extends Component {
state = {
modalVisible: false,
selectedField: null,
visiblePredictions: null,
comment: ''
}
componentWillMount () {
this.props.getCurrentLocation()
}
componentDidMount () {
this.requestTour()
const { currentLocation } = this.props
reverseGeolocate(currentLocation.latitude, currentLocation.longitude)
.then(res => {
if (res.status === 'OK' && res.results.length) {
this.props.handlePredictionPress(res.results[0].place_id, 0)
}
})
}
requestTour = async () => {
const isTourFinished = await AsyncStorage.getItem('@Tour:key')
if (!isTourFinished) {
Alert.alert(
I18n.t('tourWalkthrougthTitle'),
I18n.t('tourWalkthrougth'),
[
{ text: 'Cancel', onPress: async () => { await AsyncStorage.setItem('@Tour:key', 'true') }, style: 'cancel' },
{
text: 'OK',
onPress: async () => {
this.props.navigation.navigate('Tutorial')
await AsyncStorage.setItem('@Tour:key', 'true')
}
}
],
{ cancelable: false }
)
}
}
setModalVisible = (visible, id = null) => {
this.setState({ modalVisible: visible, selectedField: id, visiblePredictions: null })
}
renderAutocompletePredictions = (predictions, id) => {
return (
<SearchPredictions
isVisible={this.state.visiblePredictions === id}
fetching={this.props.search.fetching}
predictions={predictions.length ? predictions : this.props.storedLocations}
onItemPress={(item) => {
this.props.handlePredictionPress(item.placeID, id)
this.props.storeLocation(item)
this.refs[id]._root.blur()
}}
/>
)
}
renderStartDirection = () => (
<View
style={styles.locationPointWrapper}
>
<View style={styles.locationPointSpace} />
<View style={styles.startLocationPoint} />
<View style={styles.locationPointJoiner} />
</View>
)
renderEndDirection = () => (
<View
style={styles.locationPointWrapper}
>
<View style={styles.locationPointJoiner} />
<View style={styles.endLocationPoint} />
<View style={styles.locationPointSpace} />
</View>
)
renderDirections = () => (
<View
style={styles.locationPointWrapper}
>
<View style={styles.locationPointJoiner} />
<View style={styles.throughLocationPoint} />
<View style={styles.locationPointJoiner} />
</View>
)
renderInput = (el, index) => {
const { waypoints } = this.props.search
let direction
if (index === 0) {
direction = this.renderStartDirection()
} else if (index === waypoints.length - 1) {
direction = this.renderEndDirection()
} else {
direction = this.renderDirections()
}
const hasError = el.selectedAddress === null && !el.pristine
let borderColor
if (hasError) {
borderColor = Colors.cablookPink
} else if (index !== waypoints.length - 1) {
borderColor = Colors.cablookLightGrey
} else {
borderColor = 'transparent'
}
return (
<View key={el.id}>
<View style={styles.inputWrapper}>
{direction}
<View
style={[
styles.inputInnerWrapper,
{ borderBottomColor: borderColor }
]}
>
<Input
ref={el.id}
autoCorrect={false}
selectTextOnFocus
style={{
color: Colors.cablookDarkViolet,
fontFamily: Platform.OS === 'ios' ? 'Gilroy-Bold' : 'gilroy_bold'
}}
placeholder={el.placeholder}
placeholderTextColor={Colors.cablookGreen}
onFocus={() => {
this.setState({ visiblePredictions: el.id })
}}
onChange={() => this.props.onAddressFocus(el.id)}
onBlur={() => this.setState({ visiblePredictions: null })}
value={el.value}
onChangeText={(e) => this.props.handleTextChange(e, el.id)}
/>
<View style={styles.inputButtonGroup}>
<NBButton
small
transparent
onPress={() => {
this.refs[el.id]._root.blur()
this.setModalVisible(true, el.id)
}}
>
<Icon name='pin' style={{ color: Colors.cablookGreen }} />
</NBButton>
{(el.id !== 0 && el.id !== 1) && <NBButton
small
transparent
onPress={() => this.props.removeWaypoint(el.id)
}>
<Icon name='close' style={{ color: Colors.cablookPink }} />
</NBButton>}
</View>
</View>
</View>
{this.renderAutocompletePredictions(el.predictions, el.id)}
</View>
)
}
onAddressSelect = (address) => {
this.props.handlePredictionPress(address.place_id, this.state.selectedField)
this.setModalVisible(false)
this.setState({ visiblePredictions: null })
}
handleOnOkPress = () => {
Analytics.logEvent('ok_pressed')
Keyboard.dismiss()
const places = this.props.search.waypoints
.filter(waypoint => !!waypoint.selectedAddress)
.map(waypoint => waypoint.selectedAddress.place_id)
.filter(place => place !== '')
const stops = this.props.search.waypoints
.map(waypoint => waypoint.value)
let departureAddress = stops[0]
let destinationAddress = stops[stops.length - 1]
let halts = stops.slice(1, stops.length - 1)
let departure = places[0]
let destination = places[places.length - 1]
let waypoints = places.slice(1, stops.length - 1)
const params = {
departure_address: departureAddress,
destination_address: destinationAddress,
stops: halts,
departure,
destination,
waypoints,
comment: this.state.comment
}
this.props.buildTrip(params)
}
renderComment = () => (
<View>
<View style={styles.commentWrapper}>
<TextInput
style={styles.commentInput}
value={this.state.comment}
onChangeText={val => this.setState({ comment: val })}
placeholder={`${I18n.t('yourComment')}...`}
placeholderTextColor={Colors.cablookDarkGreen}
numberOfLines={1}
underlineColorAndroid='transparent'
/>
</View>
</View>
)
renderButton = () => {
const { waypoints } = this.props.search
const disabled = waypoints[waypoints.length - 1].selectedAddress === null || waypoints[0].selectedAddress === null
return (
<TouchableOpacity
style={[styles.addButton, { borderColor: !disabled ? Colors.cablookGreen : Colors.cablookLightGrey }]}
onPress={() => this.props.addWaypoint()}
disabled={disabled}
>
<Icon name='add' style={{ fontSize: 42, color: !disabled ? Colors.cablookGreen : Colors.cablookLightGrey }} />
</TouchableOpacity>
)
}
render () {
const { waypoints } = this.props.search
const { fetching } = this.props.trip
return (
<Container>
<AppHeader
title={I18n.t('tripSearch')}
onButtonPress={this.props.navigation.toggleDrawer}
/>
<Content padder contentContainerStyle={styles.contentWrapper}>
<Form>
{waypoints.map((el, index) => this.renderInput(el, index))}
</Form>
{waypoints.length < 6 && this.renderButton()}
<View>
{this.renderComment()}
<Button
disabled={waypoints.map(e => e.selectedAddress).indexOf(null) !== -1 || fetching}
onPress={this.handleOnOkPress}
style={{ marginHorizontal: 0 }}
submitting={fetching}
>
{I18n.t('OK')}
</Button>
</View>
</Content>
<Modal
animationType='slide'
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => { }}
>
<SearchMap
region={this.props.region}
onButtonPress={this.onAddressSelect}
onModalClose={() => this.setModalVisible(false)}
/>
</Modal>
</Container>
)
}
}
const mapStateToProps = ({ cards, search, trip, map: { region }, location: { currentLocation }, trips: { storedLocations } }) => {
return {
search,
trip,
region,
currentLocation,
storedLocations,
cards
}
}
const mapDisptchToProps = (dispatch) => {
return {
getCurrentLocation: () => dispatch(LocationActions.currentLocationRequest()),
addWaypoint: () => dispatch(SearchActions.addWaypoint()),
removeWaypoint: id => dispatch(SearchActions.removeWaypoint(id)),
handleTextChange: (text, id) => dispatch(SearchActions.changeTextRequest(text, id)),
handlePredictionPress: (selectedAddress, id) => dispatch(SearchActions.selectAddressRequest(selectedAddress, id)),
onAddressFocus: id => dispatch(SearchActions.resetAddress(id)),
setTrip: data => dispatch(TripActions.setTrip(data)),
setRegion: (locations) => dispatch(MapActions.updateRegion(calculateRegion(locations, { latPadding: 0.09, longPadding: 0.09 }))),
storeLocation: (location) => dispatch(TripsActions.storeLocation(location)),
buildTrip: data => dispatch(TripActions.buildTripRequest(data))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(SearchScreen)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment