diff --git a/assets/images/treasure-chest-green-with-sparkle.svg b/assets/images/treasure-chest-green-with-sparkle.svg
new file mode 100644
index 000000000000..6b98a1e74cf5
--- /dev/null
+++ b/assets/images/treasure-chest-green-with-sparkle.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index 96dc465789fe..e0056fcdd775 100755
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -32,6 +32,8 @@ const USE_EXPENSIFY_URL = 'https://use.expensify.com';
const EXPENSIFY_MOBILE_URL = 'https://expensify.com/mobile';
const EXPENSIFY_URL = 'https://www.expensify.com';
const UBER_CONNECT_URL = 'https://business-integrations.uber.com/connect';
+const XERO_PARTNER_LINK = 'https://xero5440.partnerlinks.io/uzfjy4uegog2-v0pj1v';
+const UBER_TERMS_LINK = 'https://www.uber.com/us/en/business/sign-up/terms/expense-partners/';
const PLATFORM_OS_MACOS = 'Mac OS';
const PLATFORM_IOS = 'iOS';
const ANDROID_PACKAGE_NAME = 'org.me.mobiexpensifyg';
@@ -445,6 +447,8 @@ const CONST = {
NEW_EXPENSIFY_URL: ACTIVE_EXPENSIFY_URL,
UBER_CONNECT_URL,
+ XERO_PARTNER_LINK,
+ UBER_TERMS_LINK,
APP_DOWNLOAD_LINKS: {
ANDROID: `https://play.google.com/store/apps/details?id=${ANDROID_PACKAGE_NAME}`,
IOS: 'https://apps.apple.com/us/app/expensify-travel-expense/id471713959',
diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index 5119da278a08..a468a2c79dce 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -2987,6 +2987,10 @@ const ROUTES = {
return `workspaces/${policyID}/accounting/xero/advanced` as const;
},
},
+ POLICY_ACCOUNTING_CLAIM_OFFER: {
+ route: 'workspaces/:policyID/accounting/claim-offer/:integration',
+ getRoute: (policyID: string, integration: string) => `workspaces/${policyID}/accounting/claim-offer/${integration}` as const,
+ },
POLICY_ACCOUNTING_XERO_AUTO_SYNC: {
route: 'workspaces/:policyID/accounting/xero/advanced/autosync',
getRoute: (policyID: string | undefined, backTo?: string) => {
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index 590fb002eb3d..c224566c44f2 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -498,6 +498,7 @@ const SCREENS = {
QUICKBOOKS_DESKTOP_CUSTOMERS_DISPLAYED_AS: 'Policy_Accounting_Quickbooks_Desktop_Import_Customers_Displayed_As',
QUICKBOOKS_DESKTOP_ITEMS: 'Policy_Accounting_Quickbooks_Desktop_Import_Items',
XERO_IMPORT: 'Policy_Accounting_Xero_Import',
+ CLAIM_OFFER: 'Policy_Accounting_Claim_Offer',
XERO_ORGANIZATION: 'Policy_Accounting_Xero_Customers',
XERO_CHART_OF_ACCOUNTS: 'Policy_Accounting_Xero_Import_Chart_Of_Accounts',
XERO_CUSTOMER: 'Policy_Accounting_Xero_Import_Customer',
diff --git a/src/components/Icon/chunks/expensify-icons.chunk.ts b/src/components/Icon/chunks/expensify-icons.chunk.ts
index 71447b27039c..02e26682bc7a 100644
--- a/src/components/Icon/chunks/expensify-icons.chunk.ts
+++ b/src/components/Icon/chunks/expensify-icons.chunk.ts
@@ -215,6 +215,7 @@ import ThumbsUp from '@assets/images/thumbs-up.svg';
import Train from '@assets/images/train.svg';
import Transfer from '@assets/images/transfer.svg';
import Trashcan from '@assets/images/trashcan.svg';
+import TreasureChestGreenWithSparkle from '@assets/images/treasure-chest-green-with-sparkle.svg';
import TreasureChest from '@assets/images/treasure-chest.svg';
import Unlock from '@assets/images/unlock.svg';
import UploadAlt from '@assets/images/upload-alt.svg';
@@ -471,6 +472,7 @@ const Expensicons = {
XeroExport,
ArrowCircleClockwise,
LuggageWithLines,
+ TreasureChestGreenWithSparkle,
};
// Create the ExpensifyIcons object from the imported Expensicons
diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx
index f11abee49c16..6d6d3a807f98 100644
--- a/src/components/MenuItem.tsx
+++ b/src/components/MenuItem.tsx
@@ -87,6 +87,9 @@ type MenuItemBaseProps = ForwardedFSClassProps &
/** Whether the badge should be shown as success */
badgeSuccess?: boolean;
+ /** Callback to fire when the badge is pressed */
+ onBadgePress?: (event?: GestureResponderEvent | KeyboardEvent) => void;
+
/** Used to apply offline styles to child text components */
style?: StyleProp;
@@ -397,6 +400,12 @@ type MenuItemBaseProps = ForwardedFSClassProps &
/** Whether the screen containing the item is focused */
isFocused?: boolean;
+
+ /** Whether to show the badge in a separate row */
+ shouldShowBadgeInSeparateRow?: boolean;
+
+ /** Whether to show the badge below the title */
+ shouldShowBadgeBelow?: boolean;
};
type MenuItemProps = (IconProps | AvatarProps | NoIcon) & MenuItemBaseProps;
@@ -416,6 +425,9 @@ function MenuItem({
badgeText,
badgeIcon,
badgeSuccess,
+ onBadgePress,
+ shouldShowBadgeInSeparateRow = false,
+ shouldShowBadgeBelow = false,
style,
wrapperStyle,
titleWrapperStyle,
@@ -914,18 +926,30 @@ function MenuItem({
)}
+ {!!badgeText && shouldShowBadgeBelow && (
+
+ )}
{furtherDetailsComponent}
{titleComponent}
- {!!badgeText && (
+ {!!badgeText && !shouldShowBadgeInSeparateRow && !shouldShowBadgeBelow && (
)}
{/* Since subtitle can be of type number, we should allow 0 to be shown */}
@@ -1007,6 +1031,16 @@ function MenuItem({
)}
+ {!!badgeText && shouldShowBadgeInSeparateRow && (
+
+ )}
{!!errorText && (
`Sind Sie sicher, dass Sie ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? 'diese Buchhaltungsintegration'} verbinden möchten? Dadurch werden alle bestehenden Buchhaltungsverbindungen entfernt.`,
enterCredentials: 'Geben Sie Ihre Anmeldedaten ein',
+ claimOffer: {
+ badgeText: 'Angebot verfügbar!',
+ xero: {
+ headline: '6 Monate kostenlos mit Xero!',
+ description: 'Neu bei Xero? Expensify-Kunden erhalten 6 Monate kostenlos. Fordern Sie Ihr Angebot unten an.',
+ connectButton: 'Mit Xero verbinden',
+ },
+ uber: {
+ headerTitle: 'Uber for Business',
+ headline: '5% Rabatt auf Uber-Fahrten',
+ description: `Aktivieren Sie Uber for Business über Expensify und sparen Sie 5% bei allen Geschäftsreisen bis Juni. Bedingungen gelten.`,
+ connectButton: 'Mit Uber for Business verbinden',
+ },
+ },
connections: {
syncStageName: ({stage}: SyncStageNameConnectionsParams) => {
switch (stage) {
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 9c5d7bf8c225..7c24af4207b2 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -5499,6 +5499,20 @@ const translations = {
CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? 'this accounting integration'
}? This will remove any existing accounting connections.`,
enterCredentials: 'Enter your credentials',
+ claimOffer: {
+ badgeText: 'Offer available!',
+ xero: {
+ headline: 'Get Xero free for 6 months!',
+ description: 'New to Xero? Expensify customers get 6 months free. Claim your offer below.',
+ connectButton: 'Connect to Xero',
+ },
+ uber: {
+ headerTitle: 'Uber for Business',
+ headline: 'Get 5% off Uber rides',
+ description: `Activate Uber for Business through Expensify and save 5% on all business rides through June. Terms apply.`,
+ connectButton: 'Connect to Uber for Business',
+ },
+ },
connections: {
syncStageName: ({stage}: SyncStageNameConnectionsParams) => {
switch (stage) {
diff --git a/src/languages/es.ts b/src/languages/es.ts
index cd72dbb083e8..3ba65aa05cdc 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -5197,6 +5197,21 @@ ${amount} para ${merchant} - ${date}`,
CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? 'esta integración contable'
}? Esto eliminará cualquier conexión contable existente.`,
enterCredentials: 'Ingresa tus credenciales',
+ claimOffer: {
+ badgeText: '¡Oferta disponible!',
+ xero: {
+ headline: '¡Obtén Xero gratis por 6 meses!',
+ description:
+ '¿Nuevo en Xero? Los clientes de Expensify obtienen 6 meses gratis. Reclama tu oferta a continuación.',
+ connectButton: 'Conectar con Xero',
+ },
+ uber: {
+ headerTitle: 'Uber for Business',
+ headline: 'Obtén 5% de descuento en viajes de Uber',
+ description: `Activa Uber for Business a través de Expensify y ahorra 5% en todos los viajes de negocios hasta junio. Aplican términos.`,
+ connectButton: 'Conectar con Uber for Business',
+ },
+ },
connections: {
syncStageName: ({stage}) => {
switch (stage) {
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 83e0b8ad8938..a16d2f5120f9 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -5605,6 +5605,21 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
connectPrompt: ({connectionName}: ConnectionNameParams) =>
`Voulez-vous vraiment connecter ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? 'cette intégration comptable'} ? Cela supprimera toutes les connexions comptables existantes.`,
enterCredentials: 'Saisissez vos identifiants',
+ claimOffer: {
+ badgeText: 'Offre disponible !',
+ xero: {
+ headline: 'Obtenez Xero gratuitement pendant 6 mois !',
+ description:
+ 'Nouveau sur Xero ? Les clients Expensify bénéficient de 6 mois gratuits. Réclamez votre offre ci-dessous.',
+ connectButton: 'Se connecter à Xero',
+ },
+ uber: {
+ headerTitle: 'Uber for Business',
+ headline: 'Obtenez 5% de réduction sur les trajets Uber',
+ description: `Activez Uber for Business via Expensify et économisez 5% sur tous les trajets professionnels jusqu\'en juin. Conditions applicables.`,
+ connectButton: 'Se connecter à Uber for Business',
+ },
+ },
connections: {
syncStageName: ({stage}: SyncStageNameConnectionsParams) => {
switch (stage) {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 6a6bd16c2987..06cbefc9ba95 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -5582,6 +5582,20 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
connectPrompt: ({connectionName}: ConnectionNameParams) =>
`Sei sicuro di voler collegare ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? 'questa integrazione contabile'}? Questo rimuoverà tutte le connessioni contabili esistenti.`,
enterCredentials: 'Inserisci le tue credenziali',
+ claimOffer: {
+ badgeText: 'Offerta disponibile!',
+ xero: {
+ headline: 'Ottieni Xero gratis per 6 mesi!',
+ description: 'Nuovo su Xero? I clienti Expensify ottengono 6 mesi gratuiti. Richiedi la tua offerta qui sotto.',
+ connectButton: 'Connetti a Xero',
+ },
+ uber: {
+ headerTitle: 'Uber for Business',
+ headline: 'Ottieni il 5% di sconto sui viaggi Uber',
+ description: `Attiva Uber for Business tramite Expensify e risparmia il 5% su tutti i viaggi di lavoro fino a giugno. Si applicano i termini.`,
+ connectButton: 'Connetti a Uber for Business',
+ },
+ },
connections: {
syncStageName: ({stage}: SyncStageNameConnectionsParams) => {
switch (stage) {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index d7ac0a9aace5..2abeeb767a37 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -5547,6 +5547,21 @@ _より詳しい手順については、[ヘルプサイトをご覧ください
connectPrompt: ({connectionName}: ConnectionNameParams) =>
`${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? 'この会計統合'} を接続してもよろしいですか?これにより、既存の会計連携はすべて削除されます。`,
enterCredentials: '認証情報を入力してください',
+ claimOffer: {
+ badgeText: 'オファー利用可能!',
+ xero: {
+ headline: 'Xero を6か月間無料で利用!',
+ description:
+ 'Xero を初めてご利用ですか?Expensify のお客様は6か月間無料でご利用いただけます。以下のオファーを獲得してください。',
+ connectButton: 'Xero に接続',
+ },
+ uber: {
+ headerTitle: 'Uber for Business',
+ headline: 'Uber の乗車で5%割引',
+ description: `Expensify を通じて Uber for Business を有効化すると、6月までのすべてのビジネス乗車で5%割引になります。条件が適用されます。`,
+ connectButton: 'Uber for Business に接続',
+ },
+ },
connections: {
syncStageName: ({stage}: SyncStageNameConnectionsParams) => {
switch (stage) {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 8b152871fef8..d49582c96e9a 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -5575,6 +5575,20 @@ _Voor gedetailleerdere instructies, [bezoek onze helpsite](${CONST.NETSUITE_IMPO
connectPrompt: ({connectionName}: ConnectionNameParams) =>
`Weet je zeker dat je ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? 'deze boekhoudkundige integratie'} wilt verbinden? Hierdoor worden alle bestaande boekhoudkoppelingen verwijderd.`,
enterCredentials: 'Voer je inloggegevens in',
+ claimOffer: {
+ badgeText: 'Aanbieding beschikbaar!',
+ xero: {
+ headline: 'Krijg 6 maanden gratis Xero!',
+ description: 'Nieuw bij Xero? Expensify-klanten krijgen 6 maanden gratis. Verzilver je aanbieding hieronder.',
+ connectButton: 'Verbinden met Xero',
+ },
+ uber: {
+ headerTitle: 'Uber for Business',
+ headline: 'Krijg 5% korting op Uber-ritten',
+ description: `Activeer Uber for Business via Expensify en bespaar 5% op alle zakelijke ritten tot en met juni. Voorwaarden zijn van toepassing.`,
+ connectButton: 'Verbinden met Uber for Business',
+ },
+ },
connections: {
syncStageName: ({stage}: SyncStageNameConnectionsParams) => {
switch (stage) {
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 197dc6db9f9f..366c8ff58244 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -5562,6 +5562,20 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
connectPrompt: ({connectionName}: ConnectionNameParams) =>
`Czy na pewno chcesz połączyć ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? 'to połączenie z systemem księgowym'}? Spowoduje to usunięcie wszystkich istniejących połączeń księgowych.`,
enterCredentials: 'Wprowadź swoje dane logowania',
+ claimOffer: {
+ badgeText: 'Oferta dostępna!',
+ xero: {
+ headline: 'Otrzymaj Xero za darmo na 6 miesięcy!',
+ description: 'Nowy w Xero? Klienci Expensify otrzymują 6 miesięcy za darmo. Odbierz swoją ofertę poniżej.',
+ connectButton: 'Połącz z Xero',
+ },
+ uber: {
+ headerTitle: 'Uber for Business',
+ headline: 'Otrzymaj 5% zniżki na przejazdy Uber',
+ description: `Aktywuj Uber for Business przez Expensify i zaoszczędź 5% na wszystkich przejazdach służbowych do czerwca. Obowiązują warunki.`,
+ connectButton: 'Połącz z Uber for Business',
+ },
+ },
connections: {
syncStageName: ({stage}: SyncStageNameConnectionsParams) => {
switch (stage) {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 565f0d4b3a06..445d5ad5ecae 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -5564,6 +5564,20 @@ _Para instruções mais detalhadas, [visite nosso site de ajuda](${CONST.NETSUIT
connectPrompt: ({connectionName}: ConnectionNameParams) =>
`Tem certeza de que deseja conectar ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? 'esta integração contábil'}? Isso removerá quaisquer conexões contábeis existentes.`,
enterCredentials: 'Insira suas credenciais',
+ claimOffer: {
+ badgeText: 'Oferta disponível!',
+ xero: {
+ headline: 'Obtenha Xero grátis por 6 meses!',
+ description: 'Novo no Xero? Clientes Expensify ganham 6 meses grátis. Resgate sua oferta abaixo.',
+ connectButton: 'Conectar ao Xero',
+ },
+ uber: {
+ headerTitle: 'Uber for Business',
+ headline: 'Obtenha 5% de desconto em viagens do Uber',
+ description: `Ative o Uber for Business através do Expensify e economize 5% em todas as viagens de negócios até junho. Termos se aplicam.`,
+ connectButton: 'Conectar ao Uber for Business',
+ },
+ },
connections: {
syncStageName: ({stage}: SyncStageNameConnectionsParams) => {
switch (stage) {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index a3a1bfea29c3..583ca7a9822e 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -5461,6 +5461,20 @@ _如需更详细的说明,请[访问我们的帮助网站](${CONST.NETSUITE_IM
connectPrompt: ({connectionName}: ConnectionNameParams) =>
`您确定要连接 ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? '此会计集成'} 吗?这将移除所有现有的会计连接。`,
enterCredentials: '请输入您的凭证',
+ claimOffer: {
+ badgeText: '优惠可用!',
+ xero: {
+ headline: '免费使用 Xero 6 个月!',
+ description: '首次使用 Xero?Expensify 客户可免费使用 6 个月。请在下方领取您的优惠。',
+ connectButton: '连接到 Xero',
+ },
+ uber: {
+ headerTitle: 'Uber for Business',
+ headline: 'Uber 乘车享受 5% 折扣',
+ description: `通过 Expensify 激活 Uber for Business,在 6 月之前的所有商务乘车均可享受 5% 折扣。适用条款。`,
+ connectButton: '连接到 Uber for Business',
+ },
+ },
connections: {
syncStageName: ({stage}: SyncStageNameConnectionsParams) => {
switch (stage) {
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index 0ccc117e8a9b..20061d6c5494 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -576,6 +576,7 @@ const SettingsModalStackNavigator = createModalStackNavigator('../../../../pages/workspace/accounting/qbo/advanced/QuickbooksInvoiceAccountSelectPage').default,
[SCREENS.WORKSPACE.ACCOUNTING.XERO_IMPORT]: () => require('../../../../pages/workspace/accounting/xero/XeroImportPage').default,
+ [SCREENS.WORKSPACE.ACCOUNTING.CLAIM_OFFER]: () => require('../../../../pages/workspace/accounting/ClaimOfferPage').default,
[SCREENS.WORKSPACE.ACCOUNTING.XERO_ORGANIZATION]: () => require('../../../../pages/workspace/accounting/xero/XeroOrganizationConfigurationPage').default,
[SCREENS.WORKSPACE.ACCOUNTING.XERO_CHART_OF_ACCOUNTS]: () => require('../../../../pages/workspace/accounting/xero/import/XeroChartOfAccountsPage').default,
[SCREENS.WORKSPACE.ACCOUNTING.XERO_CUSTOMER]: () => require('../../../../pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage').default,
diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
index 3ec54d858f82..6eae43d74ff2 100755
--- a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
+++ b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
@@ -101,6 +101,7 @@ const WORKSPACE_TO_RHP: Partial['config'] = {
[SCREENS.WORKSPACE.ACCOUNTING.XERO_EXPORT_PURCHASE_BILL_DATE_SELECT]: {path: ROUTES.POLICY_ACCOUNTING_XERO_EXPORT_PURCHASE_BILL_DATE_SELECT.route},
[SCREENS.WORKSPACE.ACCOUNTING.XERO_EXPORT_BANK_ACCOUNT_SELECT]: {path: ROUTES.POLICY_ACCOUNTING_XERO_EXPORT_BANK_ACCOUNT_SELECT.route},
[SCREENS.WORKSPACE.ACCOUNTING.XERO_ADVANCED]: {path: ROUTES.POLICY_ACCOUNTING_XERO_ADVANCED.route},
+ [SCREENS.WORKSPACE.ACCOUNTING.CLAIM_OFFER]: {path: ROUTES.POLICY_ACCOUNTING_CLAIM_OFFER.route},
[SCREENS.WORKSPACE.ACCOUNTING.XERO_AUTO_SYNC]: {path: ROUTES.POLICY_ACCOUNTING_XERO_AUTO_SYNC.route},
[SCREENS.WORKSPACE.ACCOUNTING.XERO_ACCOUNTING_METHOD]: {path: ROUTES.POLICY_ACCOUNTING_XERO_ACCOUNTING_METHOD.route},
[SCREENS.WORKSPACE.ACCOUNTING.XERO_BILL_STATUS_SELECTOR]: {path: ROUTES.POLICY_ACCOUNTING_XERO_BILL_STATUS_SELECTOR.route},
@@ -835,7 +836,6 @@ const config: LinkingOptions['config'] = {
[SCREENS.WORKSPACE.RECEIPT_PARTNERS_CHANGE_BILLING_ACCOUNT]: {
path: ROUTES.WORKSPACE_RECEIPT_PARTNERS_CHANGE_BILLING_ACCOUNT.route,
},
-
[SCREENS.WORKSPACE.RECEIPT_PARTNERS_INVITE_EDIT]: {
path: ROUTES.WORKSPACE_RECEIPT_PARTNERS_INVITE_EDIT.route,
screens: {
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index 0322c1e09c33..34702a3f643d 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -815,6 +815,10 @@ type SettingsNavigatorParamList = {
[SCREENS.WORKSPACE.ACCOUNTING.XERO_ADVANCED]: {
policyID: string;
};
+ [SCREENS.WORKSPACE.ACCOUNTING.CLAIM_OFFER]: {
+ policyID: string;
+ integration: string;
+ };
[SCREENS.WORKSPACE.ACCOUNTING.XERO_BILL_STATUS_SELECTOR]: {
policyID: string;
// eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
diff --git a/src/pages/workspace/accounting/ClaimOfferPage.tsx b/src/pages/workspace/accounting/ClaimOfferPage.tsx
new file mode 100644
index 000000000000..00764ca49b03
--- /dev/null
+++ b/src/pages/workspace/accounting/ClaimOfferPage.tsx
@@ -0,0 +1,163 @@
+import React from 'react';
+import {View} from 'react-native';
+import Button from '@components/Button';
+import FixedFooter from '@components/FixedFooter';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import Icon from '@components/Icon';
+import RenderHTML from '@components/RenderHTML';
+import ScreenWrapper from '@components/ScreenWrapper';
+import ScrollView from '@components/ScrollView';
+import Text from '@components/Text';
+import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
+import useLocalize from '@hooks/useLocalize';
+import useNetwork from '@hooks/useNetwork';
+import useThemeStyles from '@hooks/useThemeStyles';
+import {openExternalLink} from '@libs/actions/Link';
+import Navigation from '@libs/Navigation/Navigation';
+import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import type {SettingsNavigatorParamList} from '@navigation/types';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
+import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections';
+import withPolicyConnections from '@pages/workspace/withPolicyConnections';
+import CONST from '@src/CONST';
+import type SCREENS from '@src/SCREENS';
+import type {PolicyFeatureName} from '@src/types/onyx/Policy';
+import {AccountingContextProvider, useAccountingContext} from './AccountingContext';
+
+type IntegrationType = typeof CONST.POLICY.CONNECTIONS.NAME.XERO | typeof CONST.POLICY.RECEIPT_PARTNERS.NAME.UBER;
+
+type IntegrationConfig = {
+ headerTitle: string;
+ headline: string;
+ descriptionHtml: string;
+ claimOfferLink?: string;
+ connectButtonText: string;
+ connectionName: string;
+ featureName: PolicyFeatureName;
+ onConnect: () => void;
+};
+
+type ClaimOfferPageProps = WithPolicyConnectionsProps & PlatformStackScreenProps;
+
+function ClaimOfferPage({route, policy}: ClaimOfferPageProps) {
+ const {integration, policyID} = route.params;
+ const styles = useThemeStyles();
+ const {translate} = useLocalize();
+ const {isOffline} = useNetwork();
+ const {startIntegrationFlow} = useAccountingContext();
+ const expensifyIcons = useMemoizedLazyExpensifyIcons(['TreasureChestGreenWithSparkle'] as const);
+ const integrations = policy?.receiptPartners;
+
+ const integrationConfig: Record = {
+ xero: {
+ headerTitle: translate('workspace.accounting.xero'),
+ headline: translate('workspace.accounting.claimOffer.xero.headline'),
+ descriptionHtml: translate('workspace.accounting.claimOffer.xero.description'),
+ claimOfferLink: CONST.XERO_PARTNER_LINK,
+ connectButtonText: translate('workspace.accounting.claimOffer.xero.connectButton'),
+ connectionName: CONST.POLICY.CONNECTIONS.NAME.XERO,
+ featureName: CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED,
+ onConnect: () => {
+ startIntegrationFlow({name: CONST.POLICY.CONNECTIONS.NAME.XERO});
+ },
+ },
+ uber: {
+ headerTitle: translate('workspace.accounting.claimOffer.uber.headerTitle'),
+ headline: translate('workspace.accounting.claimOffer.uber.headline'),
+ descriptionHtml: translate('workspace.accounting.claimOffer.uber.description'),
+ connectButtonText: translate('workspace.accounting.claimOffer.uber.connectButton'),
+ connectionName: CONST.POLICY.RECEIPT_PARTNERS.NAME.UBER,
+ featureName: CONST.POLICY.MORE_FEATURES.ARE_RECEIPT_PARTNERS_ENABLED,
+ onConnect: () => {
+ openExternalLink(`${CONST.UBER_CONNECT_URL}?${integrations?.uber?.connectFormData}`);
+ },
+ },
+ };
+
+ const config = integrationConfig[integration as IntegrationType];
+
+ const handleClaimOffer = () => {
+ if (!config.claimOfferLink) {
+ return;
+ }
+ openExternalLink(config.claimOfferLink);
+ };
+
+ const handleConnect = () => {
+ config.onConnect();
+ };
+
+ const buttons = (
+
+ {!!config.claimOfferLink && (
+
+ )}
+
+
+ );
+
+ return (
+
+
+ Navigation.goBack()}
+ />
+
+
+
+
+
+
+ {config.headline}
+
+
+
+
+
+
+ {buttons}
+
+
+ );
+}
+
+ClaimOfferPage.displayName = 'ClaimOfferPage';
+
+function ClaimOfferPageWrapper(props: ClaimOfferPageProps) {
+ return (
+
+
+
+ );
+}
+export default withPolicyConnections(ClaimOfferPageWrapper);
diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx
index d5ae9be4a3e9..dbb0da02177b 100644
--- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx
+++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx
@@ -288,6 +288,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) {
return undefined;
}
+ const isXero = integration === CONST.POLICY.CONNECTIONS.NAME.XERO;
const iconProps = integrationData?.icon
? {
icon: integrationData.icon,
@@ -301,6 +302,15 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) {
wrapperStyle: [styles.sectionMenuItemTopDescription],
shouldShowRightComponent: true,
title: integrationData?.title,
+ badgeText: isXero ? translate('workspace.accounting.claimOffer.badgeText') : undefined,
+ onBadgePress: isXero
+ ? () => {
+ Navigation.navigate(ROUTES.POLICY_ACCOUNTING_CLAIM_OFFER.getRoute(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO));
+ }
+ : undefined,
+ badgeStyle: styles.mr3,
+ badgeSuccess: isXero,
+ shouldShowBadgeBelow: shouldUseNarrowLayout,
rightComponent: (