diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index 780c8c7d2ea4..1a6fa5326234 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -8,7 +8,6 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import * as CurrencyUtils from '@libs/CurrencyUtils'; -import * as HeaderUtils from '@libs/HeaderUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; @@ -22,7 +21,6 @@ import ROUTES from '@src/ROUTES'; import type {Route} from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; -import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type IconAsset from '@src/types/utils/IconAsset'; import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; import Button from './Button'; @@ -86,28 +84,20 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea const [shouldShowHoldMenu, setShouldShowHoldMenu] = useState(false); const {translate} = useLocalize(); const {isOffline} = useNetwork(); - const {isSmallScreenWidth, windowWidth} = useWindowDimensions(); + const {isSmallScreenWidth} = useWindowDimensions(); const {reimbursableSpend} = ReportUtils.getMoneyRequestSpendBreakdown(moneyRequestReport); - const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID); - const isApproved = ReportUtils.isReportApproved(moneyRequestReport); - const isClosed = ReportUtils.isClosedReport(moneyRequestReport); const isOnHold = TransactionUtils.isOnHold(transaction); - const isScanning = TransactionUtils.hasReceipt(transaction) && TransactionUtils.isReceiptBeingScanned(transaction); const isDeletedParentAction = !!requestParentReportAction && ReportActionsUtils.isDeletedAction(requestParentReportAction); - const canHoldOrUnholdRequest = !isEmptyObject(transaction) && !isSettled && !isApproved && !isDeletedParentAction && !isClosed; // Only the requestor can delete the request, admins can only edit it. const isActionOwner = typeof requestParentReportAction?.actorAccountID === 'number' && typeof session?.accountID === 'number' && requestParentReportAction.actorAccountID === session?.accountID; const canDeleteRequest = isActionOwner && ReportUtils.canAddOrDeleteTransactions(moneyRequestReport) && !isDeletedParentAction; - const isPolicyAdmin = policy?.role === CONST.POLICY.ROLE.ADMIN; - const isApprover = ReportUtils.isMoneyRequestReport(moneyRequestReport) && moneyRequestReport?.managerID !== null && session?.accountID === moneyRequestReport?.managerID; const [isHoldMenuVisible, setIsHoldMenuVisible] = useState(false); const [paymentType, setPaymentType] = useState(); const [requestType, setRequestType] = useState(); const canAllowSettlement = ReportUtils.hasUpdatedTotal(moneyRequestReport, policy); const policyType = policy?.type; - const isPayer = ReportUtils.isPayer(session, moneyRequestReport); const isDraft = ReportUtils.isOpenExpenseReport(moneyRequestReport); const [isConfirmModalVisible, setIsConfirmModalVisible] = useState(false); @@ -198,22 +188,6 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea TransactionActions.markAsCash(iouTransactionID, reportID); }, [requestParentReportAction, transactionThreadReport?.reportID]); - const changeMoneyRequestStatus = () => { - if (!transactionThreadReport) { - return; - } - const iouTransactionID = ReportActionsUtils.isMoneyRequestAction(requestParentReportAction) - ? ReportActionsUtils.getOriginalMessage(requestParentReportAction)?.IOUTransactionID ?? '-1' - : '-1'; - - if (isOnHold) { - IOU.unholdRequest(iouTransactionID, transactionThreadReport.reportID); - } else { - const activeRoute = encodeURIComponent(Navigation.getActiveRouteWithoutParams()); - Navigation.navigate(ROUTES.MONEY_REQUEST_HOLD_REASON.getRoute(policy?.type ?? CONST.POLICY.TYPE.PERSONAL, iouTransactionID, transactionThreadReport.reportID, activeRoute)); - } - }; - const getStatusIcon: (src: IconAsset) => React.ReactNode = (src) => ( changeMoneyRequestStatus(), - }); - } - if (!isOnHold && (isRequestIOU || canModifyStatus) && !isScanning && !isInvoiceReport) { - threeDotsMenuItems.push({ - icon: Expensicons.Stopwatch, - text: translate('iou.hold'), - onSelected: () => changeMoneyRequestStatus(), - }); - } - } - useEffect(() => { if (isLoadingHoldUseExplained) { return; @@ -291,23 +242,6 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea IOU.dismissHoldUseExplanation(); }; - if (isPayer && isSettled && ReportUtils.isExpenseReport(moneyRequestReport)) { - threeDotsMenuItems.push({ - icon: Expensicons.Trashcan, - text: translate('iou.cancelPayment'), - onSelected: () => setIsConfirmModalVisible(true), - }); - } - - // If the report supports adding transactions to it, then it also supports deleting transactions from it. - if (canDeleteRequest && !isEmptyObject(transactionThreadReport)) { - threeDotsMenuItems.push({ - icon: Expensicons.Trashcan, - text: translate('reportActionContextMenu.deleteAction', {action: requestParentReportAction}), - onSelected: () => setIsDeleteRequestModalVisible(true), - }); - } - useEffect(() => { if (canDeleteRequest) { return; @@ -328,9 +262,6 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea onBackButtonPress={onBackButtonPress} // Shows border if no buttons or banners are showing below the header shouldShowBorderBottom={!isMoreContentShown} - shouldShowThreeDotsButton - threeDotsMenuItems={threeDotsMenuItems} - threeDotsAnchorPosition={styles.threeDotsPopoverOffsetNoCloseButton(windowWidth)} > {shouldShowSettlementButton && !shouldUseNarrowLayout && ( diff --git a/src/components/MoneyRequestHeader.tsx b/src/components/MoneyRequestHeader.tsx index d55d3cc19fe9..b30e9da50701 100644 --- a/src/components/MoneyRequestHeader.tsx +++ b/src/components/MoneyRequestHeader.tsx @@ -1,5 +1,5 @@ import type {ReactNode} from 'react'; -import React, {useCallback, useEffect, useRef, useState} from 'react'; +import React, {useCallback, useEffect, useState} from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; @@ -7,7 +7,6 @@ import useLocalize from '@hooks/useLocalize'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; -import * as HeaderUtils from '@libs/HeaderUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; @@ -15,15 +14,12 @@ import * as TransactionUtils from '@libs/TransactionUtils'; import variables from '@styles/variables'; import * as IOU from '@userActions/IOU'; import * as TransactionActions from '@userActions/Transaction'; -import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type {Route} from '@src/ROUTES'; import type {Policy, Report, ReportAction} from '@src/types/onyx'; import type IconAsset from '@src/types/utils/IconAsset'; import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; import Button from './Button'; -import ConfirmModal from './ConfirmModal'; import HeaderWithBackButton from './HeaderWithBackButton'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; @@ -56,43 +52,21 @@ function MoneyRequestHeader({report, parentReportAction, policy, shouldUseNarrow }`, ); const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS); - const [session] = useOnyx(ONYXKEYS.SESSION); const [dismissedHoldUseExplanation, dismissedHoldUseExplanationResult] = useOnyx(ONYXKEYS.NVP_DISMISSED_HOLD_USE_EXPLANATION, {initialValue: true}); const isLoadingHoldUseExplained = isLoadingOnyxValue(dismissedHoldUseExplanationResult); const styles = useThemeStyles(); const theme = useTheme(); const {translate} = useLocalize(); - const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false); const [shouldShowHoldMenu, setShouldShowHoldMenu] = useState(false); const isSelfDMTrackExpenseReport = ReportUtils.isTrackExpenseReport(report) && ReportUtils.isSelfDM(parentReport); const moneyRequestReport = !isSelfDMTrackExpenseReport ? parentReport : undefined; - const isSettled = ReportUtils.isSettled(moneyRequestReport?.reportID); - const isApproved = ReportUtils.isReportApproved(moneyRequestReport); const isDraft = ReportUtils.isOpenExpenseReport(moneyRequestReport); const isOnHold = TransactionUtils.isOnHold(transaction); const isDuplicate = TransactionUtils.isDuplicate(transaction?.transactionID ?? ''); - const {isSmallScreenWidth, windowWidth} = useWindowDimensions(); + const {isSmallScreenWidth} = useWindowDimensions(); - const navigateBackToAfterDelete = useRef(); - - // Only the requestor can take delete the request, admins can only edit it. - const isActionOwner = typeof parentReportAction?.actorAccountID === 'number' && typeof session?.accountID === 'number' && parentReportAction.actorAccountID === session?.accountID; - const isPolicyAdmin = policy?.role === CONST.POLICY.ROLE.ADMIN; - const isApprover = ReportUtils.isMoneyRequestReport(moneyRequestReport) && moneyRequestReport?.managerID !== null && session?.accountID === moneyRequestReport?.managerID; const hasAllPendingRTERViolations = TransactionUtils.allHavePendingRTERViolation([transaction?.transactionID ?? '-1']); const shouldShowMarkAsCashButton = isDraft && hasAllPendingRTERViolations; - const deleteTransaction = useCallback(() => { - if (parentReportAction) { - const iouTransactionID = ReportActionsUtils.isMoneyRequestAction(parentReportAction) ? ReportActionsUtils.getOriginalMessage(parentReportAction)?.IOUTransactionID ?? '-1' : '-1'; - if (ReportActionsUtils.isTrackExpenseAction(parentReportAction)) { - navigateBackToAfterDelete.current = IOU.deleteTrackExpense(parentReport?.reportID ?? '-1', iouTransactionID, parentReportAction, true); - } else { - navigateBackToAfterDelete.current = IOU.deleteMoneyRequest(iouTransactionID, parentReportAction, true); - } - } - - setIsDeleteModalVisible(false); - }, [parentReport?.reportID, parentReportAction, setIsDeleteModalVisible]); const markAsCash = useCallback(() => { TransactionActions.markAsCash(transaction?.transactionID ?? '-1', report.reportID); @@ -100,23 +74,6 @@ function MoneyRequestHeader({report, parentReportAction, policy, shouldUseNarrow const isScanning = TransactionUtils.hasReceipt(transaction) && TransactionUtils.isReceiptBeingScanned(transaction); - const isDeletedParentAction = ReportActionsUtils.isDeletedAction(parentReportAction); - const canHoldOrUnholdRequest = !isSettled && !isApproved && !isDeletedParentAction && !ReportUtils.isArchivedRoom(parentReport); - - // If the report supports adding transactions to it, then it also supports deleting transactions from it. - const canDeleteRequest = isActionOwner && (ReportUtils.canAddOrDeleteTransactions(moneyRequestReport) || isSelfDMTrackExpenseReport) && !isDeletedParentAction; - - const changeMoneyRequestStatus = () => { - const iouTransactionID = ReportActionsUtils.isMoneyRequestAction(parentReportAction) ? ReportActionsUtils.getOriginalMessage(parentReportAction)?.IOUTransactionID ?? '-1' : '-1'; - - if (isOnHold) { - IOU.unholdRequest(iouTransactionID, report?.reportID); - } else { - const activeRoute = encodeURIComponent(Navigation.getActiveRouteWithoutParams()); - Navigation.navigate(ROUTES.MONEY_REQUEST_HOLD_REASON.getRoute(policy?.type ?? CONST.POLICY.TYPE.PERSONAL, iouTransactionID, report?.reportID, activeRoute)); - } - }; - const getStatusIcon: (src: IconAsset) => ReactNode = (src) => ( { - if (canDeleteRequest) { - return; - } - - setIsDeleteModalVisible(false); - }, [canDeleteRequest]); - - const threeDotsMenuItems = [HeaderUtils.getPinMenuItem(report)]; - if (canHoldOrUnholdRequest) { - const isRequestIOU = parentReport?.type === 'iou'; - const isHoldCreator = ReportUtils.isHoldCreator(transaction, report?.reportID) && isRequestIOU; - const isTrackExpenseReport = ReportUtils.isTrackExpenseReport(report); - const canModifyStatus = !isTrackExpenseReport && (isPolicyAdmin || isActionOwner || isApprover); - if (isOnHold && !isDuplicate && (isHoldCreator || (!isRequestIOU && canModifyStatus))) { - threeDotsMenuItems.push({ - icon: Expensicons.Stopwatch, - text: translate('iou.unholdExpense'), - onSelected: () => changeMoneyRequestStatus(), - }); - } - if (!isOnHold && (isRequestIOU || canModifyStatus) && !isScanning) { - threeDotsMenuItems.push({ - icon: Expensicons.Stopwatch, - text: translate('iou.hold'), - onSelected: () => changeMoneyRequestStatus(), - }); - } - } - useEffect(() => { if (isLoadingHoldUseExplained) { return; @@ -199,14 +126,6 @@ function MoneyRequestHeader({report, parentReportAction, policy, shouldUseNarrow IOU.dismissHoldUseExplanation(); }; - if (canDeleteRequest) { - threeDotsMenuItems.push({ - icon: Expensicons.Trashcan, - text: translate('reportActionContextMenu.deleteAction', {action: parentReportAction}), - onSelected: () => setIsDeleteModalVisible(true), - }); - } - return ( <> @@ -215,9 +134,6 @@ function MoneyRequestHeader({report, parentReportAction, policy, shouldUseNarrow shouldShowReportAvatarWithDisplay shouldEnableDetailPageNavigation shouldShowPinButton={false} - shouldShowThreeDotsButton - threeDotsMenuItems={threeDotsMenuItems} - threeDotsAnchorPosition={styles.threeDotsPopoverOffsetNoCloseButton(windowWidth)} report={{ ...report, ownerAccountID: parentReport?.ownerAccountID, @@ -281,18 +197,6 @@ function MoneyRequestHeader({report, parentReportAction, policy, shouldUseNarrow )} - setIsDeleteModalVisible(false)} - onModalHide={() => ReportUtils.navigateBackAfterDeleteTransaction(navigateBackToAfterDelete.current)} - prompt={translate('iou.deleteConfirmation')} - confirmText={translate('common.delete')} - cancelText={translate('common.cancel')} - danger - shouldEnableNewFocusManagement - /> {isSmallScreenWidth && shouldShowHoldMenu && ( account?.guideCalendarLink, + }); const reportKey = useMemo(() => { const accountID = Number(route.params?.accountID ?? -1); @@ -175,6 +179,8 @@ function ProfilePage({route}: ProfilePageProps) { return result; }, [accountID, isCurrentUser, loginParams, report]); + const isConcierge = ReportUtils.isConciergeChatReport(report); + return ( @@ -276,6 +282,16 @@ function ProfilePage({route}: ProfilePageProps) { brickRoadIndicator={ReportActions.hasErrorInPrivateNotes(report) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} /> )} + {isConcierge && guideCalendarLink && ( + { + LinkActions.openExternalLink(guideCalendarLink); + })} + /> + )} {!hasAvatar && isLoading && } diff --git a/src/pages/home/HeaderView.tsx b/src/pages/home/HeaderView.tsx index 53d2347a2809..7077c1a325c5 100644 --- a/src/pages/home/HeaderView.tsx +++ b/src/pages/home/HeaderView.tsx @@ -1,4 +1,4 @@ -import React, {memo, useMemo} from 'react'; +import React, {memo} from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; @@ -7,7 +7,6 @@ import Button from '@components/Button'; import CaretWrapper from '@components/CaretWrapper'; import ConfirmModal from '@components/ConfirmModal'; import DisplayNames from '@components/DisplayNames'; -import type {ThreeDotsMenuItem} from '@components/HeaderWithBackButton/types'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; import MultipleAvatars from '@components/MultipleAvatars'; @@ -18,18 +17,14 @@ import ReportHeaderSkeletonView from '@components/ReportHeaderSkeletonView'; import SubscriptAvatar from '@components/SubscriptAvatar'; import TaskHeaderActionButton from '@components/TaskHeaderActionButton'; import Text from '@components/Text'; -import ThreeDotsMenu from '@components/ThreeDotsMenu'; import Tooltip from '@components/Tooltip'; import useLocalize from '@hooks/useLocalize'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import useWindowDimensions from '@hooks/useWindowDimensions'; -import * as HeaderUtils from '@libs/HeaderUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as ReportUtils from '@libs/ReportUtils'; import * as SubscriptionUtils from '@libs/SubscriptionUtils'; -import * as Link from '@userActions/Link'; import * as Report from '@userActions/Report'; import * as Session from '@userActions/Session'; import * as Task from '@userActions/Task'; @@ -40,12 +35,6 @@ import type * as OnyxTypes from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; type HeaderViewOnyxProps = { - /** URL to the assigned guide's appointment booking calendar */ - guideCalendarLink: OnyxEntry; - - /** Current user session */ - session: OnyxEntry; - /** Personal details of all the users */ personalDetails: OnyxEntry; @@ -73,20 +62,8 @@ type HeaderViewProps = HeaderViewOnyxProps & { shouldUseNarrowLayout?: boolean; }; -function HeaderView({ - report, - personalDetails, - parentReport, - parentReportAction, - policy, - session, - reportID, - guideCalendarLink, - onNavigationMenuButtonClicked, - shouldUseNarrowLayout = false, -}: HeaderViewProps) { +function HeaderView({report, personalDetails, parentReport, parentReportAction, policy, reportID, onNavigationMenuButtonClicked, shouldUseNarrowLayout = false}: HeaderViewProps) { const [isDeleteTaskConfirmModalVisible, setIsDeleteTaskConfirmModalVisible] = React.useState(false); - const {windowWidth} = useWindowDimensions(); const {translate} = useLocalize(); const theme = useTheme(); const styles = useThemeStyles(); @@ -108,9 +85,6 @@ function HeaderView({ const title = ReportUtils.getReportName(reportHeaderData, undefined, parentReportAction); const subtitle = ReportUtils.getChatRoomSubtitle(reportHeaderData); const parentNavigationSubtitleData = ReportUtils.getParentNavigationSubtitle(reportHeaderData); - const isConcierge = ReportUtils.isConciergeChatReport(report); - const isCanceledTaskReport = ReportUtils.isCanceledTaskReport(report, parentReportAction); - const isPolicyEmployee = useMemo(() => !isEmptyObject(policy), [policy]); const reportDescription = ReportUtils.getReportDescriptionText(report); const policyName = ReportUtils.getPolicyName(report, true); const policyDescription = ReportUtils.getPolicyDescriptionText(policy); @@ -128,48 +102,9 @@ function HeaderView({ return true; }; - // We hide the button when we are chatting with an automated Expensify account since it's not possible to contact - // these users via alternative means. It is possible to request a call with Concierge so we leave the option for them. - const threeDotMenuItems: ThreeDotsMenuItem[] = []; - if (isTaskReport && !isCanceledTaskReport) { - const canModifyTask = Task.canModifyTask(report, session?.accountID ?? -1); - - // Task is marked as completed - if (ReportUtils.isCompletedTaskReport(report) && canModifyTask) { - threeDotMenuItems.push({ - icon: Expensicons.Checkmark, - text: translate('task.markAsIncomplete'), - onSelected: Session.checkIfActionIsAllowed(() => Task.reopenTask(report)), - }); - } - - // Task is not closed - if (ReportUtils.canWriteInReport(report) && report.stateNum !== CONST.REPORT.STATE_NUM.APPROVED && !ReportUtils.isClosedReport(report) && canModifyTask) { - threeDotMenuItems.push({ - icon: Expensicons.Trashcan, - text: translate('common.delete'), - onSelected: Session.checkIfActionIsAllowed(() => setIsDeleteTaskConfirmModalVisible(true)), - }); - } - } - const join = Session.checkIfActionIsAllowed(() => Report.joinRoom(report)); const canJoin = ReportUtils.canJoinChat(report, parentReportAction, policy); - if (canJoin) { - threeDotMenuItems.push({ - icon: Expensicons.ChatBubbles, - text: translate('common.join'), - onSelected: join, - }); - } else if (ReportUtils.canLeaveChat(report, policy)) { - const isWorkspaceMemberLeavingWorkspaceRoom = !isChatThread && (report.visibility === CONST.REPORT.VISIBILITY.RESTRICTED || isPolicyExpenseChat) && isPolicyEmployee; - threeDotMenuItems.push({ - icon: Expensicons.ChatBubbles, - text: translate('common.leave'), - onSelected: Session.checkIfActionIsAllowed(() => Report.leaveRoom(reportID, isWorkspaceMemberLeavingWorkspaceRoom)), - }); - } const joinButton = (