diff --git a/assets/images/simple-illustrations/simple-illustration__commentbubbles.svg b/assets/images/simple-illustrations/simple-illustration__commentbubbles.svg
new file mode 100644
index 000000000000..829d3ee2e3fe
--- /dev/null
+++ b/assets/images/simple-illustrations/simple-illustration__commentbubbles.svg
@@ -0,0 +1,22 @@
+
+
+
diff --git a/assets/images/simple-illustrations/simple-illustration__hourglass.svg b/assets/images/simple-illustrations/simple-illustration__hourglass.svg
new file mode 100644
index 000000000000..539e1e45b795
--- /dev/null
+++ b/assets/images/simple-illustrations/simple-illustration__hourglass.svg
@@ -0,0 +1,56 @@
+
+
+
diff --git a/assets/images/simple-illustrations/simple-illustration__trashcan.svg b/assets/images/simple-illustrations/simple-illustration__trashcan.svg
new file mode 100644
index 000000000000..4e66efa0a67e
--- /dev/null
+++ b/assets/images/simple-illustrations/simple-illustration__trashcan.svg
@@ -0,0 +1,52 @@
+
+
+
diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index 1663f0295b9e..b6e62814466b 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -479,6 +479,7 @@ const ROUTES = {
route: 'referral/:contentType',
getRoute: (contentType: string) => `referral/${contentType}` as const,
},
+ PROCESS_MONEY_REQUEST_HOLD: 'hold-request-educational',
} as const;
export {getUrlWithBackToParam};
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index 91c4153bacd2..703cb309d641 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -108,6 +108,7 @@ const SCREENS = {
ROOM_MEMBERS: 'RoomMembers',
ROOM_INVITE: 'RoomInvite',
REFERRAL: 'Referral',
+ PROCESS_MONEY_REQUEST_HOLD: 'ProcessMoneyRequestHold',
},
SIGN_IN_WITH_APPLE_DESKTOP: 'AppleSignInDesktop',
SIGN_IN_WITH_GOOGLE_DESKTOP: 'GoogleSignInDesktop',
@@ -231,6 +232,7 @@ const SCREENS = {
SIGN_IN_ROOT: 'SignIn_Root',
DETAILS_ROOT: 'Details_Root',
PROFILE_ROOT: 'Profile_Root',
+ PROCESS_MONEY_REQUEST_HOLD_ROOT: 'ProcessMoneyRequestHold_Root',
REPORT_WELCOME_MESSAGE_ROOT: 'Report_WelcomeMessage_Root',
REPORT_PARTICIPANTS_ROOT: 'ReportParticipants_Root',
ROOM_MEMBERS_ROOT: 'RoomMembers_Root',
diff --git a/src/components/HoldMenuSectionList.tsx b/src/components/HoldMenuSectionList.tsx
new file mode 100644
index 000000000000..9a9857f037f2
--- /dev/null
+++ b/src/components/HoldMenuSectionList.tsx
@@ -0,0 +1,78 @@
+import React from 'react';
+import {ImageSourcePropType, View} from 'react-native';
+import {SvgProps} from 'react-native-svg';
+import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
+import variables from '@styles/variables';
+import {TranslationPaths} from '@src/languages/types';
+import Icon from './Icon';
+import * as Illustrations from './Icon/Illustrations';
+import Text from './Text';
+
+type HoldMenuSection = {
+ /** The icon supplied with the section */
+ icon: React.FC | ImageSourcePropType;
+
+ /** Translation key for the title */
+ titleTranslationKey: TranslationPaths;
+
+ /** Translation key for the description */
+ descriptionTranslationKey: TranslationPaths;
+};
+
+function HoldMenuSectionList() {
+ const {translate} = useLocalize();
+ const styles = useThemeStyles();
+
+ const holdMenuSections: HoldMenuSection[] = [
+ {
+ icon: Illustrations.Hourglass,
+ titleTranslationKey: 'iou.whatIsHoldTitle',
+ descriptionTranslationKey: 'iou.whatIsHoldExplain',
+ },
+ {
+ icon: Illustrations.CommentBubbles,
+ titleTranslationKey: 'iou.holdIsTemporaryTitle',
+ descriptionTranslationKey: 'iou.holdIsTemporaryExplain',
+ },
+ {
+ icon: Illustrations.TrashCan,
+ titleTranslationKey: 'iou.deleteHoldTitle',
+ descriptionTranslationKey: 'iou.deleteHoldExplain',
+ },
+ ];
+
+ return (
+ <>
+ {holdMenuSections.map((section, i) => (
+
+
+
+ {translate(section.titleTranslationKey)}
+
+ {translate(section.descriptionTranslationKey)}
+
+
+
+ ))}
+ >
+ );
+}
+
+HoldMenuSectionList.displayName = 'HoldMenuSectionList';
+
+export type {HoldMenuSection};
+
+export default HoldMenuSectionList;
diff --git a/src/components/Icon/Illustrations.ts b/src/components/Icon/Illustrations.ts
index 1e574504001d..954c8d0392fc 100644
--- a/src/components/Icon/Illustrations.ts
+++ b/src/components/Icon/Illustrations.ts
@@ -32,6 +32,7 @@ import BigRocket from '@assets/images/simple-illustrations/simple-illustration__
import PinkBill from '@assets/images/simple-illustrations/simple-illustration__bill.svg';
import ChatBubbles from '@assets/images/simple-illustrations/simple-illustration__chatbubbles.svg';
import CoffeeMug from '@assets/images/simple-illustrations/simple-illustration__coffeemug.svg';
+import CommentBubbles from '@assets/images/simple-illustrations/simple-illustration__commentbubbles.svg';
import ConciergeBubble from '@assets/images/simple-illustrations/simple-illustration__concierge-bubble.svg';
import ConciergeNew from '@assets/images/simple-illustrations/simple-illustration__concierge.svg';
import CreditCardsNew from '@assets/images/simple-illustrations/simple-illustration__credit-cards.svg';
@@ -39,6 +40,7 @@ import EmailAddress from '@assets/images/simple-illustrations/simple-illustratio
import HandCard from '@assets/images/simple-illustrations/simple-illustration__handcard.svg';
import HandEarth from '@assets/images/simple-illustrations/simple-illustration__handearth.svg';
import HotDogStand from '@assets/images/simple-illustrations/simple-illustration__hotdogstand.svg';
+import Hourglass from '@assets/images/simple-illustrations/simple-illustration__hourglass.svg';
import InvoiceBlue from '@assets/images/simple-illustrations/simple-illustration__invoice.svg';
import LockOpen from '@assets/images/simple-illustrations/simple-illustration__lockopen.svg';
import Luggage from '@assets/images/simple-illustrations/simple-illustration__luggage.svg';
@@ -53,6 +55,7 @@ import ShieldYellow from '@assets/images/simple-illustrations/simple-illustratio
import SmallRocket from '@assets/images/simple-illustrations/simple-illustration__smallrocket.svg';
import ThumbsUpStars from '@assets/images/simple-illustrations/simple-illustration__thumbsupstars.svg';
import TrackShoe from '@assets/images/simple-illustrations/simple-illustration__track-shoe.svg';
+import TrashCan from '@assets/images/simple-illustrations/simple-illustration__trashcan.svg';
import TreasureChest from '@assets/images/simple-illustrations/simple-illustration__treasurechest.svg';
export {
@@ -111,5 +114,8 @@ export {
Hands,
HandEarth,
SmartScan,
+ Hourglass,
+ CommentBubbles,
+ TrashCan,
TeleScope,
};
diff --git a/src/components/ProcessMoneyRequestHoldMenu.tsx b/src/components/ProcessMoneyRequestHoldMenu.tsx
new file mode 100644
index 000000000000..be72fdb98a8b
--- /dev/null
+++ b/src/components/ProcessMoneyRequestHoldMenu.tsx
@@ -0,0 +1,66 @@
+import React from 'react';
+import {View} from 'react-native';
+import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
+import Button from './Button';
+import HoldMenuSectionList from './HoldMenuSectionList';
+import {PopoverAnchorPosition} from './Modal/types';
+import Popover from './Popover';
+import {AnchorAlignment} from './Popover/types';
+import Text from './Text';
+import TextPill from './TextPill';
+
+type ProcessMoneyRequestHoldMenuProps = {
+ /** Whether the content is visible */
+ isVisible: boolean;
+
+ /** Method to trigger when pressing outside of the popover menu to close it */
+ onClose: () => void;
+
+ /** Method to trigger when pressing confirm button */
+ onConfirm: () => void;
+
+ /** The anchor position of the popover menu */
+ anchorPosition?: PopoverAnchorPosition;
+
+ /** The anchor alignment of the popover menu */
+ anchorAlignment: AnchorAlignment;
+
+ /** The anchor ref of the popover menu */
+ anchorRef: React.RefObject;
+};
+
+function ProcessMoneyRequestHoldMenu({isVisible, onClose, onConfirm, anchorPosition, anchorAlignment, anchorRef}: ProcessMoneyRequestHoldMenuProps) {
+ const {translate} = useLocalize();
+ const styles = useThemeStyles();
+
+ return (
+
+
+
+ {translate('iou.holdEducationalTitle')}
+ {translate('iou.hold')};
+
+
+
+
+
+ );
+}
+
+ProcessMoneyRequestHoldMenu.displayName = 'ProcessMoneyRequestHoldMenu';
+
+export default ProcessMoneyRequestHoldMenu;
diff --git a/src/components/TextPill.tsx b/src/components/TextPill.tsx
new file mode 100644
index 000000000000..035ae1dd42d8
--- /dev/null
+++ b/src/components/TextPill.tsx
@@ -0,0 +1,26 @@
+import React from 'react';
+import {StyleProp, TextStyle} from 'react-native';
+// eslint-disable-next-line no-restricted-imports
+import useThemeStyles from '@hooks/useThemeStyles';
+import colors from '@styles/theme/colors';
+import Text from './Text';
+
+type TextPillProps = {
+ /** The color of the text/ */
+ color?: string;
+
+ /** Styles to apply to the text */
+ textStyles: StyleProp;
+
+ children: React.ReactNode;
+};
+
+function TextPill({color, textStyles, children}: TextPillProps) {
+ const styles = useThemeStyles();
+
+ return {children};
+}
+
+TextPill.displayName = 'TextPill';
+
+export default TextPill;
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 6e177c1df141..0b8983a8361b 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -641,6 +641,14 @@ export default {
},
waitingOnEnabledWallet: ({submitterDisplayName}: WaitingOnBankAccountParams) => `Started settling up, payment is held until ${submitterDisplayName} enables their Wallet`,
enableWallet: 'Enable Wallet',
+ hold: 'Hold',
+ holdEducationalTitle: 'This request is on',
+ whatIsHoldTitle: 'What is hold?',
+ whatIsHoldExplain: 'Hold is our way of streamlining financial collaboration. "Reject" is so harsh!',
+ holdIsTemporaryTitle: 'Hold is usually temporary',
+ holdIsTemporaryExplain: "Because hold is used to clear up confusion or clarify an important detail before payment, it's not permanent.",
+ deleteHoldTitle: "Delete whatever won't be paid",
+ deleteHoldExplain: "In the rare case where something is put on hold and won't be paid, it's on the person requesting payment to delete it.",
set: 'set',
changed: 'changed',
removed: 'removed',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 990554b0b502..a1afde53482b 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -636,6 +636,14 @@ export default {
},
waitingOnEnabledWallet: ({submitterDisplayName}: WaitingOnBankAccountParams) => `Inició el pago, pero no se procesará hasta que ${submitterDisplayName} active su Billetera`,
enableWallet: 'Habilitar Billetera',
+ hold: 'Hold',
+ holdEducationalTitle: 'Esta solicitud está en',
+ whatIsHoldTitle: '¿Qué es Hold?',
+ whatIsHoldExplain: 'Hold es nuestra forma de agilizar la colaboración financiera. ¡"Rechazar" es tan duro!',
+ holdIsTemporaryTitle: 'Hold suele ser temporal',
+ holdIsTemporaryExplain: 'Debido a que hold se utiliza para aclarar confusión o aclarar un detalle importante antes del pago, no es permanente.',
+ deleteHoldTitle: 'Eliminar lo que no se pagará',
+ deleteHoldExplain: 'En el raro caso de que algo se ponga en hold y no se pague, la persona que solicita el pago debe eliminarlo.',
set: 'estableció',
changed: 'cambió',
removed: 'eliminó',
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx
index e177f1c2003d..4be1c988561b 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx
@@ -283,6 +283,10 @@ const ReferralModalStackNavigator = createModalStackNavigator require('../../../pages/ReferralDetailsPage').default as React.ComponentType,
});
+const ProcessMoneyRequestHoldStackNavigator = createModalStackNavigator({
+ [SCREENS.PROCESS_MONEY_REQUEST_HOLD_ROOT]: () => require('../../../pages/ProcessMoneyRequestHoldPage').default as React.ComponentType,
+});
+
export {
MoneyRequestModalStackNavigator,
SplitDetailsModalStackNavigator,
@@ -309,4 +313,5 @@ export {
RoomMembersModalStackNavigator,
RoomInviteModalStackNavigator,
ReferralModalStackNavigator,
+ ProcessMoneyRequestHoldStackNavigator,
};
diff --git a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx
index ca33b32113bb..dbb2790c1318 100644
--- a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx
+++ b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx
@@ -118,6 +118,10 @@ function RightModalNavigator({navigation}: RightModalNavigatorProps) {
name={SCREENS.RIGHT_MODAL.PRIVATE_NOTES}
component={ModalStackNavigators.PrivateNotesModalStackNavigator}
/>
+
diff --git a/src/libs/Navigation/linkingConfig.ts b/src/libs/Navigation/linkingConfig.ts
index 3b2350afcc43..5f2a607b5f78 100644
--- a/src/libs/Navigation/linkingConfig.ts
+++ b/src/libs/Navigation/linkingConfig.ts
@@ -492,6 +492,11 @@ const linkingConfig: LinkingOptions = {
[SCREENS.REFERRAL_DETAILS]: ROUTES.REFERRAL_DETAILS_MODAL.route,
},
},
+ ProcessMoneyRequestHold: {
+ screens: {
+ ProcessMoneyRequestHold_Root: ROUTES.PROCESS_MONEY_REQUEST_HOLD,
+ },
+ },
},
},
},
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index 505bc82180f4..90f5361f11f4 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -331,6 +331,10 @@ type ReferralDetailsNavigatorParamList = {
[SCREENS.REFERRAL_DETAILS]: undefined;
};
+type ProcessMoneyRequestHoldNavigatorParamList = {
+ [SCREENS.PROCESS_MONEY_REQUEST_HOLD_ROOT]: undefined;
+};
+
type PrivateNotesNavigatorParamList = {
[SCREENS.PRIVATE_NOTES.VIEW]: {
reportID: string;
@@ -372,6 +376,7 @@ type RightModalNavigatorParamList = {
[SCREENS.RIGHT_MODAL.FLAG_COMMENT]: NavigatorScreenParams;
[SCREENS.RIGHT_MODAL.EDIT_REQUEST]: NavigatorScreenParams;
[SCREENS.RIGHT_MODAL.SIGN_IN]: NavigatorScreenParams;
+ [SCREENS.RIGHT_MODAL.PROCESS_MONEY_REQUEST_HOLD]: NavigatorScreenParams;
[SCREENS.RIGHT_MODAL.REFERRAL]: NavigatorScreenParams;
[SCREENS.RIGHT_MODAL.PRIVATE_NOTES]: NavigatorScreenParams;
};
diff --git a/src/pages/ProcessMoneyRequestHoldPage.js b/src/pages/ProcessMoneyRequestHoldPage.js
new file mode 100644
index 000000000000..c9de16f874a2
--- /dev/null
+++ b/src/pages/ProcessMoneyRequestHoldPage.js
@@ -0,0 +1,51 @@
+import React, {useCallback, useMemo} from 'react';
+import {View} from 'react-native';
+import Button from '@components/Button';
+import HeaderPageLayout from '@components/HeaderPageLayout';
+import HoldMenuSectionList from '@components/HoldMenuSectionList';
+import Text from '@components/Text';
+import TextPill from '@components/TextPill';
+import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
+import Navigation from '@libs/Navigation/Navigation';
+
+function ProcessMoneyRequestHoldPage() {
+ const styles = useThemeStyles();
+ const {translate} = useLocalize();
+
+ const onConfirm = useCallback(() => {
+ // Currently only goes back, this will be changed after backends for hold will be merged
+ Navigation.goBack();
+ }, []);
+
+ const footerComponent = useMemo(
+ () => (
+
+ ),
+ [onConfirm, translate],
+ );
+
+ return (
+ Navigation.goBack()}
+ >
+
+
+ {translate('iou.holdEducationalTitle')}
+ {translate('iou.hold')};
+
+
+
+
+ );
+}
+
+ProcessMoneyRequestHoldPage.displayName = 'ProcessMoneyRequestHoldPage';
+
+export default ProcessMoneyRequestHoldPage;
diff --git a/src/styles/index.ts b/src/styles/index.ts
index a0ad7094ab9b..4ef8740fbebb 100644
--- a/src/styles/index.ts
+++ b/src/styles/index.ts
@@ -4068,6 +4068,21 @@ const styles = (theme: ThemeColors) =>
marginBottom: 16,
},
+ holdRequestInline: {
+ ...headlineFont,
+ ...whiteSpace.preWrap,
+ color: theme.heading,
+ fontSize: variables.fontSizeXLarge,
+ lineHeight: variables.lineHeightXXLarge,
+
+ backgroundColor: colors.red,
+ borderRadius: variables.componentBorderRadiusMedium,
+ overflow: 'hidden',
+
+ paddingHorizontal: 8,
+ paddingVertical: 4,
+ },
+
walletCard: {
borderRadius: variables.componentBorderRadiusLarge,
position: 'relative',
diff --git a/src/styles/variables.ts b/src/styles/variables.ts
index 4d717389cdb6..80834c9a0261 100644
--- a/src/styles/variables.ts
+++ b/src/styles/variables.ts
@@ -196,4 +196,5 @@ export default {
cardPreviewHeight: 148,
cardPreviewWidth: 235,
cardNameWidth: 156,
+ holdMenuIconSize: 64,
} as const;