Skip to content

Commit

Permalink
Merge pull request #30576 from MrMuzyk/michal/personal-info-page
Browse files Browse the repository at this point in the history
feat: PersonalInfo Step
  • Loading branch information
mountiny authored Nov 7, 2023
2 parents 7d807c7 + 47553da commit 4cd72c8
Show file tree
Hide file tree
Showing 20 changed files with 882 additions and 191 deletions.
12 changes: 12 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,18 @@ const CONST = {
DOMAIN: '@expensify.sms',
},
BANK_ACCOUNT: {
PERSONAL_INFO_STEP: {
INPUT_KEY: {
FIRST_NAME: 'firstName',
LAST_NAME: 'lastName',
DOB: 'dob',
SSN_LAST_4: 'ssnLast4',
STREET: 'requestorAddressStreet',
CITY: 'requestorAddressCity',
STATE: 'requestorAddressState',
ZIP_CODE: 'requestorAddressZipCode',
},
},
PLAID: {
ALLOWED_THROTTLED_COUNT: 2,
ERROR: {
Expand Down
24 changes: 22 additions & 2 deletions src/components/Form/FormWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ const propTypes = {
/** Container styles */
style: stylePropTypes,

/** Submit button container styles */
// eslint-disable-next-line react/forbid-prop-types
submitButtonStyles: PropTypes.arrayOf(PropTypes.object),

/** Custom content to display in the footer after submit button */
footerContent: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),

Expand All @@ -74,10 +78,25 @@ const defaultProps = {
scrollContextEnabled: false,
footerContent: null,
style: [],
submitButtonStyles: [],
};

function FormWrapper(props) {
const {onSubmit, children, formState, errors, inputRefs, submitButtonText, footerContent, isSubmitButtonVisible, style, enabledWhenOffline, isSubmitActionDangerous, formID} = props;
const {
onSubmit,
children,
formState,
errors,
inputRefs,
submitButtonText,
footerContent,
isSubmitButtonVisible,
style,
enabledWhenOffline,
isSubmitActionDangerous,
formID,
submitButtonStyles,
} = props;
const formRef = useRef(null);
const formContentRef = useRef(null);
const errorMessage = useMemo(() => {
Expand Down Expand Up @@ -129,7 +148,7 @@ function FormWrapper(props) {
focusInput.focus();
}
}}
containerStyles={[styles.mh0, styles.mt5, styles.flex1]}
containerStyles={[styles.mh0, styles.mt5, styles.flex1, ...submitButtonStyles]}
enabledWhenOffline={enabledWhenOffline}
isSubmitActionDangerous={isSubmitActionDangerous}
disablePressOnEnter
Expand All @@ -150,6 +169,7 @@ function FormWrapper(props) {
isSubmitActionDangerous,
isSubmitButtonVisible,
onSubmit,
submitButtonStyles,
style,
submitButtonText,
],
Expand Down
15 changes: 7 additions & 8 deletions src/components/InteractiveStepSubHeader.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import React, {forwardRef, useState, useImperativeHandle} from 'react';
import PropTypes from 'prop-types';
import map from 'lodash/map';
import PropTypes from 'prop-types';
import React, {forwardRef, useImperativeHandle, useState} from 'react';
import {View} from 'react-native';

import CONST from '../CONST';
import variables from '../styles/variables';
import styles from '../styles/styles';
import colors from '../styles/colors';
import colors from '@styles/colors';
import styles from '@styles/styles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import Icon from './Icon';
import * as Expensicons from './Icon/Expensicons';
import PressableWithFeedback from './Pressable/PressableWithFeedback';
import Text from './Text';
import Icon from './Icon';

const propTypes = {
/** List of the Route Name to navigate when the step is selected */
Expand Down
36 changes: 34 additions & 2 deletions src/components/NewDatePicker/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import TextInput from '@components/TextInput';
import {propTypes as baseTextInputPropTypes, defaultProps as defaultBaseTextInputPropTypes} from '@components/TextInput/baseTextInputPropTypes';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import styles from '@styles/styles';
import * as FormActions from '@userActions/FormActions';
import CONST from '@src/CONST';
import CalendarPicker from './CalendarPicker';

Expand All @@ -33,6 +34,12 @@ const propTypes = {
/** A maximum date of calendar to select */
maxDate: PropTypes.objectOf(Date),

/** Saves a draft of the input value when used in a form */
shouldSaveDraft: PropTypes.bool,

/** ID of the wrapping form */
formID: PropTypes.string,

...withLocalizePropTypes,
...baseTextInputPropTypes,
};
Expand All @@ -42,17 +49,42 @@ const datePickerDefaultProps = {
minDate: setYear(new Date(), CONST.CALENDAR_PICKER.MIN_YEAR),
maxDate: setYear(new Date(), CONST.CALENDAR_PICKER.MAX_YEAR),
value: undefined,
shouldSaveDraft: false,
formID: '',
};

function NewDatePicker({containerStyles, defaultValue, disabled, errorText, inputID, isSmallScreenWidth, label, maxDate, minDate, onInputChange, onTouched, placeholder, translate, value}) {
function NewDatePicker({
containerStyles,
defaultValue,
disabled,
errorText,
inputID,
isSmallScreenWidth,
label,
maxDate,
minDate,
onInputChange,
onTouched,
placeholder,
translate,
value,
shouldSaveDraft,
formID,
}) {
const [selectedDate, setSelectedDate] = useState(value || defaultValue || undefined);

useEffect(() => {
// Value is provided to input via props and onChange never fires. We have to save draft manually.
if (shouldSaveDraft && formID !== '') {
FormActions.setDraftValues(formID, {[inputID]: selectedDate});
}

if (selectedDate === value || _.isUndefined(value)) {
return;
}

setSelectedDate(value);
}, [selectedDate, value]);
}, [formID, inputID, selectedDate, shouldSaveDraft, value]);

useEffect(() => {
if (_.isFunction(onTouched)) {
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useSubStep.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {useState, useRef, useCallback} from 'react';
import PropTypes from 'prop-types';
import {useCallback, useRef, useState} from 'react';

const propTypes = {
/** an array of substep components */
Expand Down
18 changes: 17 additions & 1 deletion src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ export default {
noPO: 'PO boxes and mail drop addresses are not allowed',
city: 'City',
state: 'State',
streetAddress: 'Street address',
stateOrProvince: 'State / Province',
country: 'Country',
zip: 'Zip code',
Expand Down Expand Up @@ -266,6 +267,7 @@ export default {
tbd: 'TBD',
selectCurrency: 'Select a currency',
card: 'Card',
whyDoWeAskForThis: 'Why do we ask for this?',
},
location: {
useCurrent: 'Use current location',
Expand Down Expand Up @@ -1347,13 +1349,27 @@ export default {
},
requestorStep: {
headerTitle: 'Personal information',
subtitle: 'Please provide your personal information.',
learnMore: 'Learn more',
isMyDataSafe: 'Is my data safe?',
onFidoConditions: 'By continuing with the request to add this bank account, you confirm that you have read, understand and accept ',
isControllingOfficer: 'I am authorized to use my company bank account for business spend',
isControllingOfficerError: 'You must be a controlling officer with authorization to operate the business bank account.',
},
personalInfoStep: {
personalInfo: 'Personal info',
enterYourLegalFirstAndLast: 'Enter your legal first and last name.',
legalFirstName: 'Legal first name',
legalLastName: 'Legal last name',
legalName: 'Legal name',
enterYourDateOfBirth: 'Enter your date of birth.',
enterTheLast4: 'Enter the last 4 of your SSN.',
dontWorry: "Don't worry, we don't do any personal credit checks!",
last4SSN: 'Last 4 Social Security Number',
enterYourAddress: 'Enter your address.',
address: 'Address',
letsDoubleCheck: "Let's double check everything looks right",
byAddingThisBankAccount: 'By adding this bank account, you confirm that you have read, understand and accept',
},
validationStep: {
headerTitle: 'Validate Bank Account',
buttonText: 'Finish setup',
Expand Down
18 changes: 17 additions & 1 deletion src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ export default {
noPO: 'No se aceptan apartados ni direcciones postales',
city: 'Ciudad',
state: 'Estado',
streetAddress: 'Dirección',
stateOrProvince: 'Estado / Provincia',
country: 'País',
zip: 'Código postal',
Expand Down Expand Up @@ -256,6 +257,7 @@ export default {
tbd: 'Por determinar',
selectCurrency: 'Selecciona una moneda',
card: 'Tarjeta',
whyDoWeAskForThis: '¿Por qué pedimos esto?',
},
location: {
useCurrent: 'Usar ubicación actual',
Expand Down Expand Up @@ -1366,13 +1368,27 @@ export default {
},
requestorStep: {
headerTitle: 'Información personal',
subtitle: 'Dé más información sobre tí.',
learnMore: 'Más información',
isMyDataSafe: '¿Están seguros mis datos?',
onFidoConditions: 'Al continuar con la solicitud de añadir esta cuenta bancaria, confirma que ha leído, entiende y acepta ',
isControllingOfficer: 'Estoy autorizado a utilizar la cuenta bancaria de mi compañía para gastos de empresa',
isControllingOfficerError: 'Debe ser un oficial controlador con autorización para operar la cuenta bancaria de la compañía',
},
personalInfoStep: {
personalInfo: 'Información Personal',
enterYourLegalFirstAndLast: 'Ingrese su Nombre y Apellido',
legalFirstName: 'Nombre',
legalLastName: 'Apellido',
legalName: 'Nombre legal',
enterYourDateOfBirth: 'Ingrese su fecha de Cumple años',
enterTheLast4: 'Ingrese los últimos 4 dígitos de su NSS',
dontWorry: 'No se preocupe, no hacemos ninguna verificación de créditos',
last4SSN: 'Últimos 4 dígitos de su Número de Seguro Social',
enterYourAddress: 'Ingrese su dirección',
address: 'Dirección',
letsDoubleCheck: 'Revisemos que todo esté bien',
byAddingThisBankAccount: 'Agregando esta cuenta bancaria, confirmas que as leído, entendido y aceptado',
},
validationStep: {
headerTitle: 'Validar cuenta bancaria',
buttonText: 'Finalizar configuración',
Expand Down
2 changes: 0 additions & 2 deletions src/pages/ReimbursementAccount/AddressForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ function AddressForm(props) {
defaultValue={props.defaultValues.street}
onInputChange={props.onFieldChange}
errorText={props.errors.street ? props.translate('bankAccount.error.addressStreet') : ''}
hint={props.translate('common.noPO')}
renamedInputKeys={props.inputKeys}
maxInputLength={CONST.FORM_CHARACTER_LIMIT}
isLimitedToUSA
Expand Down Expand Up @@ -145,7 +144,6 @@ function AddressForm(props) {
onChangeText={(value) => props.onFieldChange({zipCode: value})}
errorText={props.errors.zipCode ? props.translate('bankAccount.error.zipCode') : ''}
maxLength={CONST.BANK_ACCOUNT.MAX_LENGTH.ZIP_CODE}
hint={props.translate('common.zipCodeExampleFormat', {zipSampleFormat: CONST.COUNTRY_ZIP_REGEX_DATA.US.samples})}
containerStyles={[styles.mt2]}
/>
</>
Expand Down
51 changes: 51 additions & 0 deletions src/pages/ReimbursementAccount/PersonalInfo/HelpLinks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import PropTypes from 'prop-types';
import React from 'react';
import {View} from 'react-native';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import styles from '@styles/styles';
import CONST from '@src/CONST';

const propTypes = {
/** Style for wrapping View */
// eslint-disable-next-line react/forbid-prop-types
containerStyles: PropTypes.arrayOf(PropTypes.object),

/** Translate function */
translate: PropTypes.func.isRequired,
};

const defaultProps = {
containerStyles: [],
};

function HelpLinks({containerStyles, translate}) {
return (
<View style={[styles.flexRow, styles.alignItemsCenter, containerStyles]}>
<Icon src={Expensicons.QuestionMark} />
<View style={[styles.ml2, styles.dFlex, styles.flexRow]}>
<TextLink
style={[styles.textMicro]}
href={CONST.BANK_ACCOUNT_PERSONAL_DOCUMENTATION_INFO_URL}
>
{translate('requestorStep.learnMore')}
</TextLink>
<Text style={[styles.textMicroSupporting]}>{' | '}</Text>
<TextLink
style={[styles.textMicro, styles.textLink]}
href={CONST.PERSONAL_DATA_PROTECTION_INFO_URL}
>
{translate('requestorStep.isMyDataSafe')}
</TextLink>
</View>
</View>
);
}

HelpLinks.displayName = 'HelpLinks';
HelpLinks.propTypes = propTypes;
HelpLinks.defaultProps = defaultProps;

export default HelpLinks;
Loading

0 comments on commit 4cd72c8

Please sign in to comment.