Skip to content
Open
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
55 changes: 52 additions & 3 deletions src/pages/workspace/travel/GetStartedTravel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,75 @@ import BookTravelButton from '@components/BookTravelButton';
import FeatureList from '@components/FeatureList';
import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import usePermissions from '@hooks/usePermissions';
import useThemeStyles from '@hooks/useThemeStyles';
import {getEligibleBankAccountsForCard} from '@libs/CardUtils';
import Navigation from '@libs/Navigation/Navigation';
import {hasInProgressUSDVBBA, REIMBURSEMENT_ACCOUNT_ROUTE_NAMES} from '@libs/ReimbursementAccountUtils';
import colors from '@styles/theme/colors';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';

type GetStartedTravelProps = {
policyID: string;
};

function GetStartedTravel({policyID}: GetStartedTravelProps) {
const handleCtaPress = () => {};

const {translate} = useLocalize();
const styles = useThemeStyles();
const illustrations = useMemoizedLazyIllustrations(['PendingTravel'] as const);
// TODO: Remove this when Travel Invoicing feature is fully implemented
const {isBetaEnabled} = usePermissions();

const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST, {canBeMissing: false});
const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {canBeMissing: false});

const isTravelInvoicingEnabled = isBetaEnabled(CONST.BETAS.TRAVEL_INVOICING);
const isSetupUnfinished = hasInProgressUSDVBBA(reimbursementAccount?.achData);
const eligibleBankAccounts = getEligibleBankAccountsForCard(bankAccountList);

const handleCtaPress = () => {
// Do nothing if beta is not enabled (existing noop behavior)
if (!isTravelInvoicingEnabled) {
return;
}

// If no bank accounts or setup is unfinished, start the add bank account flow
if (!eligibleBankAccounts.length || isSetupUnfinished) {
Navigation.navigate(ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute(policyID, REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.NEW, ROUTES.WORKSPACE_TRAVEL.getRoute(policyID)));
return;
}

// If bank accounts exist, navigate to settlement account selection
Navigation.navigate(ROUTES.WORKSPACE_TRAVEL_SETTINGS_ACCOUNT.getRoute(policyID));
};

// If Travel Invoicing beta is enabled, show a simple button that starts the setup flow
if (isTravelInvoicingEnabled) {
return (
<FeatureList
menuItems={[]}
title={translate('workspace.moreFeatures.travel.getStarted.title')}
subtitle={translate('workspace.moreFeatures.travel.getStarted.subtitle')}
ctaText={translate('workspace.moreFeatures.travel.getStarted.ctaText')}
onCtaPress={handleCtaPress}
illustrationBackgroundColor={colors.tangerine700}
illustration={illustrations.PendingTravel}
illustrationStyle={styles.travelCardIllustration}
illustrationContainerStyle={[styles.emptyStateCardIllustrationContainer, styles.justifyContentCenter]}
titleStyles={styles.textHeadlineH1}
/>
);
}
// TODO-END

return (
<FeatureList
menuItems={[]}
title={translate('workspace.moreFeatures.travel.getStarted.title')}
subtitle={translate('workspace.moreFeatures.travel.getStarted.subtitle')}
onCtaPress={handleCtaPress}
illustrationBackgroundColor={colors.tangerine700}
illustration={illustrations.PendingTravel}
illustrationStyle={styles.travelCardIllustration}
Expand Down
15 changes: 12 additions & 3 deletions src/pages/workspace/travel/PolicyTravelPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import Navigation from '@libs/Navigation/Navigation';
import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
import type {WorkspaceSplitNavigatorParamList} from '@libs/Navigation/types';
import {getTravelStep} from '@libs/PolicyUtils';
import {getTravelInvoicingCardSettingsKey, hasTravelInvoicingSettlementAccount} from '@libs/TravelInvoicingUtils';
import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
Expand Down Expand Up @@ -48,6 +49,10 @@ function WorkspaceTravelPage({
const {login: currentUserLogin} = useCurrentUserPersonalDetails();
const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: false});

// Get Travel Invoicing card settings to check for settlement account
const [cardSettings] = useOnyx(getTravelInvoicingCardSettingsKey(workspaceAccountID), {canBeMissing: true});
const hasSettlementAccount = hasTravelInvoicingSettlementAccount(cardSettings);

const fetchTravelData = useCallback(() => {
openPolicyTravelPage(policyID, workspaceAccountID);
}, [policyID, workspaceAccountID]);
Expand All @@ -72,11 +77,15 @@ function WorkspaceTravelPage({
const step = getTravelStep(policy, travelSettings, isBetaEnabled(CONST.BETAS.IS_TRAVEL_VERIFIED), policies, currentUserLogin);

const mainContent = (() => {
// TODO: Remove this conditional when Travel Invoicing feature is fully implemented
if (isTravelInvoicingEnabled) {
if (!hasSettlementAccount) {
return <GetStartedTravel policyID={policyID} />;
}
return <WorkspaceTravelInvoicingSection policyID={policyID} />;
}
Comment on lines 79 to +86

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve pending-review state when Travel Invoicing beta is on

When a workspace has Travel Invoicing beta enabled but the travel request is still pending (i.e., getTravelStep would return REVIEWING_REQUEST because lastTravelSignupRequestTime is set and the travel-verified beta is off), this unconditional isTravelInvoicingEnabled branch short-circuits the switch and makes the ReviewingRequest screen unreachable. That regresses the legacy flow by hiding the “reviewing request” status for those users and pushes them into the Travel Invoicing setup even though their travel access hasn’t been approved. Consider checking step before this beta gate or explicitly allowing the REVIEWING_REQUEST branch to render when applicable.

Useful? React with 👍 / 👎.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@blimpich Do you think this is a concern or the previously existing Travel section was no-op anyway ? Or people are actually using the old Travel section in production ? If that's the case we might want to lock this PRs changes to dev / adhoc / staging only - let me know!

switch (step) {
case CONST.TRAVEL.STEPS.BOOK_OR_MANAGE_YOUR_TRIP:
if (isTravelInvoicingEnabled) {
return <WorkspaceTravelInvoicingSection policyID={policyID} />;
}
return <BookOrManageYourTrip policyID={policyID} />;
case CONST.TRAVEL.STEPS.REVIEWING_REQUEST:
return <ReviewingRequest />;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,8 @@ function WorkspaceTravelInvoicingSection({policyID}: WorkspaceTravelInvoicingSec
</Section>
);

// If Travel Invoicing is not enabled or no settlement account is configured
// show the BookOrManageYourTrip component as fallback
if (!isTravelInvoicingEnabled || !hasSettlementAccount) {
// If Travel Invoicing beta is not enabled, show the BookOrManageYourTrip component as fallback (before Travel Invoicing feature)
if (!isTravelInvoicingEnabled) {
return <BookOrManageYourTrip policyID={policyID} />;
}

Expand All @@ -196,6 +195,7 @@ function WorkspaceTravelInvoicingSection({policyID}: WorkspaceTravelInvoicingSec
<Section
title={translate('workspace.moreFeatures.travel.travelInvoicing.travelBookingSection.title')}
subtitle={translate('workspace.moreFeatures.travel.travelInvoicing.travelBookingSection.subtitle')}
subtitleStyles={styles.mb6}
isCentralPane
subtitleMuted
>
Expand Down
Loading