Skip to content

Commit d8a5519

Browse files
committed
Merge branch 'mkzie2-issue/55688' of https://github.com/mkzie2/App into mkzie2-issue/55688
2 parents 3addd36 + 9ca4629 commit d8a5519

File tree

6 files changed

+127
-99
lines changed

6 files changed

+127
-99
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import React, {useMemo} from 'react';
2+
import SelectionList from '@components/SelectionList';
3+
import RadioListItem from '@components/SelectionList/RadioListItem';
4+
import type {ValueSelectionListProps} from './types';
5+
6+
function ValueSelectionList({items = [], selectedItem, onItemSelected, shouldShowTooltips = true}: ValueSelectionListProps) {
7+
const sections = useMemo(
8+
() => [{data: items.map((item) => ({value: item.value, alternateText: item.description, text: item.label ?? '', isSelected: item === selectedItem, keyForList: item.value ?? ''}))}],
9+
[items, selectedItem],
10+
);
11+
12+
return (
13+
<SelectionList
14+
sections={sections}
15+
onSelectRow={(item) => onItemSelected?.(item)}
16+
initiallyFocusedOptionKey={selectedItem?.value}
17+
shouldStopPropagation
18+
shouldShowTooltips={shouldShowTooltips}
19+
shouldUpdateFocusedIndex
20+
ListItem={RadioListItem}
21+
/>
22+
);
23+
}
24+
25+
ValueSelectionList.displayName = 'ValueSelectionList';
26+
27+
export default ValueSelectionList;

src/components/ValuePicker/ValueSelectorModal.tsx

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
import React, {useMemo} from 'react';
1+
import React from 'react';
22
import HeaderWithBackButton from '@components/HeaderWithBackButton';
33
import Modal from '@components/Modal';
44
import ScreenWrapper from '@components/ScreenWrapper';
5-
import SelectionList from '@components/SelectionList';
6-
import RadioListItem from '@components/SelectionList/RadioListItem';
75
import useThemeStyles from '@hooks/useThemeStyles';
86
import CONST from '@src/CONST';
97
import type {ValueSelectorModalProps} from './types';
8+
import ValueSelectionList from './ValueSelectionList';
109

1110
function ValueSelectorModal({
1211
items = [],
@@ -21,11 +20,6 @@ function ValueSelectorModal({
2120
}: ValueSelectorModalProps) {
2221
const styles = useThemeStyles();
2322

24-
const sections = useMemo(
25-
() => [{data: items.map((item) => ({value: item.value, alternateText: item.description, text: item.label ?? '', isSelected: item === selectedItem, keyForList: item.value ?? ''}))}],
26-
[items, selectedItem],
27-
);
28-
2923
return (
3024
<Modal
3125
type={CONST.MODAL.MODAL_TYPE.RIGHT_DOCKED}
@@ -47,13 +41,11 @@ function ValueSelectorModal({
4741
title={label}
4842
onBackButtonPress={onClose}
4943
/>
50-
<SelectionList
51-
sections={sections}
52-
onSelectRow={(item) => onItemSelected?.(item)}
53-
initiallyFocusedOptionKey={selectedItem?.value}
54-
shouldStopPropagation
44+
<ValueSelectionList
45+
items={items}
46+
selectedItem={selectedItem}
47+
onItemSelected={onItemSelected}
5548
shouldShowTooltips={shouldShowTooltips}
56-
ListItem={RadioListItem}
5749
/>
5850
</ScreenWrapper>
5951
</Modal>

src/components/ValuePicker/index.tsx

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@ import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
55
import Navigation from '@libs/Navigation/Navigation';
66
import CONST from '@src/CONST';
77
import type {ValuePickerItem, ValuePickerProps} from './types';
8+
import ValueSelectionList from './ValueSelectionList';
89
import ValueSelectorModal from './ValueSelectorModal';
910

10-
function ValuePicker({value, label, items, placeholder = '', errorText = '', onInputChange, furtherDetails, shouldShowTooltips = true}: ValuePickerProps, forwardedRef: ForwardedRef<View>) {
11+
function ValuePicker(
12+
{value, label, items, placeholder = '', errorText = '', onInputChange, furtherDetails, shouldShowTooltips = true, shouldShowModal = true}: ValuePickerProps,
13+
forwardedRef: ForwardedRef<View>,
14+
) {
1115
const [isPickerVisible, setIsPickerVisible] = useState(false);
1216

1317
const showPickerModal = () => {
@@ -29,28 +33,39 @@ function ValuePicker({value, label, items, placeholder = '', errorText = '', onI
2933

3034
return (
3135
<View>
32-
<MenuItemWithTopDescription
33-
ref={forwardedRef}
34-
shouldShowRightIcon
35-
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
36-
title={selectedItem?.label || placeholder || ''}
37-
description={label}
38-
onPress={showPickerModal}
39-
furtherDetails={furtherDetails}
40-
brickRoadIndicator={errorText ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
41-
errorText={errorText}
42-
/>
43-
<ValueSelectorModal
44-
isVisible={isPickerVisible}
45-
label={label}
46-
selectedItem={selectedItem}
47-
items={items}
48-
onClose={hidePickerModal}
49-
onItemSelected={updateInput}
50-
shouldShowTooltips={shouldShowTooltips}
51-
onBackdropPress={Navigation.dismissModal}
52-
shouldEnableKeyboardAvoidingView={false}
53-
/>
36+
{shouldShowModal ? (
37+
<>
38+
<MenuItemWithTopDescription
39+
ref={forwardedRef}
40+
shouldShowRightIcon
41+
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
42+
title={selectedItem?.label || placeholder || ''}
43+
description={label}
44+
onPress={showPickerModal}
45+
furtherDetails={furtherDetails}
46+
brickRoadIndicator={errorText ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
47+
errorText={errorText}
48+
/>
49+
<ValueSelectorModal
50+
isVisible={isPickerVisible}
51+
label={label}
52+
selectedItem={selectedItem}
53+
items={items}
54+
onClose={hidePickerModal}
55+
onItemSelected={updateInput}
56+
shouldShowTooltips={shouldShowTooltips}
57+
onBackdropPress={Navigation.dismissModal}
58+
shouldEnableKeyboardAvoidingView={false}
59+
/>
60+
</>
61+
) : (
62+
<ValueSelectionList
63+
items={items}
64+
selectedItem={selectedItem}
65+
onItemSelected={updateInput}
66+
shouldShowTooltips={shouldShowTooltips}
67+
/>
68+
)}
5469
</View>
5570
);
5671
}

src/components/ValuePicker/types.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ type ValueSelectorModalProps = {
3939
shouldEnableKeyboardAvoidingView?: boolean;
4040
};
4141

42+
type ValueSelectionListProps = Pick<ValueSelectorModalProps, 'items' | 'selectedItem' | 'onItemSelected' | 'shouldShowTooltips'>;
43+
4244
type ValuePickerProps = {
4345
/** Item to display */
4446
value?: string;
@@ -63,6 +65,9 @@ type ValuePickerProps = {
6365

6466
/** Whether to show the tooltip text */
6567
shouldShowTooltips?: boolean;
68+
69+
/** Whether to show the selector modal */
70+
shouldShowModal?: boolean;
6671
};
6772

68-
export type {ValuePickerItem, ValueSelectorModalProps, ValuePickerProps, ValuePickerListItem};
73+
export type {ValuePickerItem, ValueSelectorModalProps, ValuePickerProps, ValuePickerListItem, ValueSelectionListProps};

src/libs/actions/FormActions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function clearErrorFields(formID: OnyxFormKey) {
2424
}
2525

2626
function setDraftValues(formID: OnyxFormKey, draftValues: NullishDeep<OnyxValue<OnyxFormDraftKey>>) {
27-
Onyx.merge(`${formID}Draft`, draftValues ?? null);
27+
return Onyx.merge(`${formID}Draft`, draftValues ?? null);
2828
}
2929

3030
function clearDraftValues(formID: OnyxFormKey) {

src/pages/settings/Wallet/InternationalDepositAccount/substeps/AccountType.tsx

Lines changed: 49 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,84 @@
1-
import React, {useCallback, useMemo, useState} from 'react';
1+
import React, {useCallback, useMemo, useRef} from 'react';
22
import {View} from 'react-native';
3-
import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton';
4-
import SelectionList from '@components/SelectionList';
5-
import RadioListItem from '@components/SelectionList/RadioListItem';
3+
import FormProvider from '@components/Form/FormProvider';
4+
import InputWrapper from '@components/Form/InputWrapper';
5+
import type {FormInputErrors, FormOnyxValues, FormRef} from '@components/Form/types';
6+
import ValuePicker from '@components/ValuePicker';
7+
import useInternationalBankAccountFormSubmit from '@hooks/useInternationalBankAccountFormSubmit';
68
import useLocalize from '@hooks/useLocalize';
79
import useThemeStyles from '@hooks/useThemeStyles';
8-
import type {Option} from '@libs/searchOptions';
10+
import {setDraftValues} from '@libs/actions/FormActions';
911
import type {CustomSubStepProps} from '@pages/settings/Wallet/InternationalDepositAccount/types';
10-
import {setDraftValues} from '@userActions/FormActions';
1112
import Text from '@src/components/Text';
1213
import CONST from '@src/CONST';
13-
import type {TranslationPaths} from '@src/languages/types';
1414
import ONYXKEYS from '@src/ONYXKEYS';
1515

16-
function AccountType({isEditing, onNext, formValues, fieldsMap}: CustomSubStepProps) {
16+
function AccountType({isEditing, onNext, fieldsMap}: CustomSubStepProps) {
1717
const {translate} = useLocalize();
1818
const styles = useThemeStyles();
19-
const [currentAccountType, setCurrentAccountType] = useState(formValues[CONST.CORPAY_FIELDS.ACCOUNT_TYPE_KEY]);
20-
const [error, setError] = useState<TranslationPaths | undefined>(undefined);
19+
const formRef = useRef<FormRef>(null);
2120

2221
const fieldData = fieldsMap[CONST.CORPAY_FIELDS.STEPS_NAME.ACCOUNT_TYPE]?.[CONST.CORPAY_FIELDS.ACCOUNT_TYPE_KEY] ?? {};
2322

24-
const onAccountTypeSelected = useCallback(() => {
25-
setError(undefined);
26-
if (isEditing && formValues[CONST.CORPAY_FIELDS.ACCOUNT_TYPE_KEY] === currentAccountType) {
27-
onNext();
28-
return;
29-
}
30-
if (fieldData.isRequired && !currentAccountType) {
31-
setError('common.error.pleaseSelectOne');
32-
return;
33-
}
34-
setDraftValues(ONYXKEYS.FORMS.INTERNATIONAL_BANK_ACCOUNT_FORM, {[CONST.CORPAY_FIELDS.ACCOUNT_TYPE_KEY]: currentAccountType});
35-
onNext();
36-
}, [currentAccountType, fieldData.isRequired, formValues, isEditing, onNext]);
23+
const handleSubmit = useInternationalBankAccountFormSubmit({
24+
fieldIds: Object.keys(fieldsMap[CONST.CORPAY_FIELDS.STEPS_NAME.ACCOUNT_TYPE]),
25+
onNext,
26+
shouldSaveDraft: isEditing,
27+
});
3728

38-
const onSelectionChange = useCallback(
39-
(country: Option) => {
40-
if (!isEditing) {
41-
setDraftValues(ONYXKEYS.FORMS.INTERNATIONAL_BANK_ACCOUNT_FORM, {[CONST.CORPAY_FIELDS.ACCOUNT_TYPE_KEY]: country.value});
29+
const validate = useCallback(
30+
(values: FormOnyxValues<typeof ONYXKEYS.FORMS.INTERNATIONAL_BANK_ACCOUNT_FORM>): FormInputErrors<typeof ONYXKEYS.FORMS.INTERNATIONAL_BANK_ACCOUNT_FORM> => {
31+
if (!fieldData.isRequired || values[CONST.CORPAY_FIELDS.ACCOUNT_TYPE_KEY]) {
32+
return {};
4233
}
43-
setCurrentAccountType(country.value);
34+
return {[CONST.CORPAY_FIELDS.ACCOUNT_TYPE_KEY]: translate('common.error.pleaseSelectOne')};
4435
},
45-
[isEditing],
36+
[fieldData.isRequired, translate],
4637
);
4738

4839
const options = useMemo(
4940
() =>
5041
(fieldData.valueSet ?? []).map((item) => {
5142
return {
5243
value: item.id,
53-
keyForList: item.id,
54-
text: item.text,
55-
isSelected: currentAccountType === item.id,
56-
searchValue: item.text,
44+
label: item.text,
5745
};
5846
}),
59-
[fieldData.valueSet, currentAccountType],
47+
[fieldData.valueSet],
6048
);
6149

62-
const button = useMemo(() => {
63-
const buttonText = isEditing ? translate('common.confirm') : translate('common.next');
64-
return (
65-
<FormAlertWithSubmitButton
66-
message={error ? translate(error) : ''}
67-
isAlertVisible={!!error}
68-
buttonText={buttonText}
69-
onSubmit={onAccountTypeSelected}
70-
containerStyles={[styles.flexReset, styles.flexGrow0, styles.flexShrink0, styles.flexBasisAuto]}
71-
enabledWhenOffline
72-
/>
73-
);
74-
}, [error, isEditing, onAccountTypeSelected, styles.flexBasisAuto, styles.flexGrow0, styles.flexReset, styles.flexShrink0, translate]);
75-
7650
return (
77-
<>
51+
<FormProvider
52+
formID={ONYXKEYS.FORMS.INTERNATIONAL_BANK_ACCOUNT_FORM}
53+
submitButtonText={translate('common.confirm')}
54+
onSubmit={handleSubmit}
55+
validate={validate}
56+
style={[styles.flexGrow1, styles.mt3]}
57+
submitButtonStyles={[styles.ph5, styles.mb0]}
58+
enabledWhenOffline
59+
ref={formRef}
60+
isSubmitButtonVisible={!isEditing}
61+
>
7862
<View style={styles.ph5}>
7963
<Text style={[styles.textHeadlineLineHeightXXL, styles.mb6]}>{translate('addPersonalBankAccount.accountTypeStepHeader')}</Text>
8064
</View>
81-
<SelectionList
82-
sections={[{data: options}]}
83-
onSelectRow={onSelectionChange}
84-
ListItem={RadioListItem}
85-
initiallyFocusedOptionKey={currentAccountType}
86-
footerContent={button}
87-
shouldSingleExecuteRowSelect
88-
shouldStopPropagation
89-
shouldUseDynamicMaxToRenderPerBatch
90-
shouldUpdateFocusedIndex
65+
<InputWrapper
66+
InputComponent={ValuePicker}
67+
inputID={fieldData.id}
68+
label={fieldData.label}
69+
items={options}
70+
shouldSaveDraft={!isEditing}
71+
shouldShowModal={false}
72+
onValueChange={(value) => {
73+
if (!isEditing) {
74+
return;
75+
}
76+
setDraftValues(ONYXKEYS.FORMS.INTERNATIONAL_BANK_ACCOUNT_FORM, {[CONST.CORPAY_FIELDS.ACCOUNT_TYPE_KEY]: value}).then(() => {
77+
onNext();
78+
});
79+
}}
9180
/>
92-
</>
81+
</FormProvider>
9382
);
9483
}
9584

0 commit comments

Comments
 (0)