Skip to content

Commit c993662

Browse files
author
Nicholas Murray
authored
Merge pull request #6752 from Expensify/marcaaron-additionalDetailsFormFix
Update "Additional details" form in KYC wallet upgrade flow
2 parents 1c80150 + 8007892 commit c993662

File tree

6 files changed

+277
-115
lines changed

6 files changed

+277
-115
lines changed

src/ONYXKEYS.js

+3
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ export default {
118118
// Stores information about additional details form entry
119119
WALLET_ADDITIONAL_DETAILS: 'walletAdditionalDetails',
120120

121+
// Stores values put into the additional details step of the wallet KYC flow
122+
WALLET_ADDITIONAL_DETAILS_DRAFT: 'walletAdditionalDetailsDraft',
123+
121124
// Object containing Wallet terms step state
122125
WALLET_TERMS: 'walletTerms',
123126

src/components/AddressSearch.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ const propTypes = {
3030

3131
...withLocalizePropTypes,
3232
};
33+
3334
const defaultProps = {
3435
value: '',
35-
containerStyles: null,
36+
containerStyles: [],
3637
};
3738

3839
// Do not convert to class component! It's been tried before and presents more challenges than it's worth.

src/components/FormScrollView.js

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import {ScrollView} from 'react-native';
4+
import styles from '../styles/styles';
5+
6+
const propTypes = {
7+
/** Form elements */
8+
children: PropTypes.node.isRequired,
9+
};
10+
11+
const FormScrollView = React.forwardRef((props, ref) => (
12+
<ScrollView
13+
style={[styles.w100, styles.flex1]}
14+
ref={ref}
15+
contentContainerStyle={styles.flexGrow1}
16+
keyboardShouldPersistTaps="handled"
17+
// eslint-disable-next-line react/jsx-props-no-spreading
18+
{...props}
19+
>
20+
{props.children}
21+
</ScrollView>
22+
));
23+
24+
FormScrollView.propTypes = propTypes;
25+
export default FormScrollView;

src/libs/ValidationUtils.js

+1
Original file line numberDiff line numberDiff line change
@@ -316,4 +316,5 @@ export {
316316
isValidLengthForFirstOrLastName,
317317
isValidPaypalUsername,
318318
isValidRoutingNumber,
319+
isValidSSNLastFour,
319320
};

src/libs/actions/Wallet.js

+48-24
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,26 @@ function fetchOnfidoToken() {
2828
}
2929

3030
/**
31-
* Privately used to update the additionalDetails object in Onyx (which will have various effects on the UI)
32-
*
3331
* @param {Boolean} loading whether we are making the API call to validate the user's provided personal details
34-
* @param {String[]} [errorFields] an array of field names that should display errors in the UI
35-
* @param {String} [additionalErrorMessage] an additional error message to display in the UI
3632
* @private
3733
*/
38-
function setAdditionalDetailsStep(loading, errorFields = null, additionalErrorMessage = '') {
39-
Onyx.merge(ONYXKEYS.WALLET_ADDITIONAL_DETAILS, {loading, errorFields, additionalErrorMessage});
34+
function setAdditionalDetailsLoading(loading) {
35+
Onyx.merge(ONYXKEYS.WALLET_ADDITIONAL_DETAILS, {loading});
36+
}
37+
38+
/**
39+
* @param {Object} errorFields
40+
*/
41+
function setAdditionalDetailsErrors(errorFields) {
42+
Onyx.merge(ONYXKEYS.WALLET_ADDITIONAL_DETAILS, {errorFields: null});
43+
Onyx.merge(ONYXKEYS.WALLET_ADDITIONAL_DETAILS, {errorFields});
44+
}
45+
46+
/**
47+
* @param {String} additionalErrorMessage
48+
*/
49+
function setAdditionalDetailsErrorMessage(additionalErrorMessage) {
50+
Onyx.merge(ONYXKEYS.WALLET_ADDITIONAL_DETAILS, {additionalErrorMessage});
4051
}
4152

4253
/**
@@ -70,19 +81,9 @@ function activateWallet(currentStep, parameters) {
7081
onfidoData = parameters.onfidoData;
7182
Onyx.merge(ONYXKEYS.WALLET_ONFIDO, {error: '', loading: true});
7283
} else if (currentStep === CONST.WALLET.STEP.ADDITIONAL_DETAILS) {
73-
setAdditionalDetailsStep(true);
74-
75-
// Personal details are heavily validated on the API side. We will only do a quick check to ensure the values
76-
// exist in some capacity and then stringify them.
77-
const errorFields = _.reduce(CONST.WALLET.REQUIRED_ADDITIONAL_DETAILS_FIELDS, (missingFields, fieldName) => (
78-
!personalDetails[fieldName] ? [...missingFields, fieldName] : missingFields
79-
), []);
80-
81-
if (!_.isEmpty(errorFields)) {
82-
setAdditionalDetailsStep(false, errorFields);
83-
return;
84-
}
85-
84+
setAdditionalDetailsLoading(true);
85+
setAdditionalDetailsErrors(null);
86+
setAdditionalDetailsErrorMessage('');
8687
personalDetails = JSON.stringify(parameters.personalDetails);
8788
} else if (currentStep === CONST.WALLET.STEP.TERMS) {
8889
hasAcceptedTerms = parameters.hasAcceptedTerms;
@@ -104,7 +105,15 @@ function activateWallet(currentStep, parameters) {
104105

105106
if (currentStep === CONST.WALLET.STEP.ADDITIONAL_DETAILS) {
106107
if (response.title === CONST.WALLET.ERROR.MISSING_FIELD) {
107-
setAdditionalDetailsStep(false, response.data.fieldNames);
108+
// Errors for missing fields are returned from the API as an array of strings so we are converting this to an
109+
// object with field names as keys and boolean for values
110+
const errorFields = _.reduce(response.data.fieldNames, (errors, fieldName) => ({
111+
...errors,
112+
[fieldName]: true,
113+
}), {});
114+
setAdditionalDetailsLoading(false);
115+
setAdditionalDetailsErrors(errorFields);
116+
setAdditionalDetailsErrorMessage('');
108117
return;
109118
}
110119

@@ -116,11 +125,15 @@ function activateWallet(currentStep, parameters) {
116125
];
117126

118127
if (_.contains(errorTitles, response.title)) {
119-
setAdditionalDetailsStep(false, null, response.message);
128+
setAdditionalDetailsLoading(false);
129+
setAdditionalDetailsErrorMessage(response.message);
130+
setAdditionalDetailsErrors(null);
120131
return;
121132
}
122133

123-
setAdditionalDetailsStep(false);
134+
setAdditionalDetailsLoading(false);
135+
setAdditionalDetailsErrors(null);
136+
setAdditionalDetailsErrorMessage('');
124137
return;
125138
}
126139

@@ -132,7 +145,9 @@ function activateWallet(currentStep, parameters) {
132145
if (currentStep === CONST.WALLET.STEP.ONFIDO) {
133146
Onyx.merge(ONYXKEYS.WALLET_ONFIDO, {error: '', loading: true});
134147
} else if (currentStep === CONST.WALLET.STEP.ADDITIONAL_DETAILS) {
135-
setAdditionalDetailsStep(false);
148+
setAdditionalDetailsLoading(false);
149+
setAdditionalDetailsErrors(null);
150+
setAdditionalDetailsErrorMessage('');
136151
} else if (currentStep === CONST.WALLET.STEP.TERMS) {
137152
Onyx.merge(ONYXKEYS.WALLET_TERMS, {loading: false});
138153
}
@@ -159,9 +174,18 @@ function fetchUserWallet() {
159174
});
160175
}
161176

177+
/**
178+
* @param {Object} keyValuePair
179+
*/
180+
function updateAdditionalDetailsDraft(keyValuePair) {
181+
Onyx.merge(ONYXKEYS.WALLET_ADDITIONAL_DETAILS_DRAFT, keyValuePair);
182+
}
183+
162184
export {
163185
fetchOnfidoToken,
164-
setAdditionalDetailsStep,
165186
activateWallet,
166187
fetchUserWallet,
188+
setAdditionalDetailsErrors,
189+
updateAdditionalDetailsDraft,
190+
setAdditionalDetailsErrorMessage,
167191
};

0 commit comments

Comments
 (0)