diff --git a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSplitSelector.js b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSplitSelector.js index ef486dff123f..7aef507ac12d 100755 --- a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSplitSelector.js +++ b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSplitSelector.js @@ -1,4 +1,4 @@ -import React, {Component} from 'react'; +import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {View} from 'react-native'; import PropTypes from 'prop-types'; import _ from 'underscore'; @@ -55,37 +55,15 @@ const defaultProps = { safeAreaPaddingBottomStyle: {}, }; -class MoneyRequestParticipantsSplitSelector extends Component { - constructor(props) { - super(props); - - this.toggleOption = this.toggleOption.bind(this); - this.finalizeParticipants = this.finalizeParticipants.bind(this); - this.updateOptionsWithSearchTerm = this.updateOptionsWithSearchTerm.bind(this); - - const {recentReports, personalDetails, userToInvite} = OptionsListUtils.getNewChatOptions( - props.reports, - props.personalDetails, - props.betas, - '', - props.participants, - CONST.EXPENSIFY_EMAILS, - ); - - this.state = { - searchTerm: '', - recentReports, - personalDetails, - userToInvite, - }; - } - - componentDidUpdate(prevProps) { - if (_.isEqual(prevProps.reports, this.props.reports) && _.isEqual(prevProps.personalDetails, this.props.personalDetails)) { - return; - } - this.updateOptionsWithSearchTerm(this.state.searchTerm); - } +function MoneyRequestParticipantsSplitSelector({betas, participants, personalDetails, reports, translate, onAddParticipants, onStepComplete, safeAreaPaddingBottomStyle}) { + const [searchTerm, setSearchTerm] = useState(''); + const [newChatOptions, setNewChatOptions] = useState({ + recentReports: [], + personalDetails: [], + userToInvite: null, + }); + + const maxParticipantsReached = participants.length === CONST.REPORT.MAXIMUM_PARTICIPANTS; /** * Returns the sections needed for the OptionsSelector @@ -93,145 +71,124 @@ class MoneyRequestParticipantsSplitSelector extends Component { * @param {Boolean} maxParticipantsReached * @returns {Array} */ - getSections(maxParticipantsReached) { - const sections = []; + const sections = useMemo(() => { + const newSections = []; let indexOffset = 0; - sections.push({ + newSections.push({ title: undefined, - data: OptionsListUtils.getParticipantsOptions(this.props.participants, this.props.personalDetails), + data: OptionsListUtils.getParticipantsOptions(participants, personalDetails), shouldShow: true, indexOffset, }); - indexOffset += this.props.participants.length; + indexOffset += participants.length; if (maxParticipantsReached) { - return sections; + return newSections; } - sections.push({ - title: this.props.translate('common.recents'), - data: this.state.recentReports, - shouldShow: !_.isEmpty(this.state.recentReports), + newSections.push({ + title: translate('common.recents'), + data: newChatOptions.recentReports, + shouldShow: !_.isEmpty(newChatOptions.recentReports), indexOffset, }); - indexOffset += this.state.recentReports.length; + indexOffset += newChatOptions.recentReports.length; - sections.push({ - title: this.props.translate('common.contacts'), - data: this.state.personalDetails, - shouldShow: !_.isEmpty(this.state.personalDetails), + newSections.push({ + title: translate('common.contacts'), + data: newChatOptions.personalDetails, + shouldShow: !_.isEmpty(newChatOptions.personalDetails), indexOffset, }); - indexOffset += this.state.personalDetails.length; + indexOffset += newChatOptions.personalDetails.length; - if (this.state.userToInvite && !OptionsListUtils.isCurrentUser(this.state.userToInvite)) { - sections.push({ + if (newChatOptions.userToInvite && !OptionsListUtils.isCurrentUser(newChatOptions.userToInvite)) { + newSections.push({ undefined, - data: [this.state.userToInvite], + data: [newChatOptions.userToInvite], shouldShow: true, indexOffset, }); } - return sections; - } - - updateOptionsWithSearchTerm(searchTerm = '') { - const {recentReports, personalDetails, userToInvite} = OptionsListUtils.getNewChatOptions( - this.props.reports, - this.props.personalDetails, - this.props.betas, - searchTerm, - this.props.participants, - CONST.EXPENSIFY_EMAILS, - ); - this.setState({ - searchTerm, - userToInvite, - recentReports, - personalDetails, - }); - } - - /** - * Once a single or more users are selected, navigates to next step - */ - finalizeParticipants() { - this.props.onStepComplete(); - } + return newSections; + }, [maxParticipantsReached, newChatOptions, participants, personalDetails, translate]); /** * Removes a selected option from list if already selected. If not already selected add this option to the list. * @param {Object} option */ - toggleOption(option) { - const isOptionInList = _.some(this.props.participants, (selectedOption) => selectedOption.accountID === option.accountID); + const toggleOption = useCallback( + (option) => { + const isOptionInList = _.some(participants, (selectedOption) => selectedOption.accountID === option.accountID); - let newSelectedOptions; + let newSelectedOptions; - if (isOptionInList) { - newSelectedOptions = _.reject(this.props.participants, (selectedOption) => selectedOption.accountID === option.accountID); - } else { - newSelectedOptions = [...this.props.participants, {accountID: option.accountID, login: option.login, selected: true}]; - } + if (isOptionInList) { + newSelectedOptions = _.reject(participants, (selectedOption) => selectedOption.accountID === option.accountID); + } else { + newSelectedOptions = [...participants, {accountID: option.accountID, login: option.login, selected: true}]; + } + + onAddParticipants(newSelectedOptions); + + const chatOptions = OptionsListUtils.getNewChatOptions(reports, personalDetails, betas, isOptionInList ? searchTerm : '', newSelectedOptions, CONST.EXPENSIFY_EMAILS); - this.props.onAddParticipants(newSelectedOptions); - - this.setState((prevState) => { - const {recentReports, personalDetails, userToInvite} = OptionsListUtils.getNewChatOptions( - this.props.reports, - this.props.personalDetails, - this.props.betas, - isOptionInList ? prevState.searchTerm : '', - newSelectedOptions, - CONST.EXPENSIFY_EMAILS, - ); - return { - recentReports, - personalDetails, - userToInvite, - searchTerm: isOptionInList ? prevState.searchTerm : '', - }; + setNewChatOptions({ + recentReports: chatOptions.recentReports, + personalDetails: chatOptions.personalDetails, + userToInvite: chatOptions.userToInvite, + }); + if (!isOptionInList) { + setSearchTerm(''); + } + }, + [searchTerm, participants, onAddParticipants, reports, personalDetails, betas, setNewChatOptions, setSearchTerm], + ); + + const headerMessage = OptionsListUtils.getHeaderMessage( + newChatOptions.personalDetails.length + newChatOptions.recentReports.length !== 0, + Boolean(newChatOptions.userToInvite), + searchTerm, + maxParticipantsReached, + ); + const isOptionsDataReady = ReportUtils.isReportDataReady() && OptionsListUtils.isPersonalDetailsReady(personalDetails); + + useEffect(() => { + const chatOptions = OptionsListUtils.getNewChatOptions(reports, personalDetails, betas, searchTerm, participants, CONST.EXPENSIFY_EMAILS); + setNewChatOptions({ + recentReports: chatOptions.recentReports, + personalDetails: chatOptions.personalDetails, + userToInvite: chatOptions.userToInvite, }); - } - - render() { - const maxParticipantsReached = this.props.participants.length === CONST.REPORT.MAXIMUM_PARTICIPANTS; - const sections = this.getSections(maxParticipantsReached); - const headerMessage = OptionsListUtils.getHeaderMessage( - this.state.personalDetails.length + this.state.recentReports.length !== 0, - Boolean(this.state.userToInvite), - this.state.searchTerm, - maxParticipantsReached, - ); - const isOptionsDataReady = ReportUtils.isReportDataReady() && OptionsListUtils.isPersonalDetailsReady(this.props.personalDetails); - - return ( - 0 ? this.props.safeAreaPaddingBottomStyle : {}]}> - - - ); - } + }, [betas, reports, participants, personalDetails, translate, searchTerm, setNewChatOptions]); + + return ( + 0 ? safeAreaPaddingBottomStyle : {}]}> + + + ); } MoneyRequestParticipantsSplitSelector.propTypes = propTypes; MoneyRequestParticipantsSplitSelector.defaultProps = defaultProps; +MoneyRequestParticipantsSplitSelector.displayName = 'MoneyRequestParticipantsSplitSelector'; export default compose( withLocalize,