diff --git a/src/languages/en.ts b/src/languages/en.ts index c186a1fffedf..8abc0833b13c 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1209,6 +1209,7 @@ export default { messages: { errorMessageInvalidPhone: `Please enter a valid phone number without brackets or dashes. If you're outside the US please include your country code (e.g. ${CONST.EXAMPLE_PHONE_NUMBER}).`, errorMessageInvalidEmail: 'Invalid email', + errorMessageAllInviteesInvalid: 'All of the invitees are invalid or have been invited already', userIsAlreadyMember: ({login, name}: UserIsAlreadyMemberParams) => `${login} is already a member of ${name}`, }, onfidoStep: { diff --git a/src/languages/es.ts b/src/languages/es.ts index a0a30bcf4141..167061aec15b 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1226,6 +1226,7 @@ export default { messages: { errorMessageInvalidPhone: `Por favor, introduce un número de teléfono válido sin paréntesis o guiones. Si reside fuera de Estados Unidos, por favor incluye el prefijo internacional (p. ej. ${CONST.EXAMPLE_PHONE_NUMBER}).`, errorMessageInvalidEmail: 'Email inválido', + errorMessageAllInviteesInvalid: 'Todos los invitados son inválidos o ya han sido invitados', userIsAlreadyMember: ({login, name}: UserIsAlreadyMemberParams) => `${login} ya es miembro de ${name}`, }, onfidoStep: { diff --git a/src/pages/workspace/WorkspaceInvitePage.js b/src/pages/workspace/WorkspaceInvitePage.js index afb0c55e7d4e..595dbe47cad2 100644 --- a/src/pages/workspace/WorkspaceInvitePage.js +++ b/src/pages/workspace/WorkspaceInvitePage.js @@ -84,23 +84,29 @@ function WorkspaceInvitePage(props) { const excludedUsers = useMemo(() => PolicyUtils.getIneligibleInvitees(props.policyMembers, props.personalDetails), [props.policyMembers, props.personalDetails]); - useEffect(() => { - let emails = _.compact( - searchTerm - .trim() - .replace(/\s*,\s*/g, ',') - .split(','), - ); - - if (emails.length === 0) { - emails = ['']; - } + const searchEmails = useMemo( + () => + _.compact( + searchTerm + .trim() + .replace(/\s*,\s*/g, ',') + .split(','), + ), + [searchTerm], + ); + useEffect(() => { const newUsersToInviteDict = {}; - const newPersonalDetailsDict = {}; const newSelectedOptionsDict = {}; - _.each(emails, (email) => { + let emails = searchEmails; + + if (searchEmails.length === 0) { + // This ensures suggestions are displayed when there is no search term + emails = ['']; + } + + _.each(emails, (email, i) => { const inviteOptions = OptionsListUtils.getMemberInviteOptions(props.personalDetails, props.betas, email, excludedUsers); // Update selectedOptions with the latest personalDetails and policyMembers information @@ -119,10 +125,10 @@ function WorkspaceInvitePage(props) { newUsersToInviteDict[userToInvite.accountID] = userToInvite; } - // Add all personal details to the new dict - _.each(inviteOptions.personalDetails, (details) => { - newPersonalDetailsDict[details.accountID] = details; - }); + // Only show contact suggestions for the last search term + if (i === emails.length - 1) { + setPersonalDetails(inviteOptions.personalDetails); + } // Add all selected options to the new dict _.each(newSelectedOptions, (option) => { @@ -132,11 +138,10 @@ function WorkspaceInvitePage(props) { // Strip out dictionary keys and update arrays setUsersToInvite(_.values(newUsersToInviteDict)); - setPersonalDetails(_.values(newPersonalDetailsDict)); setSelectedOptions(_.values(newSelectedOptionsDict)); // eslint-disable-next-line react-hooks/exhaustive-deps -- we don't want to recalculate when selectedOptions change - }, [props.personalDetails, props.policyMembers, props.betas, searchTerm, excludedUsers]); + }, [props.personalDetails, props.policyMembers, props.betas, searchEmails, excludedUsers]); const getSections = () => { const sections = []; @@ -229,14 +234,29 @@ function WorkspaceInvitePage(props) { const headerMessage = useMemo(() => { const searchValue = searchTerm.trim().toLowerCase(); - if (usersToInvite.length === 0 && CONST.EXPENSIFY_EMAILS.includes(searchValue)) { - return translate('messages.errorMessageInvalidEmail'); - } - if (usersToInvite.length === 0 && excludedUsers.includes(searchValue)) { - return translate('messages.userIsAlreadyMember', {login: searchValue, name: policyName}); + + if (usersToInvite.length === 0) { + // Handle errors when a single email is specified + if (searchEmails.length === 1) { + const email = _.first(searchEmails); + + if (CONST.EXPENSIFY_EMAILS.includes(email)) { + return translate('messages.errorMessageInvalidEmail'); + } + + if (excludedUsers.includes(email)) { + return translate('messages.userIsAlreadyMember', {login: searchValue, name: policyName}); + } + } + + // Handle errors when multiple emails are specified + if (searchEmails.length > 1 && personalDetails.length === 0) { + return translate('messages.errorMessageAllInviteesInvalid'); + } } + return OptionsListUtils.getHeaderMessage(personalDetails.length !== 0, usersToInvite.length > 0, searchValue); - }, [excludedUsers, translate, searchTerm, policyName, usersToInvite, personalDetails.length]); + }, [excludedUsers, translate, searchTerm, searchEmails, policyName, usersToInvite, personalDetails]); return (