diff --git a/src/components/AvatarWithDisplayName.js b/src/components/AvatarWithDisplayName.tsx similarity index 73% rename from src/components/AvatarWithDisplayName.js rename to src/components/AvatarWithDisplayName.tsx index 9d7e6467e804..9229cb80cf4c 100644 --- a/src/components/AvatarWithDisplayName.js +++ b/src/components/AvatarWithDisplayName.tsx @@ -1,83 +1,76 @@ -import lodashGet from 'lodash/get'; -import PropTypes from 'prop-types'; import React, {useCallback, useEffect, useRef} from 'react'; import {View} from 'react-native'; -import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; +import {OnyxCollection, OnyxEntry, withOnyx} from 'react-native-onyx'; +import {ValueOf} from 'type-fest'; import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as ReportUtils from '@libs/ReportUtils'; -import reportActionPropTypes from '@pages/home/report/reportActionPropTypes'; -import reportPropTypes from '@pages/reportPropTypes'; import * as StyleUtils from '@styles/StyleUtils'; import useTheme from '@styles/themes/useTheme'; import useThemeStyles from '@styles/useThemeStyles'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import {PersonalDetails, Policy, Report, ReportActions} from '@src/types/onyx'; import DisplayNames from './DisplayNames'; import MultipleAvatars from './MultipleAvatars'; import ParentNavigationSubtitle from './ParentNavigationSubtitle'; -import participantPropTypes from './participantPropTypes'; import PressableWithoutFeedback from './Pressable/PressableWithoutFeedback'; import SubscriptAvatar from './SubscriptAvatar'; import Text from './Text'; -const propTypes = { +type AvatarWithDisplayNamePropsWithOnyx = { + /** All of the actions of the report */ + parentReportActions: OnyxEntry; +}; + +type AvatarWithDisplayNameProps = AvatarWithDisplayNamePropsWithOnyx & { /** The report currently being looked at */ - report: reportPropTypes, + report: OnyxEntry; /** The policy which the user has access to and which the report is tied to */ - policy: PropTypes.shape({ - /** Name of the policy */ - name: PropTypes.string, - }), + policy?: OnyxEntry; /** The size of the avatar */ - size: PropTypes.oneOf(_.values(CONST.AVATAR_SIZE)), + size?: ValueOf; /** Personal details of all the users */ - personalDetails: PropTypes.objectOf(participantPropTypes), + personalDetails: OnyxCollection; /** Whether if it's an unauthenticated user */ - isAnonymous: PropTypes.bool, + isAnonymous?: boolean; - shouldEnableDetailPageNavigation: PropTypes.bool, - - /* Onyx Props */ - /** All of the actions of the report */ - parentReportActions: PropTypes.objectOf(PropTypes.shape(reportActionPropTypes)), + /** Whether we should enable detail page navigation */ + shouldEnableDetailPageNavigation?: boolean; }; -const defaultProps = { - personalDetails: {}, - policy: {}, - report: {}, - parentReportActions: {}, - isAnonymous: false, - size: CONST.AVATAR_SIZE.DEFAULT, - shouldEnableDetailPageNavigation: false, -}; - -function AvatarWithDisplayName({report, policy, size, isAnonymous, parentReportActions, personalDetails, shouldEnableDetailPageNavigation}) { +function AvatarWithDisplayName({ + personalDetails, + policy, + report, + parentReportActions, + isAnonymous = false, + size = CONST.AVATAR_SIZE.DEFAULT, + shouldEnableDetailPageNavigation = false, +}: AvatarWithDisplayNameProps) { const theme = useTheme(); const styles = useThemeStyles(); const title = ReportUtils.getReportName(report); const subtitle = ReportUtils.getChatRoomSubtitle(report); const parentNavigationSubtitleData = ReportUtils.getParentNavigationSubtitle(report); const isMoneyRequestOrReport = ReportUtils.isMoneyRequestReport(report) || ReportUtils.isMoneyRequest(report); - const icons = ReportUtils.getIcons(report, personalDetails, policy); - const ownerPersonalDetails = OptionsListUtils.getPersonalDetailsForAccountIDs([report.ownerAccountID], personalDetails); - const displayNamesWithTooltips = ReportUtils.getDisplayNamesWithTooltips(_.values(ownerPersonalDetails), false); + const icons = ReportUtils.getIcons(report, personalDetails, null, '', -1, policy); + const ownerPersonalDetails = OptionsListUtils.getPersonalDetailsForAccountIDs(report?.ownerAccountID ? [report.ownerAccountID] : [], personalDetails); + const displayNamesWithTooltips = ReportUtils.getDisplayNamesWithTooltips(Object.values(ownerPersonalDetails), false); const shouldShowSubscriptAvatar = ReportUtils.shouldReportShowSubscript(report); const isExpenseRequest = ReportUtils.isExpenseRequest(report); const defaultSubscriptSize = isExpenseRequest ? CONST.AVATAR_SIZE.SMALL_NORMAL : size; const avatarBorderColor = isAnonymous ? theme.highlightBG : theme.componentBG; - const actorAccountID = useRef(null); + const actorAccountID = useRef(null); useEffect(() => { - const parentReportAction = lodashGet(parentReportActions, [report.parentReportActionID], {}); - actorAccountID.current = lodashGet(parentReportAction, 'actorAccountID', -1); + const parentReportAction = parentReportActions?.[report?.parentReportActionID ?? '']; + actorAccountID.current = parentReportAction?.actorAccountID ?? -1; }, [parentReportActions, report]); const showActorDetails = useCallback(() => { @@ -86,31 +79,33 @@ function AvatarWithDisplayName({report, policy, size, isAnonymous, parentReportA return ReportUtils.navigateToDetailsPage(report); } - if (ReportUtils.isExpenseReport(report)) { + if (ReportUtils.isExpenseReport(report) && report?.ownerAccountID) { Navigation.navigate(ROUTES.PROFILE.getRoute(report.ownerAccountID)); return; } - if (ReportUtils.isIOUReport(report)) { + if (ReportUtils.isIOUReport(report) && report?.reportID) { Navigation.navigate(ROUTES.REPORT_PARTICIPANTS.getRoute(report.reportID)); return; } if (ReportUtils.isChatThread(report)) { // In an ideal situation account ID won't be 0 - if (actorAccountID.current > 0) { + if (actorAccountID.current && actorAccountID.current > 0) { Navigation.navigate(ROUTES.PROFILE.getRoute(actorAccountID.current)); return; } } - // Report detail route is added as fallback but based on the current implementation this route won't be executed - Navigation.navigate(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(report.reportID)); + if (report?.reportID) { + // Report detail route is added as fallback but based on the current implementation this route won't be executed + Navigation.navigate(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(report.reportID)); + } }, [report, shouldEnableDetailPageNavigation]); const headerView = ( - {Boolean(report && title) && ( + {report && !!title && ( - {!_.isEmpty(parentNavigationSubtitleData) && ( + {Object.keys(parentNavigationSubtitleData).length > 0 && ( )} - {!_.isEmpty(subtitle) && ( + {!!subtitle && ( ); } -AvatarWithDisplayName.propTypes = propTypes; + AvatarWithDisplayName.displayName = 'AvatarWithDisplayName'; -AvatarWithDisplayName.defaultProps = defaultProps; -export default withOnyx({ +export default withOnyx({ parentReportActions: { key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report ? report.parentReportID : '0'}`, canEvict: false, diff --git a/src/languages/types.ts b/src/languages/types.ts index 96dd85dfb627..9f66dc6f97ec 100644 --- a/src/languages/types.ts +++ b/src/languages/types.ts @@ -187,7 +187,7 @@ type OOOEventSummaryFullDayParams = {summary: string; dayCount: number; date: st type OOOEventSummaryPartialDayParams = {summary: string; timePeriod: string; date: string}; -type ParentNavigationSummaryParams = {rootReportName: string; workspaceName: string}; +type ParentNavigationSummaryParams = {rootReportName?: string; workspaceName?: string}; type SetTheRequestParams = {valueName: string; newValueToDisplay: string}; diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index ddd3fd6e4f87..4678ce395f76 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -152,7 +152,7 @@ function getAvatarsForAccountIDs(accountIDs, personalDetails, defaultValues = {} * Returns the personal details for an array of accountIDs * * @param {Array} accountIDs - * @param {Object} personalDetails + * @param {Object | null} personalDetails * @returns {Object} – keys of the object are emails, values are PersonalDetails objects. */ function getPersonalDetailsForAccountIDs(accountIDs, personalDetails) { diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 70fd41937fa0..c444187cbd10 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -12,7 +12,7 @@ import {ValueOf} from 'type-fest'; import * as Expensicons from '@components/Icon/Expensicons'; import * as defaultWorkspaceAvatars from '@components/Icon/WorkspaceDefaultAvatars'; import CONST from '@src/CONST'; -import {TranslationPaths} from '@src/languages/types'; +import {ParentNavigationSummaryParams, TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import {Beta, Login, PersonalDetails, Policy, PolicyTags, Report, ReportAction, Session, Transaction} from '@src/types/onyx'; @@ -2310,7 +2310,7 @@ function getChatRoomSubtitle(report: OnyxEntry): string | undefined { /** * Gets the parent navigation subtitle for the report */ -function getParentNavigationSubtitle(report: OnyxEntry): ReportAndWorkspaceName | EmptyObject { +function getParentNavigationSubtitle(report: OnyxEntry): ParentNavigationSummaryParams { if (isThread(report)) { const parentReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.parentReportID}`] ?? null; const {rootReportName, workspaceName} = getRootReportAndWorkspaceName(parentReport);