diff --git a/src/languages/en.ts b/src/languages/en.ts index 68204d26b599..7f05ea436837 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -742,6 +742,10 @@ const translations = { listOfChats: 'List of chats', saveTheWorld: 'Save the world', tooltip: 'Get started here!', + redirectToExpensifyClassicModal: { + title: 'Coming soon', + description: "We're fine-tuning a few more bits and pieces of New Expensify to accommodate your specific setup. In the meantime, head over to Expensify Classic.", + }, }, allSettingsScreen: { subscription: 'Subscription', diff --git a/src/languages/es.ts b/src/languages/es.ts index f769a6c37982..92ffd8728d97 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -736,6 +736,10 @@ const translations = { listOfChats: 'lista de chats', saveTheWorld: 'Salvar el mundo', tooltip: '¡Comienza aquí!', + redirectToExpensifyClassicModal: { + title: 'Próximamente', + description: 'Estamos ajustando algunos detalles de New Expensify para adaptarla a tu configuración específica. Mientras tanto, dirígete a Expensify Classic.', + }, }, allSettingsScreen: { subscription: 'Suscripcion', diff --git a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx index 0bb94c9b9ab2..69d5407260a8 100644 --- a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx +++ b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx @@ -6,6 +6,7 @@ import {View} from 'react-native'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import {useOnyx} from 'react-native-onyx'; import type {SvgProps} from 'react-native-svg'; +import ConfirmModal from '@components/ConfirmModal'; import FloatingActionButton from '@components/FloatingActionButton'; import * as Expensicons from '@components/Icon/Expensicons'; import type {PopoverMenuItem} from '@components/PopoverMenu'; @@ -168,6 +169,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl const [hasSeenTrackTraining] = useOnyx(ONYXKEYS.NVP_HAS_SEEN_TRACK_TRAINING); const [isCreateMenuActive, setIsCreateMenuActive] = useState(false); + const [modalVisible, setModalVisible] = useState(false); const fabRef = useRef(null); const {windowHeight} = useWindowDimensions(); const {shouldUseNarrowLayout} = useResponsiveLayout(); @@ -183,6 +185,18 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl const [hasSeenTour = false] = useOnyx(ONYXKEYS.NVP_ONBOARDING, { selector: hasSeenTourSelector, }); + /** + * There are scenarios where users who have not yet had their group workspace-chats in NewDot (isPolicyExpenseChatEnabled). In those scenarios, things can get confusing if they try to submit/track expenses. To address this, we block them from Creating, Tracking, Submitting expenses from NewDot if they are: + * 1. on at least one group policy + * 2. none of the group policies they are a member of have isPolicyExpenseChatEnabled=true + */ + const shouldRedirectToExpensifyClassic = useMemo(() => { + const groupPolicies = Object.values(allPolicies ?? {}).filter((policy) => ReportUtils.isGroupPolicy(policy?.type ?? '')); + if (groupPolicies.length === 0) { + return false; + } + return !groupPolicies.some((policy) => !!policy?.isPolicyExpenseChatEnabled); + }, [allPolicies]); const quickActionAvatars = useMemo(() => { if (quickActionReport) { @@ -348,15 +362,20 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl { icon: getIconForAction(CONST.IOU.TYPE.CREATE), text: translate('iou.createExpense'), + shouldCallAfterModalHide: shouldRedirectToExpensifyClassic, onSelected: () => - interceptAnonymousUser(() => + interceptAnonymousUser(() => { + if (shouldRedirectToExpensifyClassic) { + setModalVisible(true); + return; + } IOU.startMoneyRequest( CONST.IOU.TYPE.CREATE, // When starting to create an expense from the global FAB, there is not an existing report yet. A random optimistic reportID is generated and used // for all of the routes in the creation flow. ReportUtils.generateReportID(), - ), - ), + ); + }), }, ]; } @@ -367,16 +386,21 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl { icon: getIconForAction(CONST.IOU.TYPE.TRACK), text: translate('iou.trackExpense'), + shouldCallAfterModalHide: shouldRedirectToExpensifyClassic, onSelected: () => { - interceptAnonymousUser(() => + if (shouldRedirectToExpensifyClassic) { + setModalVisible(true); + return; + } + interceptAnonymousUser(() => { IOU.startMoneyRequest( CONST.IOU.TYPE.TRACK, // When starting to create a track expense from the global FAB, we need to retrieve selfDM reportID. // If it doesn't exist, we generate a random optimistic reportID and use it for all of the routes in the creation flow. // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing ReportUtils.findSelfDMReportID() || ReportUtils.generateReportID(), - ), - ); + ); + }); if (!hasSeenTrackTraining && !isOffline) { setTimeout(() => { Navigation.navigate(ROUTES.TRACK_TRAINING_MODAL); @@ -389,18 +413,24 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl { icon: getIconForAction(CONST.IOU.TYPE.REQUEST), text: translate('iou.submitExpense'), + shouldCallAfterModalHide: shouldRedirectToExpensifyClassic, onSelected: () => - interceptAnonymousUser(() => + interceptAnonymousUser(() => { + if (shouldRedirectToExpensifyClassic) { + setModalVisible(true); + return; + } + IOU.startMoneyRequest( CONST.IOU.TYPE.SUBMIT, // When starting to create an expense from the global FAB, there is not an existing report yet. A random optimistic reportID is generated and used // for all of the routes in the creation flow. ReportUtils.generateReportID(), - ), - ), + ); + }), }, ]; - }, [canUseCombinedTrackSubmit, translate, selfDMReportID, hasSeenTrackTraining, isOffline]); + }, [canUseCombinedTrackSubmit, translate, selfDMReportID, hasSeenTrackTraining, isOffline, shouldRedirectToExpensifyClassic]); const quickActionMenuItems = useMemo(() => { // Define common properties in baseQuickAction @@ -493,15 +523,21 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl { icon: Expensicons.InvoiceGeneric, text: translate('workspace.invoices.sendInvoice'), + shouldCallAfterModalHide: shouldRedirectToExpensifyClassic, onSelected: () => - interceptAnonymousUser(() => + interceptAnonymousUser(() => { + if (shouldRedirectToExpensifyClassic) { + setModalVisible(true); + return; + } + IOU.startMoneyRequest( CONST.IOU.TYPE.INVOICE, // When starting to create an invoice from the global FAB, there is not an existing report yet. A random optimistic reportID is generated and used // for all of the routes in the creation flow. ReportUtils.generateReportID(), - ), - ), + ); + }), }, ] : []), @@ -548,6 +584,18 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl withoutOverlay anchorRef={fabRef} /> + { + setModalVisible(false); + Link.openOldDotLink(CONST.OLDDOT_URLS.INBOX); + }} + onCancel={() => setModalVisible(false)} + title={translate('sidebarScreen.redirectToExpensifyClassicModal.title')} + confirmText={translate('exitSurvey.goToExpensifyClassic')} + cancelText={translate('common.cancel')} + />