Created
August 22, 2018 09:46
-
-
Save galulex/ed4274e4cb4b4f136778fc3c057952b6 to your computer and use it in GitHub Desktop.
React Code sample
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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