diff --git a/src/components/AvatarWithDisplayName.tsx b/src/components/AvatarWithDisplayName.tsx index 9c65fa86bb9c..8f15e038c9b1 100644 --- a/src/components/AvatarWithDisplayName.tsx +++ b/src/components/AvatarWithDisplayName.tsx @@ -15,7 +15,7 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; import {getPersonalDetailsForAccountIDs} from '@libs/OptionsListUtils'; -import {getHumanAgentAccountIDFromReportAction, getHumanAgentDisplayName} from '@libs/ReportActionsUtils'; +import {getHumanAgentAccountIDFromReportAction, getHumanAgentFirstName} from '@libs/ReportActionsUtils'; import {getReportName} from '@libs/ReportNameUtils'; import type {DisplayNameWithTooltips} from '@libs/ReportUtils'; import { @@ -215,7 +215,7 @@ function AvatarWithDisplayName({ const parentReportAction = report?.parentReportActionID ? parentReportActions?.[report.parentReportActionID] : undefined; const humanAgentAccountID = getHumanAgentAccountIDFromReportAction(parentReportAction); - const humanAgentName = getHumanAgentDisplayName(parentReportAction, personalDetails); + const humanAgentName = getHumanAgentFirstName(parentReportAction, personalDetails); const parentReportActionActorAccountID = parentReportAction?.actorAccountID; const actorAccountID = useRef(null); diff --git a/src/components/ReportActionAvatars/useReportActionAvatars.ts b/src/components/ReportActionAvatars/useReportActionAvatars.ts index dcf93e930ad5..9c4333cc2751 100644 --- a/src/components/ReportActionAvatars/useReportActionAvatars.ts +++ b/src/components/ReportActionAvatars/useReportActionAvatars.ts @@ -10,6 +10,7 @@ import {addSMSDomainIfPhoneNumber} from '@libs/PhoneNumber'; import { getDelegateAccountIDFromReportAction, getHumanAgentAccountIDFromReportAction, + getHumanAgentFirstName, getOriginalMessage, getReportAction, getReportActionActorAccountID, @@ -347,11 +348,12 @@ function useReportActionAvatars({ if (humanAgentAccountID && avatarType === CONST.REPORT_ACTION_AVATARS.TYPE.SINGLE) { const humanAgentDetails = personalDetails?.[humanAgentAccountID]; if (humanAgentDetails) { + const agentFirstName = getHumanAgentFirstName(action, personalDetails); const agentAvatar: IconType = { id: humanAgentAccountID, type: CONST.ICON_TYPE_AVATAR, source: humanAgentDetails.avatar ?? defaultAvatars.FallbackAvatar, - name: humanAgentDetails.displayName ?? translate('reportAction.humanSupportAgent'), + name: agentFirstName ?? translate('reportAction.humanSupportAgent'), }; const [conciergeAvatar] = avatars; avatars = [conciergeAvatar, agentAvatar]; diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index 7f627d6c7269..9527ab74fb66 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -549,13 +549,18 @@ function getHumanAgentAccountIDFromReportAction(reportAction: OnyxInputOrEntry, personalDetails: OnyxEntry): string | undefined { +/** + * Returns the human Concierge agent's first name for the "assisted by [Name]" label. + * We intentionally use the first name only (not `displayName`, which is "First Last") + * to keep the label casual and minimize exposed agent identity. + */ +function getHumanAgentFirstName(reportAction: OnyxInputOrEntry, personalDetails: OnyxEntry): string | undefined { const humanAgentAccountID = getHumanAgentAccountIDFromReportAction(reportAction); if (!humanAgentAccountID) { return undefined; } - const displayName = personalDetails?.[humanAgentAccountID]?.displayName; - return displayName?.trim() ? displayName : undefined; + const firstName = personalDetails?.[humanAgentAccountID]?.firstName; + return firstName?.trim() ? firstName : undefined; } function isExportIntegrationAction(reportAction: OnyxInputOrEntry): reportAction is ReportAction { @@ -4838,7 +4843,7 @@ export { getUpdatedSharedBudgetNotificationMessage, getDelegateAccountIDFromReportAction, getHumanAgentAccountIDFromReportAction, - getHumanAgentDisplayName, + getHumanAgentFirstName, isPendingHide, filterOutDeprecatedReportActions, getActionableCardFraudAlertMessage, diff --git a/src/pages/inbox/HeaderView.tsx b/src/pages/inbox/HeaderView.tsx index fe363c9eb6d3..5e4a78b4a8a4 100644 --- a/src/pages/inbox/HeaderView.tsx +++ b/src/pages/inbox/HeaderView.tsx @@ -38,7 +38,7 @@ import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; import Navigation from '@libs/Navigation/Navigation'; import {getPersonalDetailsForAccountIDs} from '@libs/OptionsListUtils'; import Parser from '@libs/Parser'; -import {getHumanAgentAccountIDFromReportAction, getHumanAgentDisplayName} from '@libs/ReportActionsUtils'; +import {getHumanAgentAccountIDFromReportAction, getHumanAgentFirstName} from '@libs/ReportActionsUtils'; import {getReportName} from '@libs/ReportNameUtils'; import { canJoinChat, @@ -158,7 +158,7 @@ function HeaderView({onNavigationMenuButtonClicked, reportID}: HeaderViewProps) const isParentReportHeaderDataArchived = useReportIsArchived(reportHeaderData?.parentReportID); const parentNavigationSubtitleData = getParentNavigationSubtitle(parentNavigationReport, policy, conciergeReportID, isParentReportHeaderDataArchived); const humanAgentAccountID = getHumanAgentAccountIDFromReportAction(parentReportAction); - const humanAgentName = getHumanAgentDisplayName(parentReportAction, personalDetails); + const humanAgentName = getHumanAgentFirstName(parentReportAction, personalDetails); const reportDescription = StringUtils.lineBreaksToSpaces(Parser.htmlToText(getReportDescription(report))); const policyName = getPolicyName({report, returnEmptyIfNotFound: true}); const policyDescription = StringUtils.lineBreaksToSpaces(getPolicyDescriptionText(policy)); diff --git a/src/pages/inbox/report/ReportActionItemSingle.tsx b/src/pages/inbox/report/ReportActionItemSingle.tsx index 06518e3c2e41..b77baaec3bbd 100644 --- a/src/pages/inbox/report/ReportActionItemSingle.tsx +++ b/src/pages/inbox/report/ReportActionItemSingle.tsx @@ -21,7 +21,7 @@ import {getPersonalDetailByEmail} from '@libs/PersonalDetailsUtils'; import { getDelegateAccountIDFromReportAction, getHumanAgentAccountIDFromReportAction, - getHumanAgentDisplayName, + getHumanAgentFirstName, getManagerOnVacation, getOriginalMessage, getReportActionMessage, @@ -100,7 +100,7 @@ function ReportActionItemSingle({ const [primaryAvatar, secondaryAvatar] = avatars; const delegateAccountID = getDelegateAccountIDFromReportAction(action); const humanAgentAccountID = getHumanAgentAccountIDFromReportAction(action); - const humanAgentName = getHumanAgentDisplayName(action, personalDetails); + const humanAgentName = getHumanAgentFirstName(action, personalDetails); const mainAccountID = delegateAccountID ? (reportPreviewSenderID ?? potentialIOUReport?.ownerAccountID ?? action?.childOwnerAccountID) : (details.accountID ?? CONST.DEFAULT_NUMBER_ID); const mainAccountLogin = mainAccountID ? (personalDetails?.[mainAccountID]?.login ?? details.login) : details.login; const accountOwnerDetails = getPersonalDetailByEmail(String(mainAccountLogin ?? '')); diff --git a/tests/unit/ReportActionsUtilsTest.ts b/tests/unit/ReportActionsUtilsTest.ts index 356522f767c2..9f35156377ac 100644 --- a/tests/unit/ReportActionsUtilsTest.ts +++ b/tests/unit/ReportActionsUtilsTest.ts @@ -25,7 +25,7 @@ import { getCustomTaxNameUpdateMessage, getForeignCurrencyDefaultTaxUpdateMessage, getHumanAgentAccountIDFromReportAction, - getHumanAgentDisplayName, + getHumanAgentFirstName, getInvoiceCompanyNameUpdateMessage, getInvoiceCompanyWebsiteUpdateMessage, getOneTransactionThreadReportID, @@ -5105,7 +5105,7 @@ describe('ReportActionsUtils', () => { }); }); - describe('getHumanAgentDisplayName', () => { + describe('getHumanAgentFirstName', () => { const HUMAN_AGENT_ACCOUNT_ID = 54321; function makeConciergeAction(originalMessageOverrides: Record = {}): ReportAction { @@ -5122,10 +5122,11 @@ describe('ReportActionsUtils', () => { }; } - function makePersonalDetails(displayName: string | undefined): PersonalDetailsList { + function makePersonalDetails(firstName: string | undefined, displayName = 'Pat Agent'): PersonalDetailsList { return { [HUMAN_AGENT_ACCOUNT_ID]: { accountID: HUMAN_AGENT_ACCOUNT_ID, + firstName, displayName, }, }; @@ -5133,32 +5134,32 @@ describe('ReportActionsUtils', () => { it('returns undefined when there is no human agent on the action', () => { const action = makeConciergeAction(); - expect(getHumanAgentDisplayName(action, makePersonalDetails('Pat Agent'))).toBeUndefined(); + expect(getHumanAgentFirstName(action, makePersonalDetails('Pat'))).toBeUndefined(); }); - it('returns the agent displayName when available', () => { + it('returns the agent firstName (not the full displayName) when available', () => { const action = makeConciergeAction({humanAgentAccountID: HUMAN_AGENT_ACCOUNT_ID}); - expect(getHumanAgentDisplayName(action, makePersonalDetails('Pat Agent'))).toBe('Pat Agent'); + expect(getHumanAgentFirstName(action, makePersonalDetails('Pat', 'Pat Agent'))).toBe('Pat'); }); it('returns undefined when personalDetails has no entry for the agent', () => { const action = makeConciergeAction({humanAgentAccountID: HUMAN_AGENT_ACCOUNT_ID}); - expect(getHumanAgentDisplayName(action, {})).toBeUndefined(); + expect(getHumanAgentFirstName(action, {})).toBeUndefined(); }); it('returns undefined when personalDetails are not loaded yet', () => { const action = makeConciergeAction({humanAgentAccountID: HUMAN_AGENT_ACCOUNT_ID}); - expect(getHumanAgentDisplayName(action, undefined)).toBeUndefined(); + expect(getHumanAgentFirstName(action, undefined)).toBeUndefined(); }); - it('returns undefined when the agent displayName is an empty string so the generic fallback can be used', () => { + it('returns undefined when the agent firstName is an empty string so the generic fallback can be used', () => { const action = makeConciergeAction({humanAgentAccountID: HUMAN_AGENT_ACCOUNT_ID}); - expect(getHumanAgentDisplayName(action, makePersonalDetails(''))).toBeUndefined(); + expect(getHumanAgentFirstName(action, makePersonalDetails(''))).toBeUndefined(); }); - it('returns undefined when the agent displayName is only whitespace so the generic fallback can be used', () => { + it('returns undefined when the agent firstName is only whitespace so the generic fallback can be used', () => { const action = makeConciergeAction({humanAgentAccountID: HUMAN_AGENT_ACCOUNT_ID}); - expect(getHumanAgentDisplayName(action, makePersonalDetails(' '))).toBeUndefined(); + expect(getHumanAgentFirstName(action, makePersonalDetails(' '))).toBeUndefined(); }); }); });