Skip to content

Commit

Permalink
Merge pull request #21049 from gedu/edu/17548_personal_details_push_t…
Browse files Browse the repository at this point in the history
…o_page_patch

17548 Personal details push to page
  • Loading branch information
mountiny authored Jul 26, 2023
2 parents 1fac96b + 4852ccb commit 3d22f59
Show file tree
Hide file tree
Showing 14 changed files with 484 additions and 216 deletions.
67 changes: 0 additions & 67 deletions src/components/CountryPicker.js

This file was deleted.

96 changes: 96 additions & 0 deletions src/components/CountryPicker/CountrySelectorModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import _ from 'underscore';
import React, {useMemo} from 'react';
import PropTypes from 'prop-types';
import CONST from '../../CONST';
import useLocalize from '../../hooks/useLocalize';
import HeaderWithBackButton from '../HeaderWithBackButton';
import SelectionListRadio from '../SelectionListRadio';
import Modal from '../Modal';

const propTypes = {
/** Whether the modal is visible */
isVisible: PropTypes.bool.isRequired,

/** Country value selected */
currentCountry: PropTypes.string,

/** Function to call when the user selects a Country */
onCountrySelected: PropTypes.func,

/** Function to call when the user closes the Country modal */
onClose: PropTypes.func,

/** The search value from the selection list */
searchValue: PropTypes.string.isRequired,

/** Function to call when the user types in the search input */
setSearchValue: PropTypes.func.isRequired,
};

const defaultProps = {
currentCountry: '',
onClose: () => {},
onCountrySelected: () => {},
};

function filterOptions(searchValue, data) {
const trimmedSearchValue = searchValue.trim();
if (trimmedSearchValue.length === 0) {
return [];
}

return _.filter(data, (country) => country.text.toLowerCase().includes(searchValue.toLowerCase()));
}

function CountrySelectorModal({currentCountry, isVisible, onClose, onCountrySelected, setSearchValue, searchValue}) {
const {translate} = useLocalize();

const countries = useMemo(
() =>
_.map(translate('allCountries'), (countryName, countryISO) => ({
value: countryISO,
keyForList: countryISO,
text: countryName,
isSelected: currentCountry === countryISO,
})),
[translate, currentCountry],
);

const filteredData = filterOptions(searchValue, countries);
const headerMessage = searchValue.trim() && !filteredData.length ? translate('common.noResultsFound') : '';

return (
<Modal
type={CONST.MODAL.MODAL_TYPE.RIGHT_DOCKED}
isVisible={isVisible}
onClose={onClose}
onModalHide={onClose}
hideModalContentWhileAnimating
useNativeDriver
>
<HeaderWithBackButton
title={translate('common.country')}
onBackButtonPress={onClose}
/>
<SelectionListRadio
headerMessage={headerMessage}
textInputLabel={translate('common.country')}
textInputPlaceholder={translate('countrySelectorModal.placeholderText')}
textInputValue={searchValue}
sections={[{data: filteredData, indexOffset: 0}]}
onSelectRow={onCountrySelected}
onChangeText={setSearchValue}
shouldFocusOnSelectRow
shouldHaveOptionSeparator
shouldDelayFocus
initiallyFocusedOptionKey={currentCountry}
/>
</Modal>
);
}

CountrySelectorModal.propTypes = propTypes;
CountrySelectorModal.defaultProps = defaultProps;
CountrySelectorModal.displayName = 'CountrySelectorModal';

export default CountrySelectorModal;
93 changes: 93 additions & 0 deletions src/components/CountryPicker/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import React, {useEffect, useState} from 'react';
import {View} from 'react-native';
import PropTypes from 'prop-types';
import lodashGet from 'lodash/get';
import styles from '../../styles/styles';
import MenuItemWithTopDescription from '../MenuItemWithTopDescription';
import useLocalize from '../../hooks/useLocalize';
import CountrySelectorModal from './CountrySelectorModal';
import FormHelpMessage from '../FormHelpMessage';

const propTypes = {
/** Form Error description */
errorText: PropTypes.string,

/** Country to display */
value: PropTypes.string,

/** Callback to call when the input changes */
onInputChange: PropTypes.func,

/** A ref to forward to MenuItemWithTopDescription */
forwardedRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({current: PropTypes.instanceOf(React.Component)})]),
};

const defaultProps = {
value: undefined,
forwardedRef: undefined,
errorText: '',
onInputChange: () => {},
};

function CountryPicker({value, errorText, onInputChange, forwardedRef}) {
const {translate} = useLocalize();
const allCountries = translate('allCountries');
const [isPickerVisible, setIsPickerVisible] = useState(false);
const [searchValue, setSearchValue] = useState(lodashGet(allCountries, value, ''));

useEffect(() => {
setSearchValue(lodashGet(allCountries, value, ''));
}, [value, allCountries]);

const showPickerModal = () => {
setIsPickerVisible(true);
};

const hidePickerModal = () => {
setIsPickerVisible(false);
};

const updateCountryInput = (country) => {
onInputChange(country.value);
hidePickerModal();
};

const title = allCountries[value] || '';
const descStyle = title.length === 0 ? styles.textNormal : null;

return (
<View>
<MenuItemWithTopDescription
ref={forwardedRef}
shouldShowRightIcon
title={title}
descriptionTextStyle={descStyle}
description={translate('common.country')}
onPress={showPickerModal}
/>
<View style={styles.ml5}>
<FormHelpMessage message={errorText} />
</View>
<CountrySelectorModal
isVisible={isPickerVisible}
currentCountry={value}
searchValue={searchValue}
setSearchValue={setSearchValue}
onClose={hidePickerModal}
onCountrySelected={updateCountryInput}
/>
</View>
);
}

CountryPicker.propTypes = propTypes;
CountryPicker.defaultProps = defaultProps;
CountryPicker.displayName = 'CountryPicker';

export default React.forwardRef((props, ref) => (
<CountryPicker
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
forwardedRef={ref}
/>
));
2 changes: 1 addition & 1 deletion src/components/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ function Form(props) {
}

if (child.props.onValueChange) {
child.props.onValueChange(value);
child.props.onValueChange(value, inputKey);
}
},
});
Expand Down
9 changes: 8 additions & 1 deletion src/components/MenuItemWithTopDescription.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ function MenuItemWithTopDescription(props) {
<MenuItem
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
ref={props.forwardedRef}
shouldShowBasicTitle
shouldShowDescriptionOnTop
/>
Expand All @@ -18,4 +19,10 @@ function MenuItemWithTopDescription(props) {
MenuItemWithTopDescription.propTypes = propTypes;
MenuItemWithTopDescription.displayName = 'MenuItemWithTopDescription';

export default MenuItemWithTopDescription;
export default React.forwardRef((props, ref) => (
<MenuItemWithTopDescription
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
forwardedRef={ref}
/>
));
67 changes: 0 additions & 67 deletions src/components/StatePicker.js

This file was deleted.

Loading

0 comments on commit 3d22f59

Please sign in to comment.