From f41b7ca5ee83543c64c83cc3424c4463d2ba58bd Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Fri, 21 Jun 2024 17:00:29 +0200 Subject: [PATCH 1/9] feat: setup a new route for expensify card --- src/ROUTES.ts | 10 ++++++++++ src/SCREENS.ts | 2 ++ .../AppNavigator/ModalStackNavigators/index.tsx | 1 + src/libs/Navigation/linkingConfig/config.ts | 7 +++++++ src/pages/workspace/card/IssueNewCardPage.tsx | 14 ++++++++++++++ 5 files changed, 34 insertions(+) create mode 100644 src/pages/workspace/card/IssueNewCardPage.tsx diff --git a/src/ROUTES.ts b/src/ROUTES.ts index f39e4b5aa431..439ea2dd42b6 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -776,6 +776,16 @@ const ROUTES = { route: 'settings/workspaces/:policyID/tax/:taxID/value', getRoute: (policyID: string, taxID: string) => `settings/workspaces/${policyID}/tax/${encodeURIComponent(taxID)}/value` as const, }, + // TODO: uncomment after development is done + // WORKSPACE_EXPENSIFY_CARD: { + // route: 'settings/workspaces/:policyID/expensify-card', + // getRoute: (policyID: string) => `settings/workspaces/${policyID}/expensify-card` as const, + // }, + // WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW: { + // route: 'settings/workspaces/:policyID/expensify-card/issues-new', + // getRoute: (policyID: string) => `settings/workspaces/${policyID}/expensify-card/issue-new` as const, + // }, + WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW: 'settings/workspaces/expensify-card/issue-new', WORKSPACE_DISTANCE_RATES: { route: 'settings/workspaces/:policyID/distance-rates', getRoute: (policyID: string) => `settings/workspaces/${policyID}/distance-rates` as const, diff --git a/src/SCREENS.ts b/src/SCREENS.ts index f89469873ac7..6fa1c5c125be 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -276,6 +276,8 @@ const SCREENS = { RATE_AND_UNIT: 'Workspace_RateAndUnit', RATE_AND_UNIT_RATE: 'Workspace_RateAndUnit_Rate', RATE_AND_UNIT_UNIT: 'Workspace_RateAndUnit_Unit', + EXPENSIFY_CARD: 'Workspace_ExpensifyCard', + EXPENSIFY_CARD_ISSUE_NEW: 'Workspace_ExpensifyCard_New', BILLS: 'Workspace_Bills', INVOICES: 'Workspace_Invoices', TRAVEL: 'Workspace_Travel', diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index 480292e99c46..d679e4cc6926 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -325,6 +325,7 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/workspace/taxes/NamePage').default as React.ComponentType, [SCREENS.WORKSPACE.TAX_VALUE]: () => require('../../../../pages/workspace/taxes/ValuePage').default as React.ComponentType, [SCREENS.WORKSPACE.TAX_CREATE]: () => require('../../../../pages/workspace/taxes/WorkspaceCreateTaxPage').default as React.ComponentType, + [SCREENS.WORKSPACE.EXPENSIFY_CARD_ISSUE_NEW]: () => require('../../../../pages/workspace/card/IssueNewCardPage').default as React.ComponentType, [SCREENS.SETTINGS.SAVE_THE_WORLD]: () => require('../../../../pages/TeachersUnite/SaveTheWorldPage').default as React.ComponentType, [SCREENS.SETTINGS.SUBSCRIPTION.ADD_PAYMENT_CARD]: () => require('../../../../pages/settings/Subscription/PaymentCard/AddPaymentCard').default as React.ComponentType, }); diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 3719ce57a27b..6113fbaff75c 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -349,6 +349,13 @@ const config: LinkingOptions['config'] = { [SCREENS.WORKSPACE.SHARE]: { path: ROUTES.WORKSPACE_PROFILE_SHARE.route, }, + // TODO: uncomment after development + // [SCREENS.WORKSPACE.EXPENSIFY_CARD]: { + // path: ROUTES.WORKSPACE_EXPENSIFY_CARD, + // }, + [SCREENS.WORKSPACE.EXPENSIFY_CARD_ISSUE_NEW]: { + path: ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW, + }, [SCREENS.WORKSPACE.RATE_AND_UNIT]: { path: ROUTES.WORKSPACE_RATE_AND_UNIT.route, }, diff --git a/src/pages/workspace/card/IssueNewCardPage.tsx b/src/pages/workspace/card/IssueNewCardPage.tsx new file mode 100644 index 000000000000..9cc2a1e29716 --- /dev/null +++ b/src/pages/workspace/card/IssueNewCardPage.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import {View} from 'react-native'; +import Text from '@components/Text'; + +function IssueNewCardPage() { + return ( + + Issue New Card Page + + ); +} + +IssueNewCardPage.displayName = 'IssueNewCardPage'; +export default IssueNewCardPage; From 0da25a792c55d35c69da91873e06e7993d1016ab Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Mon, 24 Jun 2024 11:33:16 +0200 Subject: [PATCH 2/9] feat: add translations, create first step page --- src/CONST.ts | 1 + src/languages/en.ts | 28 +++++++++++ src/languages/es.ts | 28 +++++++++++ src/pages/workspace/card/IssueNewCardPage.tsx | 7 +-- .../workspace/card/Steps/AsigneeStep.tsx | 49 +++++++++++++++++++ 5 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 src/pages/workspace/card/Steps/AsigneeStep.tsx diff --git a/src/CONST.ts b/src/CONST.ts index c485268b55e2..8f54749b80ef 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1925,6 +1925,7 @@ const CONST = { MONTHLY: 'monthly', FIXED: 'fixed', }, + STEP_NAMES: ['1', '2', '3', '4', '5', '6'], }, AVATAR_ROW_SIZE: { DEFAULT: 4, diff --git a/src/languages/en.ts b/src/languages/en.ts index cced280d97df..36ce362b17bf 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2377,6 +2377,34 @@ export default { benefit4: 'Customizable limits', addWorkEmail: 'Add work email address', checkingDomain: 'Hang tight! We are still working on enabling your Expensify Cards. Check back here in a few minutes.', + issueCard: 'Issue card', + issueNewCard: { + whoNeedsCard: 'Who needs a card?', + findMember: 'Find member', + chooseCardType: 'Choose a card type', + physicalCard: 'Physical card', + physicalCardDescription: 'Great for the frequent spender', + virtualCard: 'Virtual card', + virtualCardDescription: 'Instant and flexible', + chooseLimitType: 'Choose a limit type', + smartLimit: 'Smart Limit', + smartLimitDescription: 'Spend up to a certain amount before requiring approval', + monthly: 'Monthly', + monthlyDescription: 'Spend up to a certain amount per month', + fixedAmount: 'Fixed amount', + fixedAmountDescription: 'Spend up to a certain amount once', + setLimit: 'Set a limit', + giveItName: 'Give it a name', + giveItNameInstruction: 'Make it unique enough to tell apart from the other. Specific use cases are even better!', + cardName: 'Card name', + letsDoubleCheck: 'Let’s double check that everything looks right.', + willBeReady: 'This card will be ready to use immediately.', + cardholder: 'Cardholder', + cardType: 'Card type', + limit: 'Limit', + limitType: 'Limit type', + name: 'Name', + }, }, reimburse: { captureReceipts: 'Capture receipts', diff --git a/src/languages/es.ts b/src/languages/es.ts index d33f3ca73c86..f1424c5f03e6 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2581,6 +2581,34 @@ export default { benefit4: 'Límites personalizables', addWorkEmail: 'Añadir correo electrónico de trabajo', checkingDomain: '¡Un momento! Estamos todavía trabajando para habilitar tu Tarjeta Expensify. Vuelve aquí en unos minutos.', + issueCard: 'Emitir tarjeta', + issueNewCard: { + whoNeedsCard: '¿Quién necesita una tarjeta?', + findMember: 'Buscar miembro', + chooseCardType: 'Elegir un tipo de tarjeta', + physicalCard: 'Tarjeta física', + physicalCardDescription: 'Ideal para los consumidores habituales', + virtualCard: 'Tarjeta virtual', + virtualCardDescription: 'Instantáneo y flexible', + chooseLimitType: 'Elegir un tipo de límite', + smartLimit: 'Límite inteligente', + smartLimitDescription: 'Gasta hasta una determinada cantidad antes de requerir aprobación', + monthly: 'Mensual', + monthlyDescription: 'Gasta hasta una determinada cantidad al mes', + fixedAmount: 'Cantidad fija', + fixedAmountDescription: 'Gasta hasta una determinada cantidad una vez', + setLimit: 'Establecer un límite', + giveItName: 'Dale un nombre', + giveItNameInstruction: 'Hazlo lo suficientemente único como para distinguirlo de los demás. Los casos de uso específicos son aún mejores.', + cardName: 'Nombre de la tarjeta', + letsDoubleCheck: 'Vuelve a comprobar que todo parece correcto. ', + willBeReady: 'Esta tarjeta estará lista para su uso inmediato.', + cardholder: 'Titular de la tarjeta', + cardType: 'Tipo de tarjeta', + limit: 'Limite', + limitType: 'Tipo de limite', + name: 'Nombre', + }, }, reimburse: { captureReceipts: 'Captura recibos', diff --git a/src/pages/workspace/card/IssueNewCardPage.tsx b/src/pages/workspace/card/IssueNewCardPage.tsx index 9cc2a1e29716..57d24fa1eed0 100644 --- a/src/pages/workspace/card/IssueNewCardPage.tsx +++ b/src/pages/workspace/card/IssueNewCardPage.tsx @@ -1,13 +1,10 @@ import React from 'react'; import {View} from 'react-native'; import Text from '@components/Text'; +import AsigneeStep from '@pages/workspace/card/Steps/AsigneeStep'; function IssueNewCardPage() { - return ( - - Issue New Card Page - - ); + return ; } IssueNewCardPage.displayName = 'IssueNewCardPage'; diff --git a/src/pages/workspace/card/Steps/AsigneeStep.tsx b/src/pages/workspace/card/Steps/AsigneeStep.tsx new file mode 100644 index 000000000000..bd050073a855 --- /dev/null +++ b/src/pages/workspace/card/Steps/AsigneeStep.tsx @@ -0,0 +1,49 @@ +import React from 'react'; +import {View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; +import ScreenWrapper from '@components/ScreenWrapper'; +import useLocalize from '@hooks/useLocalize'; +import useSubStep from '@hooks/useSubStep'; +import type {SubStepProps} from '@hooks/useSubStep/types'; +import useThemeStyles from '@hooks/useThemeStyles'; +import Navigation from '@navigation/Navigation'; +import * as BankAccounts from '@userActions/BankAccounts'; +import * as Wallet from '@userActions/Wallet'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; + +function AssigneeStep() { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + + const submit = () => {}; + + const handleBackButtonPress = () => {}; + + return ( + + + + + + + ); +} + +AssigneeStep.displayName = 'TermsAndFees'; + +export default AssigneeStep; From 9408da66166b4fc7cd7d8aa7882e1aeb500c9f33 Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Mon, 24 Jun 2024 12:30:34 +0200 Subject: [PATCH 3/9] feat: create the rest of the steps, give them a name and a header --- src/CONST.ts | 8 ++++ .../ModalStackNavigators/index.tsx | 2 +- src/pages/workspace/card/IssueNewCardPage.tsx | 11 ----- .../AssigneeStep.tsx} | 8 +--- .../workspace/card/issueNew/CardNameStep.tsx | 47 +++++++++++++++++++ .../workspace/card/issueNew/CartTypeStep.tsx | 47 +++++++++++++++++++ .../card/issueNew/ConfirmationStep.tsx | 47 +++++++++++++++++++ .../card/issueNew/IssueNewCardPage.tsx | 33 +++++++++++++ .../workspace/card/issueNew/LimitStep.tsx | 47 +++++++++++++++++++ .../workspace/card/issueNew/LimitTypeStep.tsx | 47 +++++++++++++++++++ 10 files changed, 279 insertions(+), 18 deletions(-) delete mode 100644 src/pages/workspace/card/IssueNewCardPage.tsx rename src/pages/workspace/card/{Steps/AsigneeStep.tsx => issueNew/AssigneeStep.tsx} (83%) create mode 100644 src/pages/workspace/card/issueNew/CardNameStep.tsx create mode 100644 src/pages/workspace/card/issueNew/CartTypeStep.tsx create mode 100644 src/pages/workspace/card/issueNew/ConfirmationStep.tsx create mode 100644 src/pages/workspace/card/issueNew/IssueNewCardPage.tsx create mode 100644 src/pages/workspace/card/issueNew/LimitStep.tsx create mode 100644 src/pages/workspace/card/issueNew/LimitTypeStep.tsx diff --git a/src/CONST.ts b/src/CONST.ts index 8f54749b80ef..e1a4fd8e112d 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1926,6 +1926,14 @@ const CONST = { FIXED: 'fixed', }, STEP_NAMES: ['1', '2', '3', '4', '5', '6'], + STEP: { + ASSIGNEE: 'Assignee', + CARD_TYPE: 'CardType', + LIMIT_TYPE: 'LimitType', + LIMIT: 'Limit', + CARD_NAME: 'CardName', + CONFIRMATION: 'Confirmation', + }, }, AVATAR_ROW_SIZE: { DEFAULT: 4, diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index d679e4cc6926..99646c322c22 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -325,7 +325,7 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/workspace/taxes/NamePage').default as React.ComponentType, [SCREENS.WORKSPACE.TAX_VALUE]: () => require('../../../../pages/workspace/taxes/ValuePage').default as React.ComponentType, [SCREENS.WORKSPACE.TAX_CREATE]: () => require('../../../../pages/workspace/taxes/WorkspaceCreateTaxPage').default as React.ComponentType, - [SCREENS.WORKSPACE.EXPENSIFY_CARD_ISSUE_NEW]: () => require('../../../../pages/workspace/card/IssueNewCardPage').default as React.ComponentType, + [SCREENS.WORKSPACE.EXPENSIFY_CARD_ISSUE_NEW]: () => require('@pages/workspace/card/issueNew/IssueNewCardPage').default as React.ComponentType, [SCREENS.SETTINGS.SAVE_THE_WORLD]: () => require('../../../../pages/TeachersUnite/SaveTheWorldPage').default as React.ComponentType, [SCREENS.SETTINGS.SUBSCRIPTION.ADD_PAYMENT_CARD]: () => require('../../../../pages/settings/Subscription/PaymentCard/AddPaymentCard').default as React.ComponentType, }); diff --git a/src/pages/workspace/card/IssueNewCardPage.tsx b/src/pages/workspace/card/IssueNewCardPage.tsx deleted file mode 100644 index 57d24fa1eed0..000000000000 --- a/src/pages/workspace/card/IssueNewCardPage.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; -import {View} from 'react-native'; -import Text from '@components/Text'; -import AsigneeStep from '@pages/workspace/card/Steps/AsigneeStep'; - -function IssueNewCardPage() { - return ; -} - -IssueNewCardPage.displayName = 'IssueNewCardPage'; -export default IssueNewCardPage; diff --git a/src/pages/workspace/card/Steps/AsigneeStep.tsx b/src/pages/workspace/card/issueNew/AssigneeStep.tsx similarity index 83% rename from src/pages/workspace/card/Steps/AsigneeStep.tsx rename to src/pages/workspace/card/issueNew/AssigneeStep.tsx index bd050073a855..a63b0af4adcc 100644 --- a/src/pages/workspace/card/Steps/AsigneeStep.tsx +++ b/src/pages/workspace/card/issueNew/AssigneeStep.tsx @@ -5,12 +5,8 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; -import useSubStep from '@hooks/useSubStep'; -import type {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@navigation/Navigation'; -import * as BankAccounts from '@userActions/BankAccounts'; -import * as Wallet from '@userActions/Wallet'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -36,7 +32,7 @@ function AssigneeStep() { /> @@ -44,6 +40,6 @@ function AssigneeStep() { ); } -AssigneeStep.displayName = 'TermsAndFees'; +AssigneeStep.displayName = 'AssigneeStep'; export default AssigneeStep; diff --git a/src/pages/workspace/card/issueNew/CardNameStep.tsx b/src/pages/workspace/card/issueNew/CardNameStep.tsx new file mode 100644 index 000000000000..4598d3e67c4d --- /dev/null +++ b/src/pages/workspace/card/issueNew/CardNameStep.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import {View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; +import ScreenWrapper from '@components/ScreenWrapper'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import Navigation from '@navigation/Navigation'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; + +function CardNameStep() { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + + const submit = () => {}; + + const handleBackButtonPress = () => {}; + + return ( + + + + + + {translate('workspace.card.issueNewCard.giveItName')} + + ); +} + +CardNameStep.displayName = 'CardNameStep'; + +export default CardNameStep; diff --git a/src/pages/workspace/card/issueNew/CartTypeStep.tsx b/src/pages/workspace/card/issueNew/CartTypeStep.tsx new file mode 100644 index 000000000000..a6f506054311 --- /dev/null +++ b/src/pages/workspace/card/issueNew/CartTypeStep.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import {View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; +import ScreenWrapper from '@components/ScreenWrapper'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import Navigation from '@navigation/Navigation'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; + +function CardTypeStep() { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + + const submit = () => {}; + + const handleBackButtonPress = () => {}; + + return ( + + + + + + {translate('workspace.card.issueNewCard.chooseCardType')} + + ); +} + +CardTypeStep.displayName = 'CardTypeStep'; + +export default CardTypeStep; diff --git a/src/pages/workspace/card/issueNew/ConfirmationStep.tsx b/src/pages/workspace/card/issueNew/ConfirmationStep.tsx new file mode 100644 index 000000000000..beb02d028e37 --- /dev/null +++ b/src/pages/workspace/card/issueNew/ConfirmationStep.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import {View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; +import ScreenWrapper from '@components/ScreenWrapper'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import Navigation from '@navigation/Navigation'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; + +function ConfirmationStep() { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + + const submit = () => {}; + + const handleBackButtonPress = () => {}; + + return ( + + + + + + {translate('workspace.card.issueNewCard.letsDoubleCheck')} + + ); +} + +ConfirmationStep.displayName = 'ConfirmationStep'; + +export default ConfirmationStep; diff --git a/src/pages/workspace/card/issueNew/IssueNewCardPage.tsx b/src/pages/workspace/card/issueNew/IssueNewCardPage.tsx new file mode 100644 index 000000000000..9543f70ed416 --- /dev/null +++ b/src/pages/workspace/card/issueNew/IssueNewCardPage.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import {View} from 'react-native'; +import Text from '@components/Text'; +import AssigneeStep from '@pages/workspace/card/issueNew/AssigneeStep'; +import CardNameStep from '@pages/workspace/card/issueNew/CardNameStep'; +import CardTypeStep from '@pages/workspace/card/issueNew/CartTypeStep'; +import ConfirmationStep from '@pages/workspace/card/issueNew/ConfirmationStep'; +import LimitStep from '@pages/workspace/card/issueNew/LimitStep'; +import LimitTypeStep from '@pages/workspace/card/issueNew/LimitTypeStep'; +import CONST from '@src/CONST'; + +function IssueNewCardPage() { + const currentStep = ''; + switch (currentStep) { + case CONST.EXPENSIFY_CARD.STEP.ASSIGNEE: + return ; + case CONST.EXPENSIFY_CARD.STEP.CARD_TYPE: + return ; + case CONST.EXPENSIFY_CARD.STEP.LIMIT_TYPE: + return ; + case CONST.EXPENSIFY_CARD.STEP.LIMIT: + return ; + case CONST.EXPENSIFY_CARD.STEP.CARD_NAME: + return ; + case CONST.EXPENSIFY_CARD.STEP.CONFIRMATION: + return ; + default: + return ; + } +} + +IssueNewCardPage.displayName = 'IssueNewCardPage'; +export default IssueNewCardPage; diff --git a/src/pages/workspace/card/issueNew/LimitStep.tsx b/src/pages/workspace/card/issueNew/LimitStep.tsx new file mode 100644 index 000000000000..6be4852f452e --- /dev/null +++ b/src/pages/workspace/card/issueNew/LimitStep.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import {View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; +import ScreenWrapper from '@components/ScreenWrapper'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import Navigation from '@navigation/Navigation'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; + +function LimitStep() { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + + const submit = () => {}; + + const handleBackButtonPress = () => {}; + + return ( + + + + + + {translate('workspace.card.issueNewCard.setLimit')} + + ); +} + +LimitStep.displayName = 'LimitStep'; + +export default LimitStep; diff --git a/src/pages/workspace/card/issueNew/LimitTypeStep.tsx b/src/pages/workspace/card/issueNew/LimitTypeStep.tsx new file mode 100644 index 000000000000..6a34a1363c1d --- /dev/null +++ b/src/pages/workspace/card/issueNew/LimitTypeStep.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import {View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; +import ScreenWrapper from '@components/ScreenWrapper'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import Navigation from '@navigation/Navigation'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; + +function LimitTypeStep() { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + + const submit = () => {}; + + const handleBackButtonPress = () => {}; + + return ( + + + + + + {translate('workspace.card.issueNewCard.chooseLimitType')} + + ); +} + +LimitTypeStep.displayName = 'LimitTypeStep'; + +export default LimitTypeStep; From 159fda6b8b0398f67bec0f1ba8f2c479952a8742 Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Mon, 24 Jun 2024 16:13:41 +0200 Subject: [PATCH 4/9] feat: create types, connect the steps --- src/ONYXKEYS.ts | 7 +++++++ src/libs/actions/Card.ts | 20 +++++++++++++++---- .../workspace/card/issueNew/AssigneeStep.tsx | 18 +++++++++++++++-- .../workspace/card/issueNew/CardNameStep.tsx | 18 +++++++++++++++-- .../workspace/card/issueNew/CartTypeStep.tsx | 18 +++++++++++++++-- .../card/issueNew/ConfirmationStep.tsx | 9 +++++++-- .../card/issueNew/IssueNewCardPage.tsx | 7 ++++++- .../workspace/card/issueNew/LimitStep.tsx | 18 +++++++++++++++-- .../workspace/card/issueNew/LimitTypeStep.tsx | 18 +++++++++++++++-- src/types/form/IssueNewExpensifyCardForm.ts | 18 +++++++++++++++++ src/types/form/index.ts | 1 + src/types/onyx/Card.ts | 11 +++++++++- src/types/onyx/index.ts | 3 ++- 13 files changed, 147 insertions(+), 19 deletions(-) create mode 100644 src/types/form/IssueNewExpensifyCardForm.ts diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index b5eea4228042..7351110c96fd 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -342,6 +342,9 @@ const ONYXKEYS = { /** Stores info during review duplicates flow */ REVIEW_DUPLICATES: 'reviewDuplicates', + /** Stores the information about the state of issuing a new card */ + ISSUE_NEW_EXPENSIFY_CARD: 'issueNewExpensifyCard', + /** Collection Keys */ COLLECTION: { DOWNLOAD: 'download_', @@ -508,6 +511,8 @@ const ONYXKEYS = { NEW_CHAT_NAME_FORM_DRAFT: 'newChatNameFormDraft', SUBSCRIPTION_SIZE_FORM: 'subscriptionSizeForm', SUBSCRIPTION_SIZE_FORM_DRAFT: 'subscriptionSizeFormDraft', + ISSUE_NEW_EXPENSIFY_CARD_FORM: 'issueNewExpensifyCardForm', + ISSUE_NEW_EXPENSIFY_CARD_FORM_DRAFT: 'issueNewExpensifyCardFormDraft', }, } as const; @@ -567,6 +572,7 @@ type OnyxFormValuesMapping = { [ONYXKEYS.FORMS.WORKSPACE_TAX_VALUE_FORM]: FormTypes.WorkspaceTaxValueForm; [ONYXKEYS.FORMS.NEW_CHAT_NAME_FORM]: FormTypes.NewChatNameForm; [ONYXKEYS.FORMS.SUBSCRIPTION_SIZE_FORM]: FormTypes.SubscriptionSizeForm; + [ONYXKEYS.FORMS.ISSUE_NEW_EXPENSIFY_CARD_FORM]: FormTypes.IssueNewExpensifyCardForm; }; type OnyxFormDraftValuesMapping = { @@ -723,6 +729,7 @@ type OnyxValuesMapping = { [ONYXKEYS.POLICY_OWNERSHIP_CHANGE_CHECKS]: Record; [ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE]: OnyxTypes.QuickAction; [ONYXKEYS.REVIEW_DUPLICATES]: OnyxTypes.ReviewDuplicates; + [ONYXKEYS.ISSUE_NEW_EXPENSIFY_CARD]: OnyxTypes.IssueNewCard; [ONYXKEYS.NVP_FIRST_DAY_FREE_TRIAL]: string; [ONYXKEYS.NVP_LAST_DAY_FREE_TRIAL]: string; [ONYXKEYS.NVP_BILLING_FUND_ID]: number; diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index 9a011d88e582..aea952618071 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -5,7 +5,7 @@ import type {ActivatePhysicalExpensifyCardParams, ReportVirtualExpensifyCardFrau import {SIDE_EFFECT_REQUEST_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {ExpensifyCardDetails} from '@src/types/onyx/Card'; +import type {ExpensifyCardDetails, IssueNewCardStep} from '@src/types/onyx/Card'; type ReplacementReason = 'damaged' | 'stolen'; @@ -44,7 +44,11 @@ function reportVirtualExpensifyCardFraud(cardID: number) { cardID, }; - API.write(WRITE_COMMANDS.REPORT_VIRTUAL_EXPENSIFY_CARD_FRAUD, parameters, {optimisticData, successData, failureData}); + API.write(WRITE_COMMANDS.REPORT_VIRTUAL_EXPENSIFY_CARD_FRAUD, parameters, { + optimisticData, + successData, + failureData, + }); } /** @@ -89,7 +93,11 @@ function requestReplacementExpensifyCard(cardID: number, reason: ReplacementReas reason, }; - API.write(WRITE_COMMANDS.REQUEST_REPLACEMENT_EXPENSIFY_CARD, parameters, {optimisticData, successData, failureData}); + API.write(WRITE_COMMANDS.REQUEST_REPLACEMENT_EXPENSIFY_CARD, parameters, { + optimisticData, + successData, + failureData, + }); } /** @@ -177,5 +185,9 @@ function revealVirtualCardDetails(cardID: number): Promise }); } -export {requestReplacementExpensifyCard, activatePhysicalExpensifyCard, clearCardListErrors, reportVirtualExpensifyCardFraud, revealVirtualCardDetails}; +function setIssueNewCardStep(step: IssueNewCardStep | null) { + Onyx.merge(ONYXKEYS.ISSUE_NEW_EXPENSIFY_CARD, {currentStep: step}); +} + +export {requestReplacementExpensifyCard, activatePhysicalExpensifyCard, clearCardListErrors, reportVirtualExpensifyCardFraud, revealVirtualCardDetails, setIssueNewCardStep}; export type {ReplacementReason}; diff --git a/src/pages/workspace/card/issueNew/AssigneeStep.tsx b/src/pages/workspace/card/issueNew/AssigneeStep.tsx index a63b0af4adcc..ab169a804464 100644 --- a/src/pages/workspace/card/issueNew/AssigneeStep.tsx +++ b/src/pages/workspace/card/issueNew/AssigneeStep.tsx @@ -1,12 +1,14 @@ import React from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; +import FormProvider from '@components/Form/FormProvider'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@navigation/Navigation'; +import * as Card from '@userActions/Card'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -15,9 +17,13 @@ function AssigneeStep() { const {translate} = useLocalize(); const styles = useThemeStyles(); - const submit = () => {}; + const submit = () => { + Card.setIssueNewCardStep(CONST.EXPENSIFY_CARD.STEP.CARD_TYPE); + }; - const handleBackButtonPress = () => {}; + const handleBackButtonPress = () => { + Navigation.goBack(); + }; return ( + + + ); } diff --git a/src/pages/workspace/card/issueNew/CardNameStep.tsx b/src/pages/workspace/card/issueNew/CardNameStep.tsx index 4598d3e67c4d..dd40289454d8 100644 --- a/src/pages/workspace/card/issueNew/CardNameStep.tsx +++ b/src/pages/workspace/card/issueNew/CardNameStep.tsx @@ -1,6 +1,7 @@ import React from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; +import FormProvider from '@components/Form/FormProvider'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -8,6 +9,7 @@ import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@navigation/Navigation'; +import * as Card from '@userActions/Card'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -16,9 +18,13 @@ function CardNameStep() { const {translate} = useLocalize(); const styles = useThemeStyles(); - const submit = () => {}; + const submit = () => { + Card.setIssueNewCardStep(CONST.EXPENSIFY_CARD.STEP.CONFIRMATION); + }; - const handleBackButtonPress = () => {}; + const handleBackButtonPress = () => { + Card.setIssueNewCardStep(CONST.EXPENSIFY_CARD.STEP.LIMIT); + }; return ( {translate('workspace.card.issueNewCard.giveItName')} + + + ); } diff --git a/src/pages/workspace/card/issueNew/CartTypeStep.tsx b/src/pages/workspace/card/issueNew/CartTypeStep.tsx index a6f506054311..2cd807d8c375 100644 --- a/src/pages/workspace/card/issueNew/CartTypeStep.tsx +++ b/src/pages/workspace/card/issueNew/CartTypeStep.tsx @@ -1,6 +1,7 @@ import React from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; +import FormProvider from '@components/Form/FormProvider'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -8,6 +9,7 @@ import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@navigation/Navigation'; +import * as Card from '@userActions/Card'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -16,9 +18,13 @@ function CardTypeStep() { const {translate} = useLocalize(); const styles = useThemeStyles(); - const submit = () => {}; + const submit = () => { + Card.setIssueNewCardStep(CONST.EXPENSIFY_CARD.STEP.LIMIT_TYPE); + }; - const handleBackButtonPress = () => {}; + const handleBackButtonPress = () => { + Card.setIssueNewCardStep(CONST.EXPENSIFY_CARD.STEP.ASSIGNEE); + }; return ( {translate('workspace.card.issueNewCard.chooseCardType')} + + + ); } diff --git a/src/pages/workspace/card/issueNew/ConfirmationStep.tsx b/src/pages/workspace/card/issueNew/ConfirmationStep.tsx index beb02d028e37..07ea2024d547 100644 --- a/src/pages/workspace/card/issueNew/ConfirmationStep.tsx +++ b/src/pages/workspace/card/issueNew/ConfirmationStep.tsx @@ -8,6 +8,7 @@ import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@navigation/Navigation'; +import * as Card from '@userActions/Card'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -16,9 +17,13 @@ function ConfirmationStep() { const {translate} = useLocalize(); const styles = useThemeStyles(); - const submit = () => {}; + const submit = () => { + Navigation.navigate(ROUTES.SETTINGS); + }; - const handleBackButtonPress = () => {}; + const handleBackButtonPress = () => { + Card.setIssueNewCardStep(CONST.EXPENSIFY_CARD.STEP.CARD_NAME); + }; return ( ; diff --git a/src/pages/workspace/card/issueNew/LimitStep.tsx b/src/pages/workspace/card/issueNew/LimitStep.tsx index 6be4852f452e..9f6acb982855 100644 --- a/src/pages/workspace/card/issueNew/LimitStep.tsx +++ b/src/pages/workspace/card/issueNew/LimitStep.tsx @@ -1,6 +1,7 @@ import React from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; +import FormProvider from '@components/Form/FormProvider'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -8,6 +9,7 @@ import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@navigation/Navigation'; +import * as Card from '@userActions/Card'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -16,9 +18,13 @@ function LimitStep() { const {translate} = useLocalize(); const styles = useThemeStyles(); - const submit = () => {}; + const submit = () => { + Card.setIssueNewCardStep(CONST.EXPENSIFY_CARD.STEP.CARD_NAME); + }; - const handleBackButtonPress = () => {}; + const handleBackButtonPress = () => { + Card.setIssueNewCardStep(CONST.EXPENSIFY_CARD.STEP.LIMIT_TYPE); + }; return ( {translate('workspace.card.issueNewCard.setLimit')} + + + ); } diff --git a/src/pages/workspace/card/issueNew/LimitTypeStep.tsx b/src/pages/workspace/card/issueNew/LimitTypeStep.tsx index 6a34a1363c1d..c773393c22a9 100644 --- a/src/pages/workspace/card/issueNew/LimitTypeStep.tsx +++ b/src/pages/workspace/card/issueNew/LimitTypeStep.tsx @@ -1,6 +1,7 @@ import React from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; +import FormProvider from '@components/Form/FormProvider'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -8,6 +9,7 @@ import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@navigation/Navigation'; +import * as Card from '@userActions/Card'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -16,9 +18,13 @@ function LimitTypeStep() { const {translate} = useLocalize(); const styles = useThemeStyles(); - const submit = () => {}; + const submit = () => { + Card.setIssueNewCardStep(CONST.EXPENSIFY_CARD.STEP.LIMIT); + }; - const handleBackButtonPress = () => {}; + const handleBackButtonPress = () => { + Card.setIssueNewCardStep(CONST.EXPENSIFY_CARD.STEP.CARD_TYPE); + }; return ( {translate('workspace.card.issueNewCard.chooseLimitType')} + + + ); } diff --git a/src/types/form/IssueNewExpensifyCardForm.ts b/src/types/form/IssueNewExpensifyCardForm.ts new file mode 100644 index 000000000000..06ff2c421968 --- /dev/null +++ b/src/types/form/IssueNewExpensifyCardForm.ts @@ -0,0 +1,18 @@ +import type {ValueOf} from 'type-fest'; +import type Form from './Form'; + +const INPUT_IDS = { + CARD_NAME: 'cardName', +} as const; + +type InputID = ValueOf; + +type IssueNewExpensifyCardForm = Form< + InputID, + { + [INPUT_IDS.CARD_NAME]: string; + } +>; + +export type {IssueNewExpensifyCardForm}; +export default INPUT_IDS; diff --git a/src/types/form/index.ts b/src/types/form/index.ts index d56ab69d6a4e..c531b681e46d 100644 --- a/src/types/form/index.ts +++ b/src/types/form/index.ts @@ -9,6 +9,7 @@ export type {GetPhysicalCardForm} from './GetPhysicalCardForm'; export type {HomeAddressForm} from './HomeAddressForm'; export type {IKnowTeacherForm} from './IKnowTeacherForm'; export type {IntroSchoolPrincipalForm} from './IntroSchoolPrincipalForm'; +export type {IssueNewExpensifyCardForm} from './IssueNewExpensifyCardForm'; export type {LegalNameForm} from './LegalNameForm'; export type {MoneyRequestAmountForm} from './MoneyRequestAmountForm'; export type {MoneyRequestDateForm} from './MoneyRequestDateForm'; diff --git a/src/types/onyx/Card.ts b/src/types/onyx/Card.ts index 595104d4aed3..a490d24e9f17 100644 --- a/src/types/onyx/Card.ts +++ b/src/types/onyx/Card.ts @@ -83,5 +83,14 @@ type ExpensifyCardDetails = { /** Record of Expensify cards, indexed by cardID */ type CardList = Record; +/** Issue new card flow steps */ +type IssueNewCardStep = ValueOf; + +/** Model of Issue new card flow */ +type IssueNewCard = { + /** The current step of the flow */ + currentStep: IssueNewCardStep; +}; + export default Card; -export type {ExpensifyCardDetails, CardList}; +export type {ExpensifyCardDetails, CardList, IssueNewCard, IssueNewCardStep}; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index becb56cb09f0..22dad4ebd8e2 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -6,7 +6,7 @@ import type Beta from './Beta'; import type BillingGraceEndPeriod from './BillingGraceEndPeriod'; import type BlockedFromConcierge from './BlockedFromConcierge'; import type Card from './Card'; -import type {CardList} from './Card'; +import type {CardList, IssueNewCard} from './Card'; import type {CapturedLogs, Log} from './Console'; import type Credentials from './Credentials'; import type Currency from './Currency'; @@ -108,6 +108,7 @@ export type { FundList, IntroSelected, IOU, + IssueNewCard, Locale, Login, LoginList, From dc10601759fd44f6bb7bf5a4dc5d1b7f19393ed0 Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Tue, 25 Jun 2024 11:07:30 +0200 Subject: [PATCH 5/9] feat: add issue new card button in the confirmation step --- .../workspace/card/issueNew/ConfirmationStep.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/pages/workspace/card/issueNew/ConfirmationStep.tsx b/src/pages/workspace/card/issueNew/ConfirmationStep.tsx index 07ea2024d547..e6cb670a72c8 100644 --- a/src/pages/workspace/card/issueNew/ConfirmationStep.tsx +++ b/src/pages/workspace/card/issueNew/ConfirmationStep.tsx @@ -1,11 +1,13 @@ import React from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; +import Button from '@components/Button'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; +import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@navigation/Navigation'; import * as Card from '@userActions/Card'; @@ -16,6 +18,7 @@ import ROUTES from '@src/ROUTES'; function ConfirmationStep() { const {translate} = useLocalize(); const styles = useThemeStyles(); + const {isOffline} = useNetwork(); const submit = () => { Navigation.navigate(ROUTES.SETTINGS); @@ -43,6 +46,16 @@ function ConfirmationStep() { /> {translate('workspace.card.issueNewCard.letsDoubleCheck')} + +