From 3f157a4a5d91c6ef4963a47bae68d42dee05a210 Mon Sep 17 00:00:00 2001 From: Nikos Bright Date: Mon, 18 Dec 2023 13:16:42 -0500 Subject: [PATCH 1/5] TS migration for ReportWelcomeText done --- ...rtWelcomeText.js => ReportWelcomeText.tsx} | 105 ++++++------------ 1 file changed, 37 insertions(+), 68 deletions(-) rename src/components/{ReportWelcomeText.js => ReportWelcomeText.tsx} (57%) diff --git a/src/components/ReportWelcomeText.js b/src/components/ReportWelcomeText.tsx similarity index 57% rename from src/components/ReportWelcomeText.js rename to src/components/ReportWelcomeText.tsx index a204d0c59aaf..9f5ab10caa79 100644 --- a/src/components/ReportWelcomeText.js +++ b/src/components/ReportWelcomeText.tsx @@ -1,92 +1,65 @@ -import lodashGet from 'lodash/get'; -import PropTypes from 'prop-types'; +import _ from 'lodash'; import React from 'react'; import {View} from 'react-native'; -import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; +import {OnyxEntry, withOnyx} from 'react-native-onyx'; import useThemeStyles from '@hooks/useThemeStyles'; import compose from '@libs/compose'; import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; -import reportPropTypes from '@pages/reportPropTypes'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import type {PersonalDetailsList, Policy, Report} from '@src/types/onyx'; import Text from './Text'; import UserDetailsTooltip from './UserDetailsTooltip'; -import withLocalize, {withLocalizePropTypes} from './withLocalize'; - -const personalDetailsPropTypes = PropTypes.shape({ - /** The login of the person (either email or phone number) */ - login: PropTypes.string, - - /** The URL of the person's avatar (there should already be a default avatar if - the person doesn't have their own avatar uploaded yet, except for anon users) */ - avatar: PropTypes.string, - - /** This is either the user's full name, or their login if full name is an empty string */ - displayName: PropTypes.string, -}); - -const propTypes = { - /** The report currently being looked at */ - report: reportPropTypes, - - /** The policy object for the current route */ - policy: PropTypes.shape({ - /** The name of the policy */ - name: PropTypes.string, - - /** The URL for the policy avatar */ - avatar: PropTypes.string, - }), - - /* Onyx Props */ +import withLocalize, {WithLocalizeProps} from './withLocalize'; +type ReportWelcomeTextOnyxProps = { /** All of the personal details for everyone */ - personalDetails: PropTypes.objectOf(personalDetailsPropTypes), - - ...withLocalizePropTypes, + personalDetails: OnyxEntry; }; -const defaultProps = { - report: {}, - policy: {}, - personalDetails: {}, -}; +type ReportWelcomeTextProps = WithLocalizeProps & + ReportWelcomeTextOnyxProps & { + /** The report currently being looked at */ + report: Report; + + /** The policy for the current route */ + policy: Policy; + }; -function ReportWelcomeText(props) { +function ReportWelcomeText({report = {} as Report, policy = {} as Policy, personalDetails = {}, translate}: ReportWelcomeTextProps) { const styles = useThemeStyles(); - const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(props.report); - const isChatRoom = ReportUtils.isChatRoom(props.report); + const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report); + const isChatRoom = ReportUtils.isChatRoom(report); const isDefault = !(isChatRoom || isPolicyExpenseChat); - const participantAccountIDs = lodashGet(props.report, 'participantAccountIDs', []); + const participantAccountIDs = report?.participantAccountIDs ?? []; const isMultipleParticipant = participantAccountIDs.length > 1; const displayNamesWithTooltips = ReportUtils.getDisplayNamesWithTooltips( - OptionsListUtils.getPersonalDetailsForAccountIDs(participantAccountIDs, props.personalDetails), + OptionsListUtils.getPersonalDetailsForAccountIDs(participantAccountIDs, personalDetails) as PersonalDetailsList, isMultipleParticipant, ); - const isUserPolicyAdmin = PolicyUtils.isPolicyAdmin(props.policy); - const roomWelcomeMessage = ReportUtils.getRoomWelcomeMessage(props.report, isUserPolicyAdmin); - const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(props.report, participantAccountIDs); + const isUserPolicyAdmin = PolicyUtils.isPolicyAdmin(policy); + const roomWelcomeMessage = ReportUtils.getRoomWelcomeMessage(report, isUserPolicyAdmin); + const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, participantAccountIDs); return ( <> - {isChatRoom ? props.translate('reportActionsView.welcomeToRoom', {roomName: ReportUtils.getReportName(props.report)}) : props.translate('reportActionsView.sayHello')} + {isChatRoom ? translate('reportActionsView.welcomeToRoom', {roomName: ReportUtils.getReportName(report)}) : translate('reportActionsView.sayHello')} {isPolicyExpenseChat && ( <> - {props.translate('reportActionsView.beginningOfChatHistoryPolicyExpenseChatPartOne')} - {ReportUtils.getDisplayNameForParticipant(props.report.ownerAccountID)} - {props.translate('reportActionsView.beginningOfChatHistoryPolicyExpenseChatPartTwo')} - {ReportUtils.getPolicyName(props.report)} - {props.translate('reportActionsView.beginningOfChatHistoryPolicyExpenseChatPartThree')} + {translate('reportActionsView.beginningOfChatHistoryPolicyExpenseChatPartOne')} + {ReportUtils.getDisplayNameForParticipant(report.ownerAccountID)} + {translate('reportActionsView.beginningOfChatHistoryPolicyExpenseChatPartTwo')} + {ReportUtils.getPolicyName(report)} + {translate('reportActionsView.beginningOfChatHistoryPolicyExpenseChatPartThree')} )} {isChatRoom && ( @@ -95,10 +68,10 @@ function ReportWelcomeText(props) { {roomWelcomeMessage.showReportName && ( Navigation.navigate(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(props.report.reportID))} + onPress={() => Navigation.navigate(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(report.reportID))} suppressHighlighting > - {ReportUtils.getReportName(props.report)} + {ReportUtils.getReportName(report)} )} {roomWelcomeMessage.phrase2 !== undefined && {roomWelcomeMessage.phrase2}} @@ -106,9 +79,9 @@ function ReportWelcomeText(props) { )} {isDefault && ( - {props.translate('reportActionsView.beginningOfChatHistory')} - {_.map(displayNamesWithTooltips, ({displayName, pronouns, accountID}, index) => ( - + {translate('reportActionsView.beginningOfChatHistory')} + {displayNamesWithTooltips.map(({displayName, pronouns, accountID}, index) => ( + {ReportUtils.isOptimisticPersonalDetail(accountID) ? ( {displayName} @@ -124,27 +97,23 @@ function ReportWelcomeText(props) { {!_.isEmpty(pronouns) && {` (${pronouns})`}} {index === displayNamesWithTooltips.length - 1 && .} - {index === displayNamesWithTooltips.length - 2 && {` ${props.translate('common.and')} `}} + {index === displayNamesWithTooltips.length - 2 && {` ${translate('common.and')} `}} {index < displayNamesWithTooltips.length - 2 && , } ))} )} - {(moneyRequestOptions.includes(CONST.IOU.TYPE.SEND) || moneyRequestOptions.includes(CONST.IOU.TYPE.REQUEST)) && ( - {props.translate('reportActionsView.usePlusButton')} - )} + {(moneyRequestOptions.includes(CONST.IOU.TYPE.SEND) || moneyRequestOptions.includes(CONST.IOU.TYPE.REQUEST)) && {translate('reportActionsView.usePlusButton')}} ); } -ReportWelcomeText.defaultProps = defaultProps; -ReportWelcomeText.propTypes = propTypes; ReportWelcomeText.displayName = 'ReportWelcomeText'; export default compose( - withLocalize, - withOnyx({ + withLocalize, + withOnyx({ personalDetails: { key: ONYXKEYS.PERSONAL_DETAILS_LIST, }, From 9e7f9746003b64ba7705f0869c391e26e3fd81f4 Mon Sep 17 00:00:00 2001 From: Nikos Bright Date: Mon, 18 Dec 2023 14:21:52 -0500 Subject: [PATCH 2/5] use hooks --- src/components/ReportWelcomeText.tsx | 33 +++++++++++++--------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/components/ReportWelcomeText.tsx b/src/components/ReportWelcomeText.tsx index 9f5ab10caa79..67eb50e54dde 100644 --- a/src/components/ReportWelcomeText.tsx +++ b/src/components/ReportWelcomeText.tsx @@ -2,8 +2,8 @@ import _ from 'lodash'; import React from 'react'; import {View} from 'react-native'; import {OnyxEntry, withOnyx} from 'react-native-onyx'; +import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import compose from '@libs/compose'; import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; @@ -14,23 +14,22 @@ import ROUTES from '@src/ROUTES'; import type {PersonalDetailsList, Policy, Report} from '@src/types/onyx'; import Text from './Text'; import UserDetailsTooltip from './UserDetailsTooltip'; -import withLocalize, {WithLocalizeProps} from './withLocalize'; type ReportWelcomeTextOnyxProps = { /** All of the personal details for everyone */ personalDetails: OnyxEntry; }; -type ReportWelcomeTextProps = WithLocalizeProps & - ReportWelcomeTextOnyxProps & { - /** The report currently being looked at */ - report: Report; +type ReportWelcomeTextProps = ReportWelcomeTextOnyxProps & { + /** The report currently being looked at */ + report: Report; - /** The policy for the current route */ - policy: Policy; - }; + /** The policy for the current route */ + policy: Policy; +}; -function ReportWelcomeText({report = {} as Report, policy = {} as Policy, personalDetails = {}, translate}: ReportWelcomeTextProps) { +function ReportWelcomeText({report = {} as Report, policy = {} as Policy, personalDetails = {}}: ReportWelcomeTextProps) { + const {translate} = useLocalize(); const styles = useThemeStyles(); const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report); const isChatRoom = ReportUtils.isChatRoom(report); @@ -38,6 +37,7 @@ function ReportWelcomeText({report = {} as Report, policy = {} as Policy, person const participantAccountIDs = report?.participantAccountIDs ?? []; const isMultipleParticipant = participantAccountIDs.length > 1; const displayNamesWithTooltips = ReportUtils.getDisplayNamesWithTooltips( + // TODO: Remove type assertion (`as PersonalDetailsList`) after `src/libs/OptionsListUtils.js` is migrated into ts OptionsListUtils.getPersonalDetailsForAccountIDs(participantAccountIDs, personalDetails) as PersonalDetailsList, isMultipleParticipant, ); @@ -111,11 +111,8 @@ function ReportWelcomeText({report = {} as Report, policy = {} as Policy, person ReportWelcomeText.displayName = 'ReportWelcomeText'; -export default compose( - withLocalize, - withOnyx({ - personalDetails: { - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - }, - }), -)(ReportWelcomeText); +export default withOnyx({ + personalDetails: { + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + }, +})(ReportWelcomeText); From 3fad7ceb9c9cf49242e2e42556ca5f36c296d56b Mon Sep 17 00:00:00 2001 From: Nikos Bright Date: Tue, 19 Dec 2023 07:50:25 -0500 Subject: [PATCH 3/5] comments addressed --- src/components/ReportWelcomeText.tsx | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/components/ReportWelcomeText.tsx b/src/components/ReportWelcomeText.tsx index 67eb50e54dde..f3237c0de29f 100644 --- a/src/components/ReportWelcomeText.tsx +++ b/src/components/ReportWelcomeText.tsx @@ -1,4 +1,3 @@ -import _ from 'lodash'; import React from 'react'; import {View} from 'react-native'; import {OnyxEntry, withOnyx} from 'react-native-onyx'; @@ -22,13 +21,13 @@ type ReportWelcomeTextOnyxProps = { type ReportWelcomeTextProps = ReportWelcomeTextOnyxProps & { /** The report currently being looked at */ - report: Report; + report: OnyxEntry; /** The policy for the current route */ - policy: Policy; + policy: OnyxEntry; }; -function ReportWelcomeText({report = {} as Report, policy = {} as Policy, personalDetails = {}}: ReportWelcomeTextProps) { +function ReportWelcomeText({report, policy, personalDetails}: ReportWelcomeTextProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report); @@ -37,8 +36,8 @@ function ReportWelcomeText({report = {} as Report, policy = {} as Policy, person const participantAccountIDs = report?.participantAccountIDs ?? []; const isMultipleParticipant = participantAccountIDs.length > 1; const displayNamesWithTooltips = ReportUtils.getDisplayNamesWithTooltips( - // TODO: Remove type assertion (`as PersonalDetailsList`) after `src/libs/OptionsListUtils.js` is migrated into ts - OptionsListUtils.getPersonalDetailsForAccountIDs(participantAccountIDs, personalDetails) as PersonalDetailsList, + // @ts-expect-error TODO: Remove this once `src/libs/OptionsListUtils.js` is migrated to TypeScript. + OptionsListUtils.getPersonalDetailsForAccountIDs(participantAccountIDs, personalDetails), isMultipleParticipant, ); const isUserPolicyAdmin = PolicyUtils.isPolicyAdmin(policy); @@ -56,7 +55,7 @@ function ReportWelcomeText({report = {} as Report, policy = {} as Policy, person {isPolicyExpenseChat && ( <> {translate('reportActionsView.beginningOfChatHistoryPolicyExpenseChatPartOne')} - {ReportUtils.getDisplayNameForParticipant(report.ownerAccountID)} + {ReportUtils.getDisplayNameForParticipant(report?.ownerAccountID)} {translate('reportActionsView.beginningOfChatHistoryPolicyExpenseChatPartTwo')} {ReportUtils.getPolicyName(report)} {translate('reportActionsView.beginningOfChatHistoryPolicyExpenseChatPartThree')} @@ -65,7 +64,7 @@ function ReportWelcomeText({report = {} as Report, policy = {} as Policy, person {isChatRoom && ( <> {roomWelcomeMessage.phrase1} - {roomWelcomeMessage.showReportName && ( + {roomWelcomeMessage.showReportName && !!report?.reportID && ( Navigation.navigate(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(report.reportID))} @@ -95,7 +94,7 @@ function ReportWelcomeText({report = {} as Report, policy = {} as Policy, person )} - {!_.isEmpty(pronouns) && {` (${pronouns})`}} + {!!pronouns && {` (${pronouns})`}} {index === displayNamesWithTooltips.length - 1 && .} {index === displayNamesWithTooltips.length - 2 && {` ${translate('common.and')} `}} {index < displayNamesWithTooltips.length - 2 && , } From e9e32fb838fd88414827deac4fb9690e8bdd0a3f Mon Sep 17 00:00:00 2001 From: Nikos Bright Date: Tue, 19 Dec 2023 07:52:37 -0500 Subject: [PATCH 4/5] comment with issue number for ts-expect-error --- src/components/ReportWelcomeText.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ReportWelcomeText.tsx b/src/components/ReportWelcomeText.tsx index f3237c0de29f..d61530f1d0a5 100644 --- a/src/components/ReportWelcomeText.tsx +++ b/src/components/ReportWelcomeText.tsx @@ -36,7 +36,7 @@ function ReportWelcomeText({report, policy, personalDetails}: ReportWelcomeTextP const participantAccountIDs = report?.participantAccountIDs ?? []; const isMultipleParticipant = participantAccountIDs.length > 1; const displayNamesWithTooltips = ReportUtils.getDisplayNamesWithTooltips( - // @ts-expect-error TODO: Remove this once `src/libs/OptionsListUtils.js` is migrated to TypeScript. + // @ts-expect-error TODO: Remove this once OptionsListUtils (https://github.com/Expensify/App/issues/24921) is migrated to TypeScript. OptionsListUtils.getPersonalDetailsForAccountIDs(participantAccountIDs, personalDetails), isMultipleParticipant, ); From 73b8b7f3345fda6344a09e58e6fa450eb9346ba0 Mon Sep 17 00:00:00 2001 From: Nikos Bright Date: Tue, 19 Dec 2023 12:21:53 -0500 Subject: [PATCH 5/5] comments addressed --- src/components/ReportWelcomeText.tsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/components/ReportWelcomeText.tsx b/src/components/ReportWelcomeText.tsx index d61530f1d0a5..cb52722b418a 100644 --- a/src/components/ReportWelcomeText.tsx +++ b/src/components/ReportWelcomeText.tsx @@ -44,6 +44,14 @@ function ReportWelcomeText({report, policy, personalDetails}: ReportWelcomeTextP const roomWelcomeMessage = ReportUtils.getRoomWelcomeMessage(report, isUserPolicyAdmin); const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, participantAccountIDs); + const navigateToReport = () => { + if (!report?.reportID) { + return; + } + + Navigation.navigate(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(report.reportID)); + }; + return ( <> @@ -64,10 +72,10 @@ function ReportWelcomeText({report, policy, personalDetails}: ReportWelcomeTextP {isChatRoom && ( <> {roomWelcomeMessage.phrase1} - {roomWelcomeMessage.showReportName && !!report?.reportID && ( + {roomWelcomeMessage.showReportName && ( Navigation.navigate(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(report.reportID))} + onPress={navigateToReport} suppressHighlighting > {ReportUtils.getReportName(report)} @@ -80,7 +88,8 @@ function ReportWelcomeText({report, policy, personalDetails}: ReportWelcomeTextP {translate('reportActionsView.beginningOfChatHistory')} {displayNamesWithTooltips.map(({displayName, pronouns, accountID}, index) => ( - + // eslint-disable-next-line react/no-array-index-key + {ReportUtils.isOptimisticPersonalDetail(accountID) ? ( {displayName}