diff --git a/src/CONST.ts b/src/CONST.ts index e3ca655f0b38..d2a274bf0ff5 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1201,7 +1201,8 @@ const CONST = { EXPORT_TO_ACCOUNTING: 'exportToAccounting', MARK_AS_EXPORTED: 'markAsExported', HOLD: 'hold', - DOWNLOAD: 'download', + DOWNLOAD_CSV: 'downloadCSV', + DOWNLOAD_PDF: 'downloadPDF', CHANGE_WORKSPACE: 'changeWorkspace', VIEW_DETAILS: 'viewDetails', DELETE: 'delete', diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index d7d80c56a07a..f232dfc542dc 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -1,6 +1,6 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useEffect, useMemo, useState} from 'react'; -import {View} from 'react-native'; +import {ActivityIndicator, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {useOnyx} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; @@ -15,7 +15,7 @@ import useSelectedTransactionsActions from '@hooks/useSelectedTransactionsAction import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode'; -import {exportReportToCSV, exportToIntegration, markAsManuallyExported, openUnreportedExpense} from '@libs/actions/Report'; +import {downloadReportPDF, exportReportToCSV, exportReportToPDF, exportToIntegration, markAsManuallyExported, openUnreportedExpense} from '@libs/actions/Report'; import {convertToDisplayString} from '@libs/CurrencyUtils'; import {getThreadReportIDsForTransactions} from '@libs/MoneyRequestReportUtils'; import Navigation from '@libs/Navigation/Navigation'; @@ -90,11 +90,13 @@ import type {DropdownOption} from './ButtonWithDropdownMenu/types'; import ConfirmModal from './ConfirmModal'; import DecisionModal from './DecisionModal'; import DelegateNoAccessModal from './DelegateNoAccessModal'; +import Header from './Header'; import HeaderWithBackButton from './HeaderWithBackButton'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; import type {PaymentMethod} from './KYCWall/types'; import LoadingBar from './LoadingBar'; +import Modal from './Modal'; import MoneyReportHeaderStatusBar from './MoneyReportHeaderStatusBar'; import type {MoneyRequestHeaderStatusBarProps} from './MoneyRequestHeaderStatusBar'; import MoneyRequestHeaderStatusBar from './MoneyRequestHeaderStatusBar'; @@ -136,6 +138,9 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const [nextStep] = useOnyx(`${ONYXKEYS.COLLECTION.NEXT_STEP}${moneyRequestReport?.reportID}`, {canBeMissing: true}); const [transactionThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`, {canBeMissing: true}); + const [reportPDFFilename] = useOnyx(`${ONYXKEYS.COLLECTION.NVP_EXPENSIFY_REPORT_PDF_FILENAME}${moneyRequestReport?.reportID}`, {canBeMissing: true}) ?? null; + const [download] = useOnyx(`${ONYXKEYS.COLLECTION.DOWNLOAD}${reportPDFFilename}`, {canBeMissing: true}); + const isDownloadingPDF = download?.isDownloading ?? false; const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false}); const requestParentReportAction = useMemo(() => { if (!reportActions || !transactionThreadReport?.parentReportActionID) { @@ -162,6 +167,7 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false); const [isUnapproveModalVisible, setIsUnapproveModalVisible] = useState(false); const [isReopenWarningModalVisible, setIsReopenWarningModalVisible] = useState(false); + const [isPDFModalVisible, setIsPDFModalVisible] = useState(false); const [exportModalStatus, setExportModalStatus] = useState(null); @@ -189,6 +195,17 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea () => Object.fromEntries(Object.entries(allViolations ?? {}).filter(([key]) => transactionIDs.includes(key.replace(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, '')))), [allViolations, transactionIDs], ); + + const messagePDF = useMemo(() => { + if (!reportPDFFilename) { + return translate('reportDetailsPage.waitForPDF'); + } + if (reportPDFFilename === CONST.REPORT_DETAILS_MENU_ITEM.ERROR) { + return translate('reportDetailsPage.errorPDF'); + } + return translate('reportDetailsPage.generatedPDF'); + }, [reportPDFFilename, translate]); + // Check if there is pending rter violation in all transactionViolations with given transactionIDs. const hasAllPendingRTERViolations = allHavePendingRTERViolation(transactionIDs, violations); // Check if user should see broken connection violation warning. @@ -535,6 +552,11 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea const {canUseRetractNewDot, canUseTableReportView} = usePermissions(); + const beginPDFExport = (reportID: string) => { + setIsPDFModalVisible(true); + exportReportToPDF({reportID}); + }; + const secondaryActions = useMemo(() => { if (!moneyRequestReport) { return []; @@ -551,9 +573,9 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea navigateToDetailsPage(moneyRequestReport, Navigation.getReportRHPActiveRoute()); }, }, - [CONST.REPORT.SECONDARY_ACTIONS.DOWNLOAD]: { - value: CONST.REPORT.SECONDARY_ACTIONS.DOWNLOAD, - text: translate('common.download'), + [CONST.REPORT.SECONDARY_ACTIONS.DOWNLOAD_CSV]: { + value: CONST.REPORT.SECONDARY_ACTIONS.DOWNLOAD_CSV, + text: translate('common.downloadAsCSV'), icon: Expensicons.Download, onSelected: () => { if (!moneyRequestReport) { @@ -564,6 +586,17 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea }); }, }, + [CONST.REPORT.SECONDARY_ACTIONS.DOWNLOAD_PDF]: { + value: CONST.REPORT.SECONDARY_ACTIONS.DOWNLOAD_PDF, + text: translate('common.downloadAsPDF'), + icon: Expensicons.Document, + onSelected: () => { + if (!moneyRequestReport) { + return; + } + beginPDFExport(moneyRequestReport.reportID); + }, + }, [CONST.REPORT.SECONDARY_ACTIONS.SUBMIT]: { value: CONST.REPORT.SECONDARY_ACTIONS.SUBMIT, text: translate('common.submit'), @@ -964,6 +997,49 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea isVisible={isDownloadErrorModalVisible} onClose={() => setIsDownloadErrorModalVisible(false)} /> + setIsPDFModalVisible(false)} + isVisible={isPDFModalVisible} + type={isSmallScreenWidth ? CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED : CONST.MODAL.MODAL_TYPE.CONFIRM} + innerContainerStyle={styles.pv0} + shouldUseNewModal + > + + + +
+ + + {messagePDF} + {!reportPDFFilename && ( + + )} + + + {!!reportPDFFilename && reportPDFFilename !== 'error' && ( +