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
52 changes: 52 additions & 0 deletions src/hooks/useRestartOnReceiptFailure.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {useEffect} from 'react';
import type {OnyxEntry} from 'react-native-onyx';
import {checkIfScanFileCanBeRead, setMoneyRequestReceipt} from '@libs/actions/IOU';
import {removeDraftTransactions} from '@libs/actions/TransactionEdit';
import {isLocalFile as isLocalFileUtil} from '@libs/fileDownload/FileUtils';
import {navigateToStartMoneyRequestStep} from '@libs/IOUUtils';
import {getRequestType} from '@libs/TransactionUtils';
import type {IOUAction, IOUType} from '@src/CONST';
import CONST from '@src/CONST';
import type {Transaction} from '@src/types/onyx';

const useRestartOnReceiptFailure = (transaction: OnyxEntry<Transaction>, reportID: string, iouType: IOUType, action: IOUAction) => {
// When the component mounts, if there is a receipt, see if the image can be read from the disk. If not, redirect the user to the starting step of the flow.
// This is because until the request is saved, the receipt file is only stored in the browsers memory as a blob:// and if the browser is refreshed, then
// the image ceases to exist. The best way for the user to recover from this is to start over from the start of the request process.
// skip this in case user is moving the transaction as the receipt path will be valid in that case
useEffect(() => {
let isScanFilesCanBeRead = true;

if (!transaction || action !== CONST.IOU.ACTION.CREATE) {
return;
}
const itemReceiptFilename = transaction.filename;
const itemReceiptPath = transaction.receipt?.source;
const itemReceiptType = transaction.receipt?.type;
const isLocalFile = isLocalFileUtil(itemReceiptPath);

if (!itemReceiptPath || !isLocalFile) {
return;
}

const onFailure = () => {
isScanFilesCanBeRead = false;
setMoneyRequestReceipt(transaction.transactionID, '', '', true);
};

checkIfScanFileCanBeRead(itemReceiptFilename, itemReceiptPath, itemReceiptType, () => {}, onFailure)?.then(() => {
const requestType = getRequestType(transaction);
if (isScanFilesCanBeRead || requestType !== CONST.IOU.REQUEST_TYPE.SCAN) {
return;
}

removeDraftTransactions(true);
navigateToStartMoneyRequestStep(requestType, iouType, transaction.transactionID, reportID);
});

// We want this hook to run on mounting only
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
}, []);
};

export default useRestartOnReceiptFailure;
2 changes: 2 additions & 0 deletions src/pages/iou/request/step/IOURequestStepAttendees.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {OnyxEntry} from 'react-native-onyx';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import usePrevious from '@hooks/usePrevious';
import useRestartOnReceiptFailure from '@hooks/useRestartOnReceiptFailure';
import useTransactionViolations from '@hooks/useTransactionViolations';
import {setMoneyRequestAttendees, updateMoneyRequestAttendees} from '@libs/actions/IOU';
import Navigation from '@libs/Navigation/Navigation';
Expand Down Expand Up @@ -46,6 +47,7 @@ function IOURequestStepAttendees({
const previousAttendees = usePrevious(attendees);
const {translate} = useLocalize();
const transactionViolations = useTransactionViolations(transactionID);
useRestartOnReceiptFailure(transaction, reportID, iouType, action);

const saveAttendees = useCallback(() => {
if (attendees.length <= 0) {
Expand Down
4 changes: 3 additions & 1 deletion src/pages/iou/request/step/IOURequestStepCategory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import WorkspaceEmptyStateSection from '@components/WorkspaceEmptyStateSection';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useOnyx from '@hooks/useOnyx';
import useRestartOnReceiptFailure from '@hooks/useRestartOnReceiptFailure';
import useShowNotFoundPageInIOUStep from '@hooks/useShowNotFoundPageInIOUStep';
import useThemeStyles from '@hooks/useThemeStyles';
import {getIOURequestPolicyID, setDraftSplitTransaction, setMoneyRequestCategory, updateMoneyRequestCategory} from '@libs/actions/IOU';
Expand All @@ -40,7 +41,7 @@ function IOURequestStepCategory({
report: reportReal,
reportDraft,
route: {
params: {transactionID, backTo, action, iouType, reportActionID},
params: {transactionID, backTo, action, iouType, reportActionID, reportID: routeReportID},
},
transaction,
}: IOURequestStepCategoryProps) {
Expand All @@ -67,6 +68,7 @@ function IOURequestStepCategory({
const isEditingSplit = (iouType === CONST.IOU.TYPE.SPLIT || iouType === CONST.IOU.TYPE.SPLIT_EXPENSE) && isEditing;
const currentTransaction = isEditingSplit && !lodashIsEmpty(splitDraftTransaction) ? splitDraftTransaction : transaction;
const transactionCategory = getTransactionDetails(currentTransaction)?.category ?? '';
useRestartOnReceiptFailure(transaction, routeReportID, iouType, action);

const categoryForDisplay = isCategoryMissing(transactionCategory) ? '' : transactionCategory;

Expand Down
2 changes: 2 additions & 0 deletions src/pages/iou/request/step/IOURequestStepDate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import useDuplicateTransactionsAndViolations from '@hooks/useDuplicateTransactio
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import usePolicy from '@hooks/usePolicy';
import useRestartOnReceiptFailure from '@hooks/useRestartOnReceiptFailure';
import useShowNotFoundPageInIOUStep from '@hooks/useShowNotFoundPageInIOUStep';
import useThemeStyles from '@hooks/useThemeStyles';
import {shouldUseTransactionDraft} from '@libs/IOUUtils';
Expand Down Expand Up @@ -54,6 +55,7 @@ function IOURequestStepDate({
// In the split flow, when editing we use SPLIT_TRANSACTION_DRAFT to save draft value
const isEditingSplit = (isSplitBill || isSplitExpense) && isEditing;
const currentCreated = isEditingSplit && !lodashIsEmpty(splitDraftTransaction) ? getFormattedCreated(splitDraftTransaction) : getFormattedCreated(transaction);
useRestartOnReceiptFailure(transaction, reportID, iouType, action);

// eslint-disable-next-line rulesdir/no-negated-variables
const shouldShowNotFound = useShowNotFoundPageInIOUStep(action, iouType, reportActionID, report, transaction);
Expand Down
2 changes: 2 additions & 0 deletions src/pages/iou/request/step/IOURequestStepDescription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import useAutoFocusInput from '@hooks/useAutoFocusInput';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import usePolicy from '@hooks/usePolicy';
import useRestartOnReceiptFailure from '@hooks/useRestartOnReceiptFailure';
import useShowNotFoundPageInIOUStep from '@hooks/useShowNotFoundPageInIOUStep';
import useThemeStyles from '@hooks/useThemeStyles';
import {addErrorMessage} from '@libs/ErrorUtils';
Expand Down Expand Up @@ -64,6 +65,7 @@ function IOURequestStepDescription({

const descriptionRef = useRef(currentDescriptionInMarkdown);
const isSavedRef = useRef(false);
useRestartOnReceiptFailure(transaction, reportID, iouType, action);

/**
* @returns - An object containing the errors for each inputID
Expand Down
3 changes: 3 additions & 0 deletions src/pages/iou/request/step/IOURequestStepMerchant.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import useAutoFocusInput from '@hooks/useAutoFocusInput';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import usePolicy from '@hooks/usePolicy';
import useRestartOnReceiptFailure from '@hooks/useRestartOnReceiptFailure';
import useShowNotFoundPageInIOUStep from '@hooks/useShowNotFoundPageInIOUStep';
import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
Expand Down Expand Up @@ -44,6 +45,8 @@ function IOURequestStepMerchant({
const {translate} = useLocalize();
const {inputCallbackRef, inputRef} = useAutoFocusInput();
const isEditing = action === CONST.IOU.ACTION.EDIT;
useRestartOnReceiptFailure(transaction, reportID, iouType, action);

// eslint-disable-next-line rulesdir/no-negated-variables
const shouldShowNotFoundPage = useShowNotFoundPageInIOUStep(action, iouType, reportActionID, report, transaction);
// In the split flow, when editing we use SPLIT_TRANSACTION_DRAFT to save draft value
Expand Down
2 changes: 2 additions & 0 deletions src/pages/iou/request/step/IOURequestStepReport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {ListItem} from '@components/SelectionListWithSections/types';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useOnyx from '@hooks/useOnyx';
import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses';
import useRestartOnReceiptFailure from '@hooks/useRestartOnReceiptFailure';
import useShowNotFoundPageInIOUStep from '@hooks/useShowNotFoundPageInIOUStep';
import {createNewReport} from '@libs/actions/Report';
import {changeTransactionsReport, setTransactionReport} from '@libs/actions/Transaction';
Expand Down Expand Up @@ -53,6 +54,7 @@ function IOURequestStepReport({route, transaction}: IOURequestStepReportProps) {
const {policyForMovingExpensesID, shouldSelectPolicy} = usePolicyForMovingExpenses();
const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true});
const hasViolations = hasViolationsReportUtils(undefined, transactionViolations);
useRestartOnReceiptFailure(transaction, reportIDFromRoute, iouType, action);

const handleGoBack = () => {
if (isEditing) {
Expand Down
4 changes: 3 additions & 1 deletion src/pages/iou/request/step/IOURequestStepTag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Text from '@components/Text';
import WorkspaceEmptyStateSection from '@components/WorkspaceEmptyStateSection';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import useRestartOnReceiptFailure from '@hooks/useRestartOnReceiptFailure';
import useShowNotFoundPageInIOUStep from '@hooks/useShowNotFoundPageInIOUStep';
import useThemeStyles from '@hooks/useThemeStyles';
import {setDraftSplitTransaction, setMoneyRequestTag, updateMoneyRequestTag} from '@libs/actions/IOU';
Expand All @@ -34,7 +35,7 @@ type IOURequestStepTagProps = WithWritableReportOrNotFoundProps<typeof SCREENS.M
function IOURequestStepTag({
report,
route: {
params: {action, orderWeight: rawTagIndex, transactionID, backTo, iouType, reportActionID},
params: {action, orderWeight: rawTagIndex, transactionID, backTo, iouType, reportActionID, reportID: reportIDFromRoute},
},
transaction,
}: IOURequestStepTagProps) {
Expand All @@ -46,6 +47,7 @@ function IOURequestStepTag({
const styles = useThemeStyles();
const {currentSearchHash} = useSearchContext();
const {translate} = useLocalize();
useRestartOnReceiptFailure(transaction, reportIDFromRoute, iouType, action);

const tagListIndex = Number(rawTagIndex);
const policyTagListName = getTagListName(policyTags, tagListIndex);
Expand Down
2 changes: 2 additions & 0 deletions src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {OnyxEntry} from 'react-native-onyx';
import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import useRestartOnReceiptFailure from '@hooks/useRestartOnReceiptFailure';
import {setDraftSplitTransaction, setMoneyRequestCurrency, setMoneyRequestParticipantsFromReport, setMoneyRequestTaxAmount, updateMoneyRequestTaxAmount} from '@libs/actions/IOU';
import {convertToBackendAmount, isValidCurrencyCode} from '@libs/CurrencyUtils';
import Navigation from '@libs/Navigation/Navigation';
Expand Down Expand Up @@ -57,6 +58,7 @@ function IOURequestStepTaxAmountPage({
const isEditing = action === CONST.IOU.ACTION.EDIT;
const isEditingSplitBill = isEditing && iouType === CONST.IOU.TYPE.SPLIT;
const focusTimeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
useRestartOnReceiptFailure(transaction, reportID, iouType, action);

const currentTransaction = isEditingSplitBill && !isEmptyObject(splitDraftTransaction) ? splitDraftTransaction : transaction;
const transactionDetails = getTransactionDetails(currentTransaction);
Expand Down
4 changes: 3 additions & 1 deletion src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type {OnyxEntry} from 'react-native-onyx';
import TaxPicker from '@components/TaxPicker';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import useRestartOnReceiptFailure from '@hooks/useRestartOnReceiptFailure';
import {convertToBackendAmount} from '@libs/CurrencyUtils';
import Navigation from '@libs/Navigation/Navigation';
import type {TaxRatesOption} from '@libs/TaxOptionsListUtils';
Expand Down Expand Up @@ -31,7 +32,7 @@ function getTaxAmount(policy: OnyxEntry<Policy>, transaction: OnyxEntry<Transact

function IOURequestStepTaxRatePage({
route: {
params: {action, backTo, iouType, transactionID},
params: {action, backTo, iouType, transactionID, reportID: reportIDFromRoute},
},
transaction,
report,
Expand All @@ -42,6 +43,7 @@ function IOURequestStepTaxRatePage({
const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policy?.id}`, {canBeMissing: true});
const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policy?.id}`, {canBeMissing: true});
const [splitDraftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`, {canBeMissing: true});
useRestartOnReceiptFailure(transaction, reportIDFromRoute, iouType, action);

const isEditing = action === CONST.IOU.ACTION.EDIT;
const isEditingSplitBill = isEditing && iouType === CONST.IOU.TYPE.SPLIT;
Expand Down
Loading