Skip to content

Instantly share code, notes, and snippets.

@andybangs
Created January 13, 2017 19:34
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andybangs/79e46c58432aaaea92d030f8d415aded to your computer and use it in GitHub Desktop.
Save andybangs/79e46c58432aaaea92d030f8d415aded to your computer and use it in GitHub Desktop.
Example Component
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