Created
January 13, 2017 19:34
-
-
Save andybangs/79e46c58432aaaea92d030f8d415aded to your computer and use it in GitHub Desktop.
Example Component
This file contains hidden or 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, PropTypes } from 'react'; | |
import { connect } from 'react-redux'; | |
import { bindActionCreators } from 'redux'; | |
import { | |
ActionSheetIOS, | |
ActivityIndicator, | |
Keyboard, | |
LayoutAnimation, | |
NativeModules, | |
StyleSheet, | |
ScrollView, | |
TouchableWithoutFeedback, | |
View | |
} from 'react-native'; | |
import GiveSlider from './components/GiveSlider'; | |
import FAQModal from './components/FAQModal'; | |
import APP from '../app/index'; | |
const { AddCCButton, GSButton, RegularText, SectionHeader, constants } = APP; | |
const { COLORS, METHODS } = constants; | |
const propTypes = { | |
app: PropTypes.object.isRequired, | |
actions: PropTypes.object.isRequired | |
}; | |
export class Settings extends Component { | |
constructor(props) { | |
super(props); | |
this.onPressPaymentMethod = this.onPressPaymentMethod.bind(this); | |
this.onPressCreditCard = this.onPressCreditCard.bind(this); | |
this.onSliderUpdate = this.onSliderUpdate.bind(this); | |
this.onPressSignOut = this.onPressSignOut.bind(this); | |
this.toggleInputVisible = this.toggleInputVisible.bind(this); | |
this.toggleModalVisible = this.toggleModalVisible.bind(this); | |
this.renderPaymentMethods = this.renderPaymentMethods.bind(this); | |
this.state = { | |
ccInputVisible: false, | |
faqModalVisible: false | |
}; | |
} | |
componentWillReceiveProps(nextProps) { | |
if ( | |
this.state.ccInputVisible && | |
( | |
nextProps.app.error || | |
nextProps.app.paymentMethods.length !== this.props.app.paymentMethods.length | |
) | |
) { | |
this.toggleInputVisible(); | |
} | |
} | |
componentWillUpdate() { | |
const { Types, Properties, create } = LayoutAnimation; | |
const customAnim = create(100, Types.easeInEaseOut, Properties.opacity); | |
LayoutAnimation.configureNext(customAnim); | |
} | |
onPressPaymentMethod(method) { | |
const BUTTONS = ['Set Default Method', 'Cancel']; | |
const CANCEL_INDEX = 1; | |
ActionSheetIOS.showActionSheetWithOptions({ | |
options: BUTTONS, | |
cancelButtonIndex: CANCEL_INDEX | |
}, | |
(buttonIndex) => { | |
switch (buttonIndex) { | |
case 0: | |
this.props.actions.setDefaultMethod(method); | |
break; | |
case CANCEL_INDEX: | |
default: | |
return; | |
} | |
}); | |
} | |
onPressCreditCard(index) { | |
const { app, actions } = this.props; | |
const BUTTONS = ['Set Default Method', 'Delete', 'Cancel']; | |
const DESTRUCTIVE_INDEX = 1; | |
const CANCEL_INDEX = 2; | |
ActionSheetIOS.showActionSheetWithOptions({ | |
options: BUTTONS, | |
destructiveButtonIndex: DESTRUCTIVE_INDEX, | |
cancelButtonIndex: CANCEL_INDEX | |
}, | |
(buttonIndex) => { | |
const userID = app.paymentProfile.id; | |
const braintreeToken = app.paymentMethods[index].braintree_token; | |
switch (buttonIndex) { | |
case 0: | |
actions.setDefaultIndex(index); | |
break; | |
case DESTRUCTIVE_INDEX: | |
actions.deletePaymentMethod(index, userID, braintreeToken); | |
break; | |
case CANCEL_INDEX: | |
default: | |
return; | |
} | |
}); | |
} | |
onSliderUpdate(value) { | |
this.props.actions.setDefaultAmount(Math.ceil(value)); | |
} | |
onPressSignOut() { | |
this.props.actions.logout(); | |
} | |
toggleInputVisible() { | |
this.setState({ ccInputVisible: !this.state.ccInputVisible }); | |
} | |
toggleModalVisible() { | |
this.setState({ faqModalVisible: !this.state.faqModalVisible }); | |
} | |
renderPaymentMethods() { | |
const { | |
applePayEnabled, | |
defaultMethod, | |
paymentMethods, | |
deletePaymentMethodIsLoading, | |
defaultIndex | |
} = this.props.app; | |
const { ccInputVisible } = this.state; | |
const paymentsHeaderText = !ccInputVisible ? 'PAYMENT METHODS' : 'ADD CREDIT CARD'; | |
if (deletePaymentMethodIsLoading) { | |
return ( | |
<View> | |
<SectionHeader>{paymentsHeaderText}</SectionHeader> | |
<ActivityIndicator | |
animating | |
style={styles.indicator} | |
size="large" | |
/> | |
</View> | |
); | |
} | |
return ( | |
<View> | |
<SectionHeader>{paymentsHeaderText}</SectionHeader> | |
{!ccInputVisible && applePayEnabled && | |
<GSButton | |
onPress={() => this.onPressPaymentMethod(METHODS.APPLE_PAY)} | |
fontWeight={defaultMethod === METHODS.APPLE_PAY ? 'bold' : 'regular'} | |
checkmark={defaultMethod === METHODS.APPLE_PAY} | |
textAlign="left" | |
> | |
Apple Pay | |
</GSButton> | |
} | |
{!ccInputVisible && | |
<GSButton | |
onPress={() => this.onPressPaymentMethod(METHODS.PAYPAL)} | |
fontWeight={defaultMethod === METHODS.PAYPAL ? 'bold' : 'regular'} | |
checkmark={defaultMethod === METHODS.PAYPAL} | |
textAlign="left" | |
> | |
PayPal | |
</GSButton> | |
} | |
{!ccInputVisible && paymentMethods.map((method, i) => | |
<GSButton | |
key={i} | |
onPress={() => this.onPressCreditCard(i)} | |
fontWeight={ | |
defaultMethod === METHODS.CREDIT_CARD && | |
i === defaultIndex ? 'bold' : 'regular' | |
} | |
checkmark={defaultMethod === METHODS.CREDIT_CARD && i === defaultIndex} | |
textAlign="left" | |
> | |
{method.description} | |
</GSButton> | |
)} | |
<AddCCButton | |
buttonText="Add Credit Card..." | |
isLoading={this.props.app.postPaymentMethodIsLoading} | |
braintreeToken={this.props.app.braintreeToken} | |
inputVisible={this.state.ccInputVisible} | |
toggleInputVisible={this.toggleInputVisible} | |
/> | |
</View> | |
); | |
} | |
render() { | |
const { logoutIsLoading, paymentProfile, defaultAmount } = this.props.app; | |
return ( | |
<View style={styles.container}> | |
{/* Placeholder for navigation header */} | |
<View style={styles.header}> | |
{!!paymentProfile && !!paymentProfile.name ? ( | |
<RegularText style={styles.headerText}> | |
{`${paymentProfile.name} ${paymentProfile.last_name}`} | |
</RegularText> | |
) : ( | |
<RegularText style={styles.headerText}> | |
{`Citygoer ${this.props.app.user.donator_id}`} | |
</RegularText> | |
)} | |
</View> | |
<View style={styles.bodyCont}> | |
<ScrollView | |
keyboardDismissMode="on-drag" | |
keyboardShouldPersistTaps="always" | |
> | |
<TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}> | |
<View> | |
{this.renderPaymentMethods()} | |
<SectionHeader>DEFAULT GIVE AMOUNT: ${defaultAmount}</SectionHeader> | |
<View style={styles.sliderCont}> | |
<GiveSlider | |
value={defaultAmount} | |
onValueChange={this.onSliderUpdate} | |
/> | |
</View> | |
<SectionHeader /> | |
<GSButton onPress={() => NativeModules.GSSocialController.composeSupportEmail()}> | |
Support | |
</GSButton> | |
<GSButton onPress={this.toggleModalVisible}>FAQ</GSButton> | |
<GSButton onPress={this.onPressSignOut} isLoading={logoutIsLoading}> | |
Sign Out | |
</GSButton> | |
<SectionHeader /> | |
<FAQModal | |
visible={this.state.faqModalVisible} | |
toggleModal={this.toggleModalVisible} | |
/> | |
</View> | |
</TouchableWithoutFeedback> | |
</ScrollView> | |
</View> | |
</View> | |
); | |
} | |
} | |
const styles = StyleSheet.create({ | |
container: { | |
flex: 1 | |
}, | |
indicator: { | |
alignItems: 'center', | |
justifyContent: 'center', | |
height: 80, | |
padding: 8 | |
}, | |
header: { | |
flex: 1, | |
alignItems: 'center', | |
justifyContent: 'center', | |
backgroundColor: COLORS.purple | |
}, | |
headerText: { | |
color: COLORS.white | |
}, | |
bodyCont: { | |
flex: 14, | |
backgroundColor: COLORS.cream | |
}, | |
addPaymentButtonsCont: { | |
flex: 1, | |
flexDirection: 'row', | |
justifyContent: 'space-around' | |
}, | |
sliderCont: { | |
paddingTop: 5, | |
paddingHorizontal: 20 | |
} | |
}); | |
Settings.propTypes = propTypes; | |
const mapStateToProps = state => ({ app: state.app }); | |
const mapDispatchToProps = dispatch => ({ actions: bindActionCreators(APP.actions, dispatch) }); | |
export default connect(mapStateToProps, mapDispatchToProps)(Settings); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment