diff --git a/src/languages/en.ts b/src/languages/en.ts index 179ad777234d..5f486f4f437c 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -617,6 +617,8 @@ export default { trackManual: 'Track expense', trackScan: 'Track receipt', trackDistance: 'Track distance', + noLongerHaveReportAccess: 'You no longer have access to your previous quick action destination. Pick a new one below.', + updateDestination: 'Update destination', }, iou: { amount: 'Amount', diff --git a/src/languages/es.ts b/src/languages/es.ts index b7c32027c40a..5538a7cc9f33 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -610,6 +610,8 @@ export default { trackManual: 'Crear gasto', trackScan: 'Crear gasto por recibo', trackDistance: 'Crear gasto por desplazamiento', + noLongerHaveReportAccess: 'Ya no tienes acceso al destino previo de esta acción rápida. Escoge uno nuevo a continuación.', + updateDestination: 'Actualiza el destino', }, iou: { amount: 'Importe', diff --git a/src/libs/actions/Task.ts b/src/libs/actions/Task.ts index 329119d688c9..e9a7c4f1c57f 100644 --- a/src/libs/actions/Task.ts +++ b/src/libs/actions/Task.ts @@ -681,6 +681,7 @@ function setAssigneeValue( shareToReportID?: string, chatReport?: OnyxEntry, isCurrentUser = false, + skipShareDestination = false, ): OnyxEntry | undefined { let report: OnyxEntry | undefined = chatReport; if (!isCurrentUser) { @@ -704,7 +705,7 @@ function setAssigneeValue( // If there is no share destination set, automatically set it to the assignee chat report // This allows for a much quicker process when creating a new task and is likely the desired share destination most times - if (!shareToReportID) { + if (!shareToReportID && !skipShareDestination) { setShareDestinationValue(report?.reportID ?? ''); } } @@ -736,7 +737,7 @@ function clearOutTaskInfoAndNavigate(reportID?: string, chatReport?: OnyxEntry 0) { const accountLogin = allPersonalDetails?.[accountID]?.login ?? ''; - setAssigneeValue(accountLogin, accountID, reportID, chatReport); + setAssigneeValue(accountLogin, accountID, reportID, chatReport, false, skipConfirmation); } Navigation.navigate(ROUTES.NEW_TASK_DETAILS); } diff --git a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx index 8ac3f7e0ca94..09023c312983 100644 --- a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx +++ b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx @@ -21,6 +21,7 @@ import getTopmostCentralPaneRoute from '@libs/Navigation/getTopmostCentralPaneRo import Navigation from '@libs/Navigation/Navigation'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; +import {isArchivedRoom} from '@libs/ReportUtils'; import * as App from '@userActions/App'; import * as IOU from '@userActions/IOU'; import * as Policy from '@userActions/Policy'; @@ -199,39 +200,41 @@ function FloatingActionButtonAndPopover( }, [quickAction, translate]); const navigateToQuickAction = () => { + const isValidReport = !(isEmptyObject(quickActionReport) || isArchivedRoom(quickActionReport)); + const quickActionReportID = isValidReport ? quickActionReport?.reportID ?? '' : ReportUtils.generateReportID(); switch (quickAction?.action) { case CONST.QUICK_ACTIONS.REQUEST_MANUAL: - IOU.startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.MANUAL, true); + IOU.startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.MANUAL, true); return; case CONST.QUICK_ACTIONS.REQUEST_SCAN: - IOU.startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.SCAN, true); + IOU.startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.SCAN, true); return; case CONST.QUICK_ACTIONS.REQUEST_DISTANCE: - IOU.startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.DISTANCE, true); + IOU.startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.DISTANCE, true); return; case CONST.QUICK_ACTIONS.SPLIT_MANUAL: - IOU.startMoneyRequest(CONST.IOU.TYPE.SPLIT, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.MANUAL, true); + IOU.startMoneyRequest(CONST.IOU.TYPE.SPLIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.MANUAL, true); return; case CONST.QUICK_ACTIONS.SPLIT_SCAN: - IOU.startMoneyRequest(CONST.IOU.TYPE.SPLIT, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.SCAN, true); + IOU.startMoneyRequest(CONST.IOU.TYPE.SPLIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.SCAN, true); return; case CONST.QUICK_ACTIONS.SPLIT_DISTANCE: - IOU.startMoneyRequest(CONST.IOU.TYPE.SPLIT, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.DISTANCE, true); + IOU.startMoneyRequest(CONST.IOU.TYPE.SPLIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.DISTANCE, true); return; case CONST.QUICK_ACTIONS.SEND_MONEY: - IOU.startMoneyRequest(CONST.IOU.TYPE.PAY, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.MANUAL, true); + IOU.startMoneyRequest(CONST.IOU.TYPE.PAY, quickActionReportID, CONST.IOU.REQUEST_TYPE.MANUAL, true); return; case CONST.QUICK_ACTIONS.ASSIGN_TASK: - Task.clearOutTaskInfoAndNavigate(quickAction?.chatReportID ?? '', quickActionReport, quickAction.targetAccountID ?? 0, true); + Task.clearOutTaskInfoAndNavigate(isValidReport ? quickActionReportID : '', isValidReport ? quickActionReport : undefined, quickAction.targetAccountID ?? 0, true); break; case CONST.QUICK_ACTIONS.TRACK_MANUAL: - IOU.startMoneyRequest(CONST.IOU.TYPE.TRACK, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.MANUAL, true); + IOU.startMoneyRequest(CONST.IOU.TYPE.TRACK, quickActionReportID, CONST.IOU.REQUEST_TYPE.MANUAL, true); break; case CONST.QUICK_ACTIONS.TRACK_SCAN: - IOU.startMoneyRequest(CONST.IOU.TYPE.TRACK, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.SCAN, true); + IOU.startMoneyRequest(CONST.IOU.TYPE.TRACK, quickActionReportID, CONST.IOU.REQUEST_TYPE.SCAN, true); break; case CONST.QUICK_ACTIONS.TRACK_DISTANCE: - IOU.startMoneyRequest(CONST.IOU.TYPE.TRACK, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.DISTANCE, true); + IOU.startMoneyRequest(CONST.IOU.TYPE.TRACK, quickActionReportID, CONST.IOU.REQUEST_TYPE.DISTANCE, true); break; default: } @@ -436,7 +439,7 @@ function FloatingActionButtonAndPopover( isLabelHoverable: false, floatRightAvatars: quickActionAvatars, floatRightAvatarSize: CONST.AVATAR_SIZE.SMALL, - description: !isEmptyObject(quickActionReport) ? ReportUtils.getReportName(quickActionReport) : '', + description: ReportUtils.getReportName(quickActionReport) ?? translate('quickAction.updateDestination'), numberOfLinesDescription: 1, onSelected: () => interceptAnonymousUser(() => navigateToQuickAction()), shouldShowSubscriptRightAvatar: ReportUtils.isPolicyExpenseChat(quickActionReport), diff --git a/src/pages/iou/request/step/IOURequestStepParticipants.tsx b/src/pages/iou/request/step/IOURequestStepParticipants.tsx index be95cb03e95b..f8d18fc03034 100644 --- a/src/pages/iou/request/step/IOURequestStepParticipants.tsx +++ b/src/pages/iou/request/step/IOURequestStepParticipants.tsx @@ -1,6 +1,9 @@ import React, {useCallback, useEffect, useMemo, useRef} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; +import FormHelpMessage from '@components/FormHelpMessage'; import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; import DistanceRequestUtils from '@libs/DistanceRequestUtils'; import * as IOUUtils from '@libs/IOUUtils'; import Navigation from '@libs/Navigation/Navigation'; @@ -8,9 +11,9 @@ import * as TransactionUtils from '@libs/TransactionUtils'; import MoneyRequestParticipantsSelector from '@pages/iou/request/MoneyTemporaryForRefactorRequestParticipantsSelector'; import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; -import type {Transaction} from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/IOU'; import StepScreenWrapper from './StepScreenWrapper'; import type {WithFullTransactionOrNotFoundProps} from './withFullTransactionOrNotFound'; @@ -19,8 +22,8 @@ import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotF import withWritableReportOrNotFound from './withWritableReportOrNotFound'; type IOURequestStepParticipantsOnyxProps = { - /** The transaction object being modified in Onyx */ - transaction: OnyxEntry; + /** Whether the confirmation step should be skipped */ + skipConfirmation: OnyxEntry; }; type IOURequestStepParticipantsProps = IOURequestStepParticipantsOnyxProps & @@ -32,9 +35,11 @@ function IOURequestStepParticipants({ params: {iouType, reportID, transactionID, action}, }, transaction, + skipConfirmation, }: IOURequestStepParticipantsProps) { const participants = transaction?.participants; const {translate} = useLocalize(); + const styles = useThemeStyles(); const selectedReportID = useRef(reportID); const numberOfParticipants = useRef(participants?.length ?? 0); const iouRequestType = TransactionUtils.getRequestType(transaction); @@ -122,6 +127,14 @@ function IOURequestStepParticipants({ testID={IOURequestStepParticipants.displayName} includeSafeAreaPaddingBottom={false} > + {skipConfirmation && ( + + )} ({ + skipConfirmation: { + key: ({route}) => { + const transactionID = route.params.transactionID ?? 0; + return `${ONYXKEYS.COLLECTION.SKIP_CONFIRMATION}${transactionID}`; + }, + }, +})(IOURequestStepParticipants); + +export default withWritableReportOrNotFound(withFullTransactionOrNotFound(IOURequestStepParticipantsWithOnyx)); diff --git a/src/pages/tasks/NewTaskPage.tsx b/src/pages/tasks/NewTaskPage.tsx index 44cb485c0b06..9deb5b74c514 100644 --- a/src/pages/tasks/NewTaskPage.tsx +++ b/src/pages/tasks/NewTaskPage.tsx @@ -5,6 +5,7 @@ import {withOnyx} from 'react-native-onyx'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton'; +import FormHelpMessage from '@components/FormHelpMessage'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import MenuItem from '@components/MenuItem'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; @@ -52,6 +53,7 @@ function NewTaskPage({task, reports, personalDetails}: NewTaskPageProps) { const [errorMessage, setErrorMessage] = useState(''); const [parentReport, setParentReport] = useState>(null); + const hasDestinationError = task?.skipConfirmation && !task?.parentReportID; const isAllowedToCreateTask = useMemo(() => isEmptyObject(parentReport) || ReportUtils.isAllowedToComment(parentReport), [parentReport]); useEffect(() => { @@ -138,6 +140,14 @@ function NewTaskPage({task, reports, personalDetails}: NewTaskPageProps) { Navigation.goBack(ROUTES.NEW_TASK_DETAILS); }} /> + {hasDestinationError && ( + + )}