Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
35 changes: 20 additions & 15 deletions src/pages/iou/request/step/IOURequestStepConfirmation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@ import reportsSelector from '@selectors/Attributes';
import {transactionDraftValuesSelector} from '@selectors/TransactionDraft';
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {View} from 'react-native';
import ConfirmModal from '@components/ConfirmModal';
import DragAndDropConsumer from '@components/DragAndDrop/Consumer';
import DragAndDropProvider from '@components/DragAndDrop/Provider';
import DropZoneUI from '@components/DropZone/DropZoneUI';
import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import LocationPermissionModal from '@components/LocationPermissionModal';
import {ModalActions} from '@components/Modal/Global/ModalContext';
import MoneyRequestConfirmationList from '@components/MoneyRequestConfirmationList';
import {usePersonalDetails, usePolicyCategories} from '@components/OnyxListItemProvider';
import PrevNextButtons from '@components/PrevNextButtons';
import ScreenWrapper from '@components/ScreenWrapper';
import useArchivedReportsIdSet from '@hooks/useArchivedReportsIdSet';
import useConfirmModal from '@hooks/useConfirmModal';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useDeepCompareRef from '@hooks/useDeepCompareRef';
import useFetchRoute from '@hooks/useFetchRoute';
Expand Down Expand Up @@ -126,7 +127,6 @@ function IOURequestStepConfirmation({
const personalDetails = usePersonalDetails();
const allPolicyCategories = usePolicyCategories();

const [isRemoveConfirmModalVisible, setRemoveConfirmModalVisible] = useState(false);
const [optimisticTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {
selector: transactionDraftValuesSelector,
canBeMissing: true,
Expand Down Expand Up @@ -233,6 +233,7 @@ function IOURequestStepConfirmation({
const {translate} = useLocalize();
const {isBetaEnabled} = usePermissions();
const {isOffline} = useNetwork();
const {showConfirmModal} = useConfirmModal();
const [startLocationPermissionFlow, setStartLocationPermissionFlow] = useState(false);
const [selectedParticipantList, setSelectedParticipantList] = useState<Participant[]>([]);

Expand Down Expand Up @@ -1278,15 +1279,27 @@ function IOURequestStepConfirmation({
if (currentTransactionID === CONST.IOU.OPTIMISTIC_TRANSACTION_ID) {
const nextTransaction = transactions.at(currentTransactionIndex + 1);
replaceDefaultDraftTransaction(nextTransaction);
setRemoveConfirmModalVisible(false);
return;
}

removeDraftTransaction(currentTransactionID);
setRemoveConfirmModalVisible(false);
showPreviousTransaction();
};

const confirmRemoveCurrentTransaction = async () => {
const result = await showConfirmModal({
title: translate('iou.removeExpense'),
prompt: translate('iou.removeExpenseConfirmation'),
confirmText: translate('common.remove'),
cancelText: translate('common.cancel'),
danger: true,
});
if (result.action !== ModalActions.CONFIRM) {
return;
}
removeCurrentTransaction();
};

const showReceiptEmptyState = shouldShowReceiptEmptyState(iouType, action, policy, isPerDiemRequest);

const shouldShowSmartScanFields = !!transaction?.receipt?.isTestDriveReceipt || isMovingTransactionFromTrackExpense || requestType !== CONST.IOU.REQUEST_TYPE.SCAN;
Expand Down Expand Up @@ -1356,7 +1369,9 @@ function IOURequestStepConfirmation({
iouCategory={transaction?.category}
onConfirm={onConfirm}
onSendMoney={sendMoney}
showRemoveExpenseConfirmModal={() => setRemoveConfirmModalVisible(true)}
showRemoveExpenseConfirmModal={() => {
confirmRemoveCurrentTransaction();
}}
receiptPath={receiptPath}
receiptFilename={receiptFilename}
iouType={iouType}
Expand All @@ -1379,16 +1394,6 @@ function IOURequestStepConfirmation({
isReceiptEditable
/>
</View>
<ConfirmModal
title={translate('iou.removeExpense')}
isVisible={isRemoveConfirmModalVisible}
onConfirm={removeCurrentTransaction}
onCancel={() => setRemoveConfirmModalVisible(false)}
prompt={translate('iou.removeExpenseConfirmation')}
confirmText={translate('common.remove')}
cancelText={translate('common.cancel')}
danger
/>
</DragAndDropProvider>
</ScreenWrapper>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import AttachmentCarouselView from '@components/Attachments/AttachmentCarousel/A
import useCarouselArrows from '@components/Attachments/AttachmentCarousel/useCarouselArrows';
import useAttachmentErrors from '@components/Attachments/AttachmentView/useAttachmentErrors';
import Button from '@components/Button';
import ConfirmModal from '@components/ConfirmModal';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import * as Expensicons from '@components/Icon/Expensicons';
import {ModalActions} from '@components/Modal/Global/ModalContext';
import ScreenWrapper from '@components/ScreenWrapper';
import useConfirmModal from '@hooks/useConfirmModal';
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import useThemeStyles from '@hooks/useThemeStyles';
Expand Down Expand Up @@ -37,9 +38,10 @@ function ReceiptView({route}: ReceiptViewProps) {
const {setAttachmentError} = useAttachmentErrors();
const {shouldShowArrows, setShouldShowArrows, autoHideArrows, cancelAutoHideArrows} = useCarouselArrows();
const styles = useThemeStyles();
const expensifyIcons = useMemoizedLazyExpensifyIcons(['Trashcan'] as const);
const [currentReceipt, setCurrentReceipt] = useState<ReceiptWithTransactionIDAndSource | null>();
const [page, setPage] = useState<number>(-1);
const [isDeleteReceiptConfirmModalVisible, setIsDeleteReceiptConfirmModalVisible] = useState(false);
const {showConfirmModal} = useConfirmModal();

const [receipts = getEmptyArray<ReceiptWithTransactionIDAndSource>()] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {
selector: transactionDraftReceiptsViewSelector,
Expand Down Expand Up @@ -81,19 +83,28 @@ function ReceiptView({route}: ReceiptViewProps) {
Navigation.goBack();
}, [currentReceipt, receipts.length, secondTransaction, secondTransactionID]);

const handleCloseConfirmModal = () => {
setIsDeleteReceiptConfirmModalVisible(false);
};

const deleteReceipt = useCallback(() => {
handleCloseConfirmModal();
handleDeleteReceipt();
}, [handleDeleteReceipt]);

const handleGoBack = useCallback(() => {
Navigation.goBack(route.params.backTo);
}, [route.params.backTo]);

const handleDeleteReceiptPress = useCallback(async () => {
const result = await showConfirmModal({
title: translate('receipt.deleteReceipt'),
prompt: translate('receipt.deleteConfirmation'),
confirmText: translate('common.delete'),
cancelText: translate('common.cancel'),
danger: true,
});
if (result.action !== ModalActions.CONFIRM) {
return;
}
deleteReceipt();
}, [showConfirmModal, translate, deleteReceipt]);

return (
<ScreenWrapper
testID="ReceiptView"
Expand All @@ -103,12 +114,11 @@ function ReceiptView({route}: ReceiptViewProps) {
title={translate('common.receipt')}
shouldDisplayHelpButton={false}
onBackButtonPress={handleGoBack}
onCloseButtonPress={handleCloseConfirmModal}
>
<Button
shouldShowRightIcon
iconRight={Expensicons.Trashcan}
onPress={() => setIsDeleteReceiptConfirmModalVisible(true)}
iconRight={expensifyIcons.Trashcan}
onPress={handleDeleteReceiptPress}
innerStyles={styles.bgTransparent}
large
/>
Expand All @@ -126,17 +136,6 @@ function ReceiptView({route}: ReceiptViewProps) {
onAttachmentError={setAttachmentError}
shouldShowArrows={shouldShowArrows}
/>
<ConfirmModal
title={translate('receipt.deleteReceipt')}
isVisible={isDeleteReceiptConfirmModalVisible}
onConfirm={deleteReceipt}
onCancel={handleCloseConfirmModal}
prompt={translate('receipt.deleteConfirmation')}
confirmText={translate('common.delete')}
cancelText={translate('common.cancel')}
onBackdropPress={handleCloseConfirmModal}
danger
/>
</ScreenWrapper>
);
}
Expand Down
49 changes: 25 additions & 24 deletions src/pages/iou/request/step/IOURequestStepSubrate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ import React, {useCallback, useEffect, useRef, useState} from 'react';
import {InteractionManager, View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
import ConfirmModal from '@components/ConfirmModal';
import FormProvider from '@components/Form/FormProvider';
import InputWrapperWithRef from '@components/Form/InputWrapper';
import type {FormOnyxValues} from '@components/Form/types';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import * as Expensicons from '@components/Icon/Expensicons';
import type BaseModalProps from '@components/Modal/types';
import {ModalActions} from '@components/Modal/Global/ModalContext';
import type {AnimatedTextInputRef} from '@components/RNTextInput';
import ScreenWrapper from '@components/ScreenWrapper';
import Text from '@components/Text';
import TextInput from '@components/TextInput';
import ValuePicker from '@components/ValuePicker';
import useConfirmModal from '@hooks/useConfirmModal';
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
import usePolicy from '@hooks/usePolicy';
import useThemeStyles from '@hooks/useThemeStyles';
Expand Down Expand Up @@ -70,11 +70,11 @@ function IOURequestStepSubrate({
const styles = useThemeStyles();
const policy = usePolicy(report?.policyID);
const customUnit = getPerDiemCustomUnit(policy);
const [isDeleteStopModalOpen, setIsDeleteStopModalOpen] = useState(false);
const [restoreFocusType, setRestoreFocusType] = useState<BaseModalProps['restoreFocusType']>();
const navigation = useNavigation();
const isFocused = navigation.isFocused();
const {translate} = useLocalize();
const expensifyIcons = useMemoizedLazyExpensifyIcons(['Trashcan'] as const);
const {showConfirmModal} = useConfirmModal();
const textInputRef = useRef<AnimatedTextInputRef>(null);
const parsedIndex = parseInt(pageIndex, 10);
const selectedDestination = transaction?.comment?.customUnit?.customUnitRateID;
Expand Down Expand Up @@ -155,11 +155,24 @@ function IOURequestStepSubrate({

const deleteSubrateAndHideModal = () => {
removeSubrate(transaction, pageIndex);
setRestoreFocusType(CONST.MODAL.RESTORE_FOCUS_TYPE.DELETE);
setIsDeleteStopModalOpen(false);
goBack();
};

const handleDeleteSubrate = async () => {
const result = await showConfirmModal({
title: translate('iou.deleteSubrate'),
prompt: translate('iou.deleteSubrateConfirmation'),
confirmText: translate('common.delete'),
cancelText: translate('common.cancel'),
shouldEnableNewFocusManagement: true,
danger: true,
});
if (result.action !== ModalActions.CONFIRM) {
return;
}
deleteSubrateAndHideModal();
};

const tabTitles = {
[CONST.IOU.TYPE.REQUEST]: translate('iou.createExpense'),
[CONST.IOU.TYPE.SUBMIT]: translate('iou.createExpense'),
Expand All @@ -176,7 +189,7 @@ function IOURequestStepSubrate({
<ScreenWrapper
includeSafeAreaPaddingBottom
shouldEnableMaxHeight
testID="IOURequestStepSubrate"
testID={IOURequestStepSubrate.displayName}
>
<FullPageNotFoundView shouldShow={shouldDisableEditor}>
<HeaderWithBackButton
Expand All @@ -187,29 +200,15 @@ function IOURequestStepSubrate({
shouldSetModalVisibility={false}
threeDotsMenuItems={[
{
icon: Expensicons.Trashcan,
icon: expensifyIcons.Trashcan,
text: translate('iou.deleteSubrate'),
onSelected: () => {
setRestoreFocusType(undefined);
setIsDeleteStopModalOpen(true);
handleDeleteSubrate();
},
shouldCallAfterModalHide: true,
},
]}
/>
<ConfirmModal
title={translate('iou.deleteSubrate')}
isVisible={isDeleteStopModalOpen}
onConfirm={deleteSubrateAndHideModal}
onCancel={() => setIsDeleteStopModalOpen(false)}
shouldSetModalVisibility={false}
prompt={translate('iou.deleteSubrateConfirmation')}
confirmText={translate('common.delete')}
cancelText={translate('common.cancel')}
shouldEnableNewFocusManagement
danger
restoreFocusType={restoreFocusType}
/>
<FormProvider
style={[styles.flexGrow1, styles.mh5]}
formID={ONYXKEYS.FORMS.MONEY_REQUEST_SUBRATE_FORM}
Expand Down Expand Up @@ -255,4 +254,6 @@ function IOURequestStepSubrate({
);
}

IOURequestStepSubrate.displayName = 'IOURequestStepSubrate';

export default withWritableReportOrNotFound(withFullTransactionOrNotFound(IOURequestStepSubrate));
45 changes: 22 additions & 23 deletions src/pages/iou/request/step/IOURequestStepWaypoint.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import AddressSearch from '@components/AddressSearch';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
import ConfirmModal from '@components/ConfirmModal';
import FormProvider from '@components/Form/FormProvider';
import InputWrapperWithRef from '@components/Form/InputWrapper';
import type {FormOnyxValues} from '@components/Form/types';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import * as Expensicons from '@components/Icon/Expensicons';
import type BaseModalProps from '@components/Modal/types';
import {ModalActions} from '@components/Modal/Global/ModalContext';
import ScreenWrapper from '@components/ScreenWrapper';
import useConfirmModal from '@hooks/useConfirmModal';
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
import useLocationBias from '@hooks/useLocationBias';
import useNetwork from '@hooks/useNetwork';
Expand Down Expand Up @@ -66,8 +66,6 @@ function IOURequestStepWaypoint({
transaction,
}: IOURequestStepWaypointProps) {
const styles = useThemeStyles();
const [isDeleteStopModalOpen, setIsDeleteStopModalOpen] = useState(false);
const [restoreFocusType, setRestoreFocusType] = useState<BaseModalProps['restoreFocusType']>();
const navigation = useNavigation();
const isFocused = navigation.isFocused();
const {translate} = useLocalize();
Expand All @@ -79,6 +77,8 @@ function IOURequestStepWaypoint({
const waypointCount = Object.keys(allWaypoints).length;
const filledWaypointCount = Object.values(allWaypoints).filter((waypoint) => !isEmptyObject(waypoint)).length;
const [caretHidden, setCaretHidden] = useState(false);
const {showConfirmModal} = useConfirmModal();
const expensifyIcons = useMemoizedLazyExpensifyIcons(['Trashcan'] as const);

const [userLocation] = useOnyx(ONYXKEYS.USER_LOCATION, {canBeMissing: true});
const [recentWaypoints] = useOnyx(ONYXKEYS.NVP_RECENT_WAYPOINTS, {selector: recentWaypointsSelector, canBeMissing: true});
Expand Down Expand Up @@ -155,11 +155,24 @@ function IOURequestStepWaypoint({

const deleteStopAndHideModal = () => {
removeWaypoint(transaction, pageIndex, shouldUseTransactionDraft(action));
setRestoreFocusType(CONST.MODAL.RESTORE_FOCUS_TYPE.DELETE);
setIsDeleteStopModalOpen(false);
goBack();
};

const handleDeleteWaypoint = async () => {
const result = await showConfirmModal({
title: translate('distance.deleteWaypoint'),
prompt: translate('distance.deleteWaypointConfirmation'),
confirmText: translate('common.delete'),
cancelText: translate('common.cancel'),
shouldEnableNewFocusManagement: true,
danger: true,
});
if (result.action !== ModalActions.CONFIRM) {
return;
}
deleteStopAndHideModal();
};

const selectWaypoint = (values: Waypoint) => {
const waypoint = {
lat: values.lat ?? 0,
Expand Down Expand Up @@ -207,29 +220,15 @@ function IOURequestStepWaypoint({
shouldSetModalVisibility={false}
threeDotsMenuItems={[
{
icon: Expensicons.Trashcan,
icon: expensifyIcons.Trashcan,
text: translate('distance.deleteWaypoint'),
onSelected: () => {
setRestoreFocusType(undefined);
setIsDeleteStopModalOpen(true);
handleDeleteWaypoint();
},
shouldCallAfterModalHide: true,
},
]}
/>
<ConfirmModal
title={translate('distance.deleteWaypoint')}
isVisible={isDeleteStopModalOpen}
onConfirm={deleteStopAndHideModal}
onCancel={() => setIsDeleteStopModalOpen(false)}
shouldSetModalVisibility={false}
prompt={translate('distance.deleteWaypointConfirmation')}
confirmText={translate('common.delete')}
cancelText={translate('common.cancel')}
shouldEnableNewFocusManagement
danger
restoreFocusType={restoreFocusType}
/>
<FormProvider
style={[styles.flexGrow1, styles.mh5]}
formID={ONYXKEYS.FORMS.WAYPOINT_FORM}
Expand Down
Loading