Skip to content

Commit

Permalink
Merge pull request #20579 from Expensify/jules-refactorIOUCurrencySel…
Browse files Browse the repository at this point in the history
…ection

Refactor IOUCurrencySelection class to use hooks
  • Loading branch information
srikarparsi authored Jun 30, 2023
2 parents 4bd1848 + b74c0aa commit 12e9718
Showing 1 changed file with 69 additions and 109 deletions.
178 changes: 69 additions & 109 deletions src/pages/iou/IOUCurrencySelection.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {Component} from 'react';
import React, {useState, useMemo, useCallback} from 'react';
import PropTypes from 'prop-types';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
Expand Down Expand Up @@ -53,50 +53,29 @@ const defaultProps = {
},
};

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

this.state = {
searchValue: '',
currencyData: this.getCurrencyOptions(this.props.currencyList),
};
this.getCurrencyOptions = this.getCurrencyOptions.bind(this);
this.getSections = this.getSections.bind(this);
this.confirmCurrencySelection = this.confirmCurrencySelection.bind(this);
this.changeSearchValue = this.changeSearchValue.bind(this);
}

/**
* Returns the sections needed for the OptionsSelector
*
* @returns {Array}
*/
getSections() {
if (this.state.searchValue.trim() && !this.state.currencyData.length) {
return [];
}
const sections = [];
sections.push({
title: this.props.translate('iOUCurrencySelection.allCurrencies'),
data: this.state.currencyData,
shouldShow: true,
indexOffset: 0,
});

return sections;
}

getSelectedCurrencyCode() {
return lodashGet(this.props.route, 'params.currency', this.props.iou.currency);
}

/**
* @returns {Object}
*/
getCurrencyOptions() {
return _.map(this.props.currencyList, (currencyInfo, currencyCode) => {
const isSelectedCurrency = currencyCode === this.getSelectedCurrencyCode();
function IOUCurrencySelection(props) {
const [searchValue, setSearchValue] = useState('');
const selectedCurrencyCode = lodashGet(props.route, 'params.currency', props.iou.currency, CONST.CURRENCY.USD);

const confirmCurrencySelection = useCallback(
(option) => {
const backTo = lodashGet(props.route, 'params.backTo', '');
// When we refresh the web, the money request route gets cleared from the navigation stack.
// Navigating to "backTo" will result in forward navigation instead, causing disruption to the currency selection.
// To prevent any negative experience, we have made the decision to simply close the currency selection page.
if (_.isEmpty(backTo) || props.navigation.getState().routes.length === 1) {
Navigation.goBack();
} else {
Navigation.navigate(`${props.route.params.backTo}?currency=${option.currencyCode}`);
}
},
[props.route, props.navigation],
);

const {translate, currencyList} = props;
const {sections, headerMessage, initiallyFocusedOptionKey} = useMemo(() => {
const currencyOptions = _.map(currencyList, (currencyInfo, currencyCode) => {
const isSelectedCurrency = currencyCode === selectedCurrencyCode;
return {
text: `${currencyCode} - ${CurrencyUtils.getLocalizedCurrencySymbol(currencyCode)}`,
currencyCode,
Expand All @@ -105,75 +84,56 @@ class IOUCurrencySelection extends Component {
boldStyle: isSelectedCurrency,
};
});
}

/**
* Sets new search value
* @param {String} searchValue
* @return {void}
*/
changeSearchValue(searchValue) {
const currencyOptions = this.getCurrencyOptions(this.props.currencyList);
const searchRegex = new RegExp(Str.escapeForRegExp(searchValue), 'i');
const filteredCurrencies = _.filter(currencyOptions, (currencyOption) => searchRegex.test(currencyOption.text));

this.setState({
searchValue,
currencyData: filteredCurrencies,
});
}

/**
* Confirms the selection of currency
*
* @param {Object} option
* @param {String} option.currencyCode
*/
confirmCurrencySelection(option) {
const backTo = lodashGet(this.props.route, 'params.backTo', '');
// When we refresh the web, the money request route gets cleared from the navigation stack.
// Navigating to "backTo" will result in forward navigation instead, causing disruption to the currency selection.
// To prevent any negative experience, we have made the decision to simply close the currency selection page.
if (_.isEmpty(backTo) || this.props.navigation.getState().routes.length === 1) {
Navigation.goBack();
} else {
Navigation.navigate(`${this.props.route.params.backTo}?currency=${option.currencyCode}`);
}
}

render() {
const headerMessage = this.state.searchValue.trim() && !this.state.currencyData.length ? this.props.translate('common.noResultsFound') : '';
const iouType = lodashGet(this.props.route, 'params.iouType', CONST.IOU.MONEY_REQUEST_TYPE.REQUEST);
const reportID = lodashGet(this.props.route, 'params.reportID', '');
return (
<ScreenWrapper includeSafeAreaPaddingBottom={false}>
{({safeAreaPaddingBottomStyle}) => (
<>
<HeaderWithBackButton
title={this.props.translate('iOUCurrencySelection.selectCurrency')}
onBackButtonPress={() => Navigation.goBack(ROUTES.getMoneyRequestRoute(iouType, reportID))}
/>
<OptionsSelector
sections={this.getSections()}
onSelectRow={this.confirmCurrencySelection}
value={this.state.searchValue}
onChangeText={this.changeSearchValue}
textInputLabel={this.props.translate('common.search')}
headerMessage={headerMessage}
safeAreaPaddingBottomStyle={safeAreaPaddingBottomStyle}
initiallyFocusedOptionKey={_.get(
_.find(this.state.currencyData, (currency) => currency.currencyCode === this.getSelectedCurrencyCode()),
'keyForList',
)}
shouldHaveOptionSeparator
/>
</>
)}
</ScreenWrapper>
);
}
const isEmpty = searchValue.trim() && !filteredCurrencies.length;

return {
initiallyFocusedOptionKey: _.get(
_.find(filteredCurrencies, (currency) => currency.currencyCode === selectedCurrencyCode),
'keyForList',
),
sections: isEmpty
? []
: [
{
title: translate('iOUCurrencySelection.allCurrencies'),
data: filteredCurrencies,
shouldShow: true,
indexOffset: 0,
},
],
headerMessage: isEmpty ? translate('common.noResultsFound') : '',
};
}, [currencyList, searchValue, selectedCurrencyCode, translate]);

return (
<ScreenWrapper includeSafeAreaPaddingBottom={false}>
{({safeAreaPaddingBottomStyle}) => (
<>
<HeaderWithBackButton
title={translate('iOUCurrencySelection.selectCurrency')}
onBackButtonPress={() => Navigation.goBack(ROUTES.getIouRequestRoute(Navigation.getTopmostReportId()))}
/>
<OptionsSelector
sections={sections}
onSelectRow={confirmCurrencySelection}
value={searchValue}
onChangeText={setSearchValue}
textInputLabel={translate('common.search')}
headerMessage={headerMessage}
safeAreaPaddingBottomStyle={safeAreaPaddingBottomStyle}
initiallyFocusedOptionKey={initiallyFocusedOptionKey}
shouldHaveOptionSeparator
/>
</>
)}
</ScreenWrapper>
);
}

IOUCurrencySelection.displayName = 'IOUCurrencySelection';
IOUCurrencySelection.propTypes = propTypes;
IOUCurrencySelection.defaultProps = defaultProps;

Expand Down

0 comments on commit 12e9718

Please sign in to comment.