Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor User_AddBillingCard in App #9648

Merged
merged 17 commits into from
Aug 11, 2022
Merged
2 changes: 1 addition & 1 deletion contributingGuides/FORMS.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ function validate(values) {
function onSubmit(values) {
setTimeout(() => {
alert(`Form submitted!`);
FormActions.setIsSubmitting('TestForm', false);
FormActions.setIsLoading('TestForm', false);
}, 1000);
}

Expand Down
20 changes: 10 additions & 10 deletions src/components/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ const propTypes = {
formState: PropTypes.shape({

/** Controls the loading state of the form */
isSubmitting: PropTypes.bool,
isLoading: PropTypes.bool,

/** Server side error message */
serverErrorMessage: PropTypes.string,
error: PropTypes.string,
}),

/** Contains draft values for each input in the form */
Expand All @@ -45,8 +45,8 @@ const propTypes = {

const defaultProps = {
formState: {
isSubmitting: false,
serverErrorMessage: '',
isLoading: false,
error: '',
},
draftValues: {},
};
Expand Down Expand Up @@ -77,7 +77,7 @@ class Form extends React.Component {

submit() {
// Return early if the form is already submitting to avoid duplicate submission
if (this.props.formState.isSubmitting) {
if (this.props.formState.isLoading) {
return;
}

Expand All @@ -92,7 +92,7 @@ class Form extends React.Component {
}

// Set loading state and call submit handler
FormActions.setIsSubmitting(this.props.formID, true);
FormActions.setIsLoading(this.props.formID, true);
this.props.onSubmit(this.inputValues);
}

Expand All @@ -101,7 +101,7 @@ class Form extends React.Component {
* @returns {Object} - An object containing the errors for each inputID, e.g. {inputID1: error1, inputID2: error2}
*/
validate(values) {
FormActions.setServerErrorMessage(this.props.formID, '');
FormActions.setErrorMessage(this.props.formID, '');
const validationErrors = this.props.validate(values);

if (!_.isObject(validationErrors)) {
Expand Down Expand Up @@ -187,9 +187,9 @@ class Form extends React.Component {
{this.childrenWrapperWithProps(this.props.children)}
<FormAlertWithSubmitButton
buttonText={this.props.submitButtonText}
isAlertVisible={_.size(this.state.errors) > 0 || Boolean(this.props.formState.serverErrorMessage)}
isLoading={this.props.formState.isSubmitting}
message={this.props.formState.serverErrorMessage}
isAlertVisible={_.size(this.state.errors) > 0 || Boolean(this.props.formState.error)}
isLoading={this.props.formState.isLoading}
message={this.props.formState.error}
onSubmit={this.submit}
onFixTheErrorsLinkPressed={() => {
this.inputRefs[_.first(_.keys(this.state.errors))].focus();
Expand Down
16 changes: 8 additions & 8 deletions src/libs/actions/FormActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ import Onyx from 'react-native-onyx';

/**
* @param {String} formID
* @param {Boolean} isSubmitting
* @param {Boolean} isLoading
*/
function setIsSubmitting(formID, isSubmitting) {
Onyx.merge(formID, {isSubmitting});
function setIsLoading(formID, isLoading) {
Onyx.merge(formID, {isLoading});
}

/**
* @param {String} formID
* @param {Boolean} serverErrorMessage
* @param {String} error
*/
function setServerErrorMessage(formID, serverErrorMessage) {
Onyx.merge(formID, {serverErrorMessage});
function setErrorMessage(formID, error) {
Onyx.merge(formID, {error});
}

/**
Expand All @@ -25,7 +25,7 @@ function setDraftValues(formID, draftValues) {
}

export {
setIsSubmitting,
setServerErrorMessage,
setIsLoading,
setErrorMessage,
setDraftValues,
};
57 changes: 22 additions & 35 deletions src/libs/actions/PaymentMethods.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,11 @@ function makeDefaultPaymentMethod(password, bankAccountID, fundID, previousPayme
*
* @param {Object} params
*/
function addBillingCard(params) {
function addPaymentCard(params) {
const cardMonth = CardUtils.getMonthFromExpirationDateString(params.expirationDate);
const cardYear = CardUtils.getYearFromExpirationDateString(params.expirationDate);

DeprecatedAPI.AddBillingCard({
API.write('AddPaymentCard', {
cardNumber: params.cardNumber,
cardYear,
cardMonth,
Expand All @@ -189,45 +189,32 @@ function addBillingCard(params) {
currency: CONST.CURRENCY.USD,
isP2PDebitCard: true,
password: params.password,
}).then(((response) => {
let serverErrorMessage = '';
if (response.jsonCode === 200) {
const cardObject = {
additionalData: {
isBillingCard: false,
isP2PDebitCard: true,
},
addressName: params.nameOnCard,
addressState: params.addressState,
addressStreet: params.addressStreet,
addressZip: params.addressZipCode,
cardMonth,
cardNumber: CardUtils.maskCardNumber(params.cardNumber),
cardYear,
currency: 'USD',
fundID: lodashGet(response, 'fundID', ''),
};
Onyx.merge(ONYXKEYS.CARD_LIST, [cardObject]);
Growl.show(Localize.translateLocal('addDebitCardPage.growlMessageOnSave'), CONST.GROWL.SUCCESS, 3000);
continueSetup();
} else {
serverErrorMessage = response.message ? response.message : Localize.translateLocal('addDebitCardPage.error.genericFailureMessage');
}

Onyx.merge(ONYXKEYS.FORMS.ADD_DEBIT_CARD_FORM, {
isSubmitting: false,
serverErrorMessage,
});
}));
}, {
optimisticData: [{
onyxMethod: 'merge',
key: ONYXKEYS.FORMS.ADD_DEBIT_CARD_FORM,
value: {isLoading: true},
}],
successData: [{
onyxMethod: 'merge',
key: ONYXKEYS.FORMS.ADD_DEBIT_CARD_FORM,
value: {isLoading: false},
}],
failureData: [{
onyxMethod: 'merge',
key: ONYXKEYS.FORMS.ADD_DEBIT_CARD_FORM,
value: {isLoading: false},
}],
});
}

/**
* Resets the values for the add debit card form back to their initial states
*/
function clearDebitCardFormErrorAndSubmit() {
Onyx.set(ONYXKEYS.FORMS.ADD_DEBIT_CARD_FORM, {
isSubmitting: false,
serverErrorMessage: null,
isLoading: false,
error: null,
});
}

Expand Down Expand Up @@ -315,9 +302,9 @@ export {
deleteDebitCard,
deletePayPalMe,
getPaymentMethods,
addPaymentCard,
openPaymentsPage,
makeDefaultPaymentMethod,
addBillingCard,
kycWallRef,
continueSetup,
clearDebitCardFormErrorAndSubmit,
Expand Down
10 changes: 0 additions & 10 deletions src/libs/deprecatedAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,6 @@ Request.use(Middleware.Retry);
// SaveResponseInOnyx - Merges either the successData or failureData into Onyx depending on if the call was successful or not
Request.use(Middleware.SaveResponseInOnyx);

/**
* @param {Object} parameters
* @returns {Promise}
*/
function AddBillingCard(parameters) {
const commandName = 'User_AddBillingCard';
return Network.post(commandName, parameters, CONST.NETWORK.METHOD.POST, true);
}

/**
* @param {{password: String, oldPassword: String}} parameters
* @param {String} parameters.authToken
Expand Down Expand Up @@ -682,7 +673,6 @@ function GetStatementPDF(parameters) {
}

export {
AddBillingCard,
BankAccount_SetupWithdrawal,
BankAccount_Validate,
ChangePassword,
Expand Down
35 changes: 32 additions & 3 deletions src/pages/settings/Payments/AddDebitCardPage.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import React, {Component} from 'react';
import {View} from 'react-native';
import _ from 'underscore';
import {withOnyx} from 'react-native-onyx';
import PropTypes from 'prop-types';
import compose from '../../../libs/compose';
import HeaderWithCloseButton from '../../../components/HeaderWithCloseButton';
import Navigation from '../../../libs/Navigation/Navigation';
import ScreenWrapper from '../../../components/ScreenWrapper';
Expand All @@ -21,16 +24,34 @@ import Form from '../../../components/Form';

const propTypes = {
/* Onyx Props */
formData: PropTypes.shape({
setupComplete: PropTypes.boolean,
}),

...withLocalizePropTypes,
};

const defaultProps = {
formData: {
setupComplete: false,
},
};

class DebitCardPage extends Component {
constructor(props) {
super(props);

this.validate = this.validate.bind(this);
}

componentDidUpdate(prevProps) {
if (prevProps.formData.setupComplete || !this.props.formData.setupComplete) {
return;
}

PaymentMethods.continueSetup();
}

/**
* Make sure we reset the onyx values so old errors don't show if this form is displayed later
*/
Expand Down Expand Up @@ -96,7 +117,7 @@ class DebitCardPage extends Component {
<Form
formID={ONYXKEYS.FORMS.ADD_DEBIT_CARD_FORM}
validate={this.validate}
onSubmit={PaymentMethods.addBillingCard}
onSubmit={PaymentMethods.addPaymentCard}
submitButtonText={this.props.translate('common.save')}
style={[styles.mh5, styles.flexGrow1]}
>
Expand Down Expand Up @@ -179,5 +200,13 @@ class DebitCardPage extends Component {
}

DebitCardPage.propTypes = propTypes;

export default withLocalize(DebitCardPage);
DebitCardPage.defaultProps = defaultProps;

export default compose(
withLocalize,
withOnyx({
formData: {
key: ONYXKEYS.FORMS.ADD_DEBIT_CARD_FORM,
},
}),
)(DebitCardPage);
18 changes: 9 additions & 9 deletions src/stories/Form.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ const story = {
const Template = (args) => {
// Form consumes data from Onyx, so we initialize Onyx with the necessary data here
NetworkConnection.setOfflineStatus(false);
FormActions.setIsSubmitting(args.formID, args.formState.isSubmitting);
FormActions.setServerErrorMessage(args.formID, args.formState.serverErrorMessage);
FormActions.setIsLoading(args.formID, args.formState.isLoading);
FormActions.setErrorMessage(args.formID, args.formState.error);
FormActions.setDraftValues(args.formID, args.draftValues);

return (
Expand Down Expand Up @@ -131,8 +131,8 @@ const WithNativeEventHandler = (args) => {

// Form consumes data from Onyx, so we initialize Onyx with the necessary data here
NetworkConnection.setOfflineStatus(false);
FormActions.setIsSubmitting(args.formID, args.formState.isSubmitting);
FormActions.setServerErrorMessage(args.formID, args.formState.serverErrorMessage);
FormActions.setIsLoading(args.formID, args.formState.isLoading);
FormActions.setErrorMessage(args.formID, args.formState.error);
FormActions.setDraftValues(args.formID, args.draftValues);

return (
Expand Down Expand Up @@ -192,12 +192,12 @@ const defaultArgs = {
onSubmit: (values) => {
setTimeout(() => {
alert(`Form submitted!\n\nInput values: ${JSON.stringify(values, null, 4)}`);
FormActions.setIsSubmitting('TestForm', false);
FormActions.setIsLoading('TestForm', false);
}, 1000);
},
formState: {
isSubmitting: false,
serverErrorMessage: '',
isLoading: false,
error: '',
},
draftValues: {
routingNumber: '00001',
Expand All @@ -212,8 +212,8 @@ const defaultArgs = {
};

Default.args = defaultArgs;
Loading.args = {...defaultArgs, formState: {isSubmitting: true}};
ServerError.args = {...defaultArgs, formState: {isSubmitting: false, serverErrorMessage: 'There was an unexpected error. Please try again later.'}};
Loading.args = {...defaultArgs, formState: {isLoading: true}};
ServerError.args = {...defaultArgs, formState: {isLoading: false, error: 'There was an unexpected error. Please try again later.'}};
InputError.args = {
...defaultArgs,
draftValues: {
Expand Down