Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[QBO Export] Manual exports #44170

Merged
Show file tree
Hide file tree
Changes from 57 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
f48cff1
feat: setup the ReportDetailsExportPage.tsx and navigation
kosmydel Jun 20, 2024
6eb2f4d
feat: add Onyx actions
kosmydel Jun 20, 2024
80389e9
feat: getConnectedIntegration
kosmydel Jun 21, 2024
bdb2917
feat: use SelectionScreen in ReportDetailsExportPage
kosmydel Jun 21, 2024
87ea402
feat: add ConfirmModal
kosmydel Jun 21, 2024
01b5268
feat: export in ReportPreview
kosmydel Jun 21, 2024
100e1dc
Merge branch 'main' into @kosmydel/qbo-export/manual-exports
kosmydel Jun 21, 2024
e552a93
fix: exporting reports
kosmydel Jun 21, 2024
062f557
cleanup
kosmydel Jun 21, 2024
64620f6
Merge branch 'main' into @kosmydel/qbo-export/manual-exports
kosmydel Jun 24, 2024
d00f1f0
feat: spanish translations
kosmydel Jun 24, 2024
095b0cc
feat: add manual button export to MoneyReportHeader
kosmydel Jun 24, 2024
2ea4435
refactor: getConnectedIntegration
kosmydel Jun 25, 2024
b8fcea9
refactor: include dropdownOptions in ExportWithDropdownMenu
kosmydel Jun 25, 2024
92949a7
feat: add not ready to export screen
kosmydel Jun 25, 2024
82708fc
feat: add screen wrapper
kosmydel Jun 25, 2024
cc0b95a
Merge branch 'main' into @kosmydel/qbo-export/manual-exports
kosmydel Jun 25, 2024
cff5d28
feat: empty Export screen translation
kosmydel Jun 25, 2024
e8f6379
Merge branch 'main' into @kosmydel/qbo-export/manual-exports
kosmydel Jun 26, 2024
f13f1cd
fix: types
kosmydel Jun 27, 2024
2c8ab95
feat: confirmation button in dropdown menu
kosmydel Jun 27, 2024
163718d
feat: add correct illustration
kosmydel Jun 27, 2024
40a1462
feat: dropdown menu clickable button
kosmydel Jun 27, 2024
5e01f89
feat: persist last export method
kosmydel Jun 28, 2024
f10a469
Merge branch 'main' into @kosmydel/qbo-export/manual-exports
kosmydel Jun 28, 2024
4c43898
fix displaying integration names
kosmydel Jun 28, 2024
15a26aa
fix: lint & TS
kosmydel Jun 28, 2024
5a35efd
Merge branch 'main' into @kosmydel/qbo-export/manual-exports
kosmydel Jun 28, 2024
e3d06bc
fix: buttons style
kosmydel Jun 28, 2024
cfddc13
cleanup: rename animation to illustration in ConfirmationPage
kosmydel Jun 28, 2024
a50a1f7
refactor: address review
kosmydel Jun 28, 2024
d29b2f2
address review
kosmydel Jun 28, 2024
21575e5
fix lint
kosmydel Jun 28, 2024
2ae3022
Merge branch 'main' into @kosmydel/qbo-export/manual-exports
kosmydel Jul 1, 2024
f478df7
fix: displaying icons on native
kosmydel Jul 1, 2024
47cb0bf
cleanup: use WRITE_COMMANDS
kosmydel Jul 1, 2024
0488216
Merge branch 'main' into @kosmydel/qbo-export/manual-exports
kosmydel Jul 3, 2024
c30c013
cleanup: SelectionScreen
kosmydel Jul 3, 2024
6a1542d
feat: add correct translations
kosmydel Jul 3, 2024
830b5b2
Merge branch 'main' into @kosmydel/qbo-export/manual-exports
kosmydel Jul 4, 2024
5101b6e
Merge branch 'main' into @kosmydel/qbo-export/manual-exports
kosmydel Jul 5, 2024
a35f02f
fix: exporting from RHP
kosmydel Jul 5, 2024
b106387
fix: display friendly name
kosmydel Jul 5, 2024
d2129ed
fix type
kosmydel Jul 5, 2024
1046f09
Merge branch 'main' into @kosmydel/qbo-export/manual-exports
kosmydel Jul 8, 2024
a556a02
lint
kosmydel Jul 8, 2024
b1b8291
fix: types
kosmydel Jul 8, 2024
deb556f
fix lint
kosmydel Jul 8, 2024
cfc7995
address review
kosmydel Jul 9, 2024
ad2c4cf
Merge branch 'main' into @kosmydel/qbo-export/manual-exports
kosmydel Jul 9, 2024
d75044e
fix modals
kosmydel Jul 9, 2024
4a18a1a
Merge branch 'main' into @kosmydel/qbo-export/manual-exports
kosmydel Jul 10, 2024
6863ba2
fix lint
kosmydel Jul 10, 2024
572c763
Merge branch 'main' into @kosmydel/qbo-export/manual-exports
kosmydel Jul 11, 2024
c4fbe0a
remove TODO
kosmydel Jul 15, 2024
32396e4
Merge branch 'main' into @kosmydel/qbo-export/manual-exports
kosmydel Jul 15, 2024
4070375
feat: display export buttons when autoSync is enabled
kosmydel Jul 15, 2024
7939596
address review
kosmydel Jul 16, 2024
ebb2c20
Merge branch 'main' into @kosmydel/qbo-export/manual-exports
kosmydel Jul 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
245 changes: 245 additions & 0 deletions assets/images/LaptopwithSecondScreenandHourglass.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,10 @@ const CONST = {
INDIVIDUAL: 'individual',
BUSINESS: 'policy',
},
EXPORT_OPTIONS: {
EXPORT_TO_INTEGRATION: 'exportToIntegration',
MARK_AS_EXPORTED: 'markAsExported',
},
},
NEXT_STEP: {
FINISHED: 'Finished!',
Expand Down Expand Up @@ -2453,6 +2457,7 @@ const CONST = {
SETTINGS: 'settings',
LEAVE_ROOM: 'leaveRoom',
PRIVATE_NOTES: 'privateNotes',
EXPORT: 'export',
DELETE: 'delete',
MARK_AS_INCOMPLETE: 'markAsIncomplete',
CANCEL_PAYMENT: 'cancelPayment',
Expand Down
4 changes: 4 additions & 0 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,9 @@ const ONYXKEYS = {
/** Stores info during review duplicates flow */
REVIEW_DUPLICATES: 'reviewDuplicates',

/** Stores the last export method for policy */
LAST_EXPORT_METHOD: 'lastExportMethod',

/** Stores the information about the state of issuing a new card */
ISSUE_NEW_EXPENSIFY_CARD: 'issueNewExpensifyCard',

Expand Down Expand Up @@ -745,6 +748,7 @@ type OnyxValuesMapping = {
[ONYXKEYS.NVP_DISMISSED_HOLD_USE_EXPLANATION]: boolean;
[ONYXKEYS.FOCUS_MODE_NOTIFICATION]: boolean;
[ONYXKEYS.NVP_LAST_PAYMENT_METHOD]: OnyxTypes.LastPaymentMethod;
[ONYXKEYS.LAST_EXPORT_METHOD]: OnyxTypes.LastExportMethod;
[ONYXKEYS.NVP_RECENT_WAYPOINTS]: OnyxTypes.RecentWaypoint[];
[ONYXKEYS.NVP_INTRO_SELECTED]: OnyxTypes.IntroSelected;
[ONYXKEYS.NVP_LAST_SELECTED_DISTANCE_RATES]: OnyxTypes.LastSelectedDistanceRates;
Expand Down
6 changes: 5 additions & 1 deletion src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type CONST from './CONST';
import type {IOUAction, IOUType} from './CONST';
import type {IOURequestType} from './libs/actions/IOU';
import type {AuthScreensParamList} from './libs/Navigation/types';
import type {SageIntacctMappingName} from './types/onyx/Policy';
import type {ConnectionName, SageIntacctMappingName} from './types/onyx/Policy';
import type {SearchQuery} from './types/onyx/SearchResults';
import type AssertTypesNotEqual from './types/utils/AssertTypesNotEqual';

Expand Down Expand Up @@ -286,6 +286,10 @@ const ROUTES = {
route: 'r/:reportID/details',
getRoute: (reportID: string, backTo?: string) => getUrlWithBackToParam(`r/${reportID}/details`, backTo),
},
REPORT_WITH_ID_DETAILS_EXPORT: {
route: 'r/:reportID/details/export/:connectionName',
getRoute: (reportID: string, connectionName: ConnectionName) => `r/${reportID}/details/export/${connectionName}` as const,
},
REPORT_SETTINGS: {
route: 'r/:reportID/settings',
getRoute: (reportID: string) => `r/${reportID}/settings` as const,
Expand Down
2 changes: 2 additions & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ const SCREENS = {
SEARCH_REPORT: 'SearchReport',
SETTINGS_CATEGORIES: 'SettingsCategories',
RESTRICTED_ACTION: 'RestrictedAction',
REPORT_EXPORT: 'Report_Export',
},
ONBOARDING_MODAL: {
ONBOARDING: 'Onboarding',
Expand Down Expand Up @@ -240,6 +241,7 @@ const SCREENS = {
REPORT_DETAILS: {
ROOT: 'Report_Details_Root',
SHARE_CODE: 'Report_Details_Share_Code',
EXPORT: 'Report_Details_Export',
},

WORKSPACE: {
Expand Down
12 changes: 11 additions & 1 deletion src/components/ButtonWithDropdownMenu/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ type WorkspaceDistanceRatesBulkActionType = DeepValueOf<typeof CONST.POLICY.BULK

type WorkspaceTaxRatesBulkActionType = DeepValueOf<typeof CONST.POLICY.BULK_ACTION_TYPES>;

type ReportExportType = DeepValueOf<typeof CONST.REPORT.EXPORT_OPTIONS>;

type DropdownOption<TValueType> = {
value: TValueType;
text: string;
Expand Down Expand Up @@ -83,4 +85,12 @@ type ButtonWithDropdownMenuProps<TValueType> = {
isSplitButton?: boolean;
};

export type {PaymentType, WorkspaceMemberBulkActionType, WorkspaceDistanceRatesBulkActionType, DropdownOption, ButtonWithDropdownMenuProps, WorkspaceTaxRatesBulkActionType};
export type {
PaymentType,
WorkspaceMemberBulkActionType,
WorkspaceDistanceRatesBulkActionType,
DropdownOption,
ButtonWithDropdownMenuProps,
WorkspaceTaxRatesBulkActionType,
ReportExportType,
};
35 changes: 26 additions & 9 deletions src/components/ConfirmationPage.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import React from 'react';
import type {TextStyle} from 'react-native';
import type {TextStyle, ViewStyle} from 'react-native';
import {View} from 'react-native';
import useThemeStyles from '@hooks/useThemeStyles';
import isIllustrationLottieAnimation from '@libs/isIllustrationLottieAnimation';
import type IconAsset from '@src/types/utils/IconAsset';
import Button from './Button';
import FixedFooter from './FixedFooter';
import ImageSVG from './ImageSVG';
import Lottie from './Lottie';
import LottieAnimations from './LottieAnimations';
import type DotLottieAnimation from './LottieAnimations/types';
import Text from './Text';

type ConfirmationPageProps = {
/** The asset to render */
animation?: DotLottieAnimation;
illustration?: DotLottieAnimation | IconAsset;

/** Heading of the confirmation page */
heading: string;
Expand All @@ -31,31 +34,45 @@ type ConfirmationPageProps = {
/** Additional style for the heading */
headingStyle?: TextStyle;

/** Additional style for the animation */
illustrationStyle?: ViewStyle;

/** Additional style for the description */
descriptionStyle?: TextStyle;
};

function ConfirmationPage({
animation = LottieAnimations.Fireworks,
illustration = LottieAnimations.Fireworks,
heading,
description,
buttonText = '',
onButtonPress = () => {},
shouldShowButton = false,
headingStyle,
illustrationStyle,
descriptionStyle,
}: ConfirmationPageProps) {
const styles = useThemeStyles();
const isLottie = isIllustrationLottieAnimation(illustration);

return (
<>
<View style={[styles.screenCenteredContainer, styles.alignItemsCenter]}>
<Lottie
source={animation}
autoPlay
loop
style={styles.confirmationAnimation}
/>
{isLottie ? (
<Lottie
source={illustration}
autoPlay
loop
style={[styles.confirmationAnimation, illustrationStyle]}
/>
) : (
<View style={[styles.confirmationAnimation, illustrationStyle]}>
<ImageSVG
src={illustration}
contentFit="contain"
/>
</View>
)}
<Text style={[styles.textHeadline, styles.textAlignCenter, styles.mv2, headingStyle]}>{heading}</Text>
<Text style={[styles.textAlignCenter, descriptionStyle]}>{description}</Text>
</View>
Expand Down
2 changes: 2 additions & 0 deletions src/components/Icon/Illustrations.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ExpensifyCardIllustration from '@assets/images/expensifyCard/cardIllustration.svg';
import LaptopwithSecondScreenandHourglass from '@assets/images/LaptopwithSecondScreenandHourglass.svg';
import Abracadabra from '@assets/images/product-illustrations/abracadabra.svg';
import BankArrowPink from '@assets/images/product-illustrations/bank-arrow--pink.svg';
import BankMouseGreen from '@assets/images/product-illustrations/bank-mouse--green.svg';
Expand Down Expand Up @@ -146,6 +147,7 @@ export {
PinkBill,
CreditCardsNew,
InvoiceBlue,
LaptopwithSecondScreenandHourglass,
LockOpen,
Luggage,
MoneyIntoWallet,
Expand Down
29 changes: 26 additions & 3 deletions src/components/MoneyReportHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as PolicyUtils from '@libs/PolicyUtils';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as TransactionUtils from '@libs/TransactionUtils';
Expand All @@ -34,6 +35,7 @@ import type {MoneyRequestHeaderStatusBarProps} from './MoneyRequestHeaderStatusB
import type {ActionHandledType} from './ProcessMoneyReportHoldMenu';
import ProcessMoneyReportHoldMenu from './ProcessMoneyReportHoldMenu';
import ProcessMoneyRequestHoldMenu from './ProcessMoneyRequestHoldMenu';
import ExportWithDropdownMenu from './ReportActionItem/ExportWithDropdownMenu';
import SettlementButton from './SettlementButton';

type MoneyReportHeaderProps = {
Expand Down Expand Up @@ -99,6 +101,7 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
const canAllowSettlement = ReportUtils.hasUpdatedTotal(moneyRequestReport, policy);
const policyType = policy?.type;
const isDraft = ReportUtils.isOpenExpenseReport(moneyRequestReport);
const connectedIntegration = PolicyUtils.getConnectedIntegration(policy);

const navigateBackToAfterDelete = useRef<Route>();
const hasScanningReceipt = ReportUtils.getTransactionsWithReceipts(moneyRequestReport?.reportID).some((t) => TransactionUtils.isReceiptBeingScanned(t));
Expand All @@ -113,15 +116,19 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea

const shouldDisableApproveButton = shouldShowApproveButton && !ReportUtils.isAllowedToApproveExpenseReport(moneyRequestReport);

const shouldShowSettlementButton = (shouldShowPayButton || shouldShowApproveButton) && !allHavePendingRTERViolation;

const shouldShowSubmitButton = isDraft && reimbursableSpend !== 0 && !allHavePendingRTERViolation;

const shouldShowExportIntegrationButton = !shouldShowPayButton && !shouldShowSubmitButton && connectedIntegration && !!policy;

const shouldShowSettlementButton = (shouldShowPayButton || shouldShowApproveButton) && !allHavePendingRTERViolation && !shouldShowExportIntegrationButton;

const shouldDisableSubmitButton = shouldShowSubmitButton && !ReportUtils.isAllowedToSubmitDraftExpenseReport(moneyRequestReport);
const shouldShowMarkAsCashButton = isDraft && allHavePendingRTERViolation;
const isFromPaidPolicy = policyType === CONST.POLICY.TYPE.TEAM || policyType === CONST.POLICY.TYPE.CORPORATE;
const shouldShowStatusBar = allHavePendingRTERViolation || hasOnlyHeldExpenses || hasScanningReceipt;
const shouldShowNextStep = !ReportUtils.isClosedExpenseReportWithNoExpenses(moneyRequestReport) && isFromPaidPolicy && !!nextStep?.message?.length && !shouldShowStatusBar;
const shouldShowAnyButton = shouldShowSettlementButton || shouldShowApproveButton || shouldShowSubmitButton || shouldShowNextStep || allHavePendingRTERViolation;
const shouldShowAnyButton =
shouldShowSettlementButton || shouldShowApproveButton || shouldShowSubmitButton || shouldShowNextStep || allHavePendingRTERViolation || shouldShowExportIntegrationButton;
const bankAccountRoute = ReportUtils.getBankAccountRoute(chatReport);
const formattedAmount = CurrencyUtils.convertToDisplayString(reimbursableSpend, moneyRequestReport.currency);
const [nonHeldAmount, fullAmount] = ReportUtils.getNonHeldAndFullAmount(moneyRequestReport, policy);
Expand Down Expand Up @@ -275,6 +282,15 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
/>
</View>
)}
{shouldShowExportIntegrationButton && !shouldUseNarrowLayout && (
<View style={[styles.pv2]}>
<ExportWithDropdownMenu
policy={policy}
report={moneyRequestReport}
connectionName={connectedIntegration}
/>
</View>
)}
{shouldShowSubmitButton && !shouldUseNarrowLayout && (
<View style={styles.pv2}>
<Button
Expand Down Expand Up @@ -319,6 +335,13 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
isLoading={!isOffline && !canAllowSettlement}
/>
)}
{shouldShowExportIntegrationButton && shouldUseNarrowLayout && (
<ExportWithDropdownMenu
policy={policy}
report={moneyRequestReport}
connectionName={connectedIntegration}
/>
)}
{shouldShowSubmitButton && shouldUseNarrowLayout && (
<Button
medium
Expand Down
128 changes: 128 additions & 0 deletions src/components/ReportActionItem/ExportWithDropdownMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import React, {useCallback, useMemo, useState} from 'react';
import {useOnyx} from 'react-native-onyx';
import type {OnyxEntry} from 'react-native-onyx';
import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu';
import type {DropdownOption, ReportExportType} from '@components/ButtonWithDropdownMenu/types';
import ConfirmModal from '@components/ConfirmModal';
import useLocalize from '@hooks/useLocalize';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useThemeStyles from '@hooks/useThemeStyles';
import * as ReportActions from '@libs/actions/Report';
kosmydel marked this conversation as resolved.
Show resolved Hide resolved
import * as PolicyUtils from '@libs/PolicyUtils';
import * as ReportUtils from '@libs/ReportUtils';
import type {ExportType} from '@pages/home/report/ReportDetailsExportPage';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Policy, Report} from '@src/types/onyx';
import type {ConnectionName} from '@src/types/onyx/Policy';

type ExportWithDropdownMenuProps = {
policy: OnyxEntry<Policy>;

report: OnyxEntry<Report>;

connectionName: ConnectionName;
};

function ExportWithDropdownMenu({policy, report, connectionName}: ExportWithDropdownMenuProps) {
const reportID = report?.reportID;
const styles = useThemeStyles();
const {translate} = useLocalize();
const {isSmallScreenWidth} = useResponsiveLayout();
const [modalStatus, setModalStatus] = useState<ExportType | null>(null);
const [exportMethods] = useOnyx(ONYXKEYS.LAST_EXPORT_METHOD, {selector: (paymentMethod) => paymentMethod ?? {}});

const iconToDisplay = ReportUtils.getIntegrationIcon(connectionName);
const canBeExported = ReportUtils.canBeExported(report);
const isExported = ReportUtils.isExported(report);
const hasIntegrationAutoSync = PolicyUtils.hasIntegrationAutoSync(policy, connectionName);

const dropdownOptions: Array<DropdownOption<ReportExportType>> = useMemo(() => {
const optionTemplate = {
icon: iconToDisplay,
disabled: !canBeExported,
displayInDefaultIconColor: true,
};
const options = [
{
value: CONST.REPORT.EXPORT_OPTIONS.EXPORT_TO_INTEGRATION,
text: translate('workspace.common.exportIntegrationSelected', connectionName),
...optionTemplate,
},
{
value: CONST.REPORT.EXPORT_OPTIONS.MARK_AS_EXPORTED,
text: translate('workspace.common.markAsExported'),
...optionTemplate,
},
];
const exportMethod = exportMethods?.[report?.policyID ?? ''] ?? null;
if (exportMethod) {
options.sort((method) => (method.value === exportMethod ? -1 : 0));
}
return options;
// We do not include exportMethods not to re-render the component when the preffered export method changes
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
}, [canBeExported, iconToDisplay, connectionName, report?.policyID, translate]);

const confirmExport = useCallback(() => {
setModalStatus(null);
if (!reportID) {
return;
}
if (modalStatus === CONST.REPORT.EXPORT_OPTIONS.EXPORT_TO_INTEGRATION) {
ReportActions.exportToIntegration(reportID, connectionName);
} else if (modalStatus === CONST.REPORT.EXPORT_OPTIONS.MARK_AS_EXPORTED) {
ReportActions.markAsManuallyExported(reportID);
}
}, [connectionName, modalStatus, reportID]);

const savePreferredExportMethod = (value: ReportExportType) => {
if (!report?.policyID) {
return;
}
ReportActions.savePreferredExportMethod(report?.policyID, value);
};

return (
<>
<ButtonWithDropdownMenu<ReportExportType>
success={!hasIntegrationAutoSync}
pressOnEnter
shouldAlwaysShowDropdownMenu
anchorAlignment={{
horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.RIGHT,
vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP,
}}
onPress={(_, value) => {
if (isExported) {
setModalStatus(value);
return;
}
if (!reportID) {
return;
}
if (value === CONST.REPORT.EXPORT_OPTIONS.EXPORT_TO_INTEGRATION) {
ReportActions.exportToIntegration(reportID, connectionName);
} else if (value === CONST.REPORT.EXPORT_OPTIONS.MARK_AS_EXPORTED) {
ReportActions.markAsManuallyExported(reportID);
}
}}
onOptionSelected={({value}) => savePreferredExportMethod(value)}
options={dropdownOptions}
style={[isSmallScreenWidth && styles.flexGrow1]}
buttonSize={CONST.DROPDOWN_BUTTON_SIZE.MEDIUM}
/>
<ConfirmModal
title={translate('workspace.exportAgainModal.title')}
onConfirm={confirmExport}
onCancel={() => setModalStatus(null)}
prompt={translate('workspace.exportAgainModal.description', report?.reportName ?? '', connectionName)}
confirmText={translate('workspace.exportAgainModal.confirmText')}
cancelText={translate('workspace.exportAgainModal.cancelText')}
isVisible={!!modalStatus}
/>
</>
);
}

export default ExportWithDropdownMenu;
Loading
Loading