From 778d9cf3db05e4233ef9d23a2e5ba31c43a4217c Mon Sep 17 00:00:00 2001 From: Pedro Guerreiro Date: Mon, 17 Jun 2024 18:40:55 +0100 Subject: [PATCH 01/14] feature: add workspace restricted action screen --- ...simple-illustration__lockclosed_orange.svg | 52 ++++++++++++++ src/ROUTES.ts | 4 ++ src/SCREENS.ts | 2 + src/components/Icon/Illustrations.ts | 2 + src/languages/en.ts | 12 ++++ src/languages/es.ts | 12 ++++ .../ModalStackNavigators/index.tsx | 5 ++ .../Navigators/RightModalNavigator.tsx | 4 ++ src/libs/Navigation/linkingConfig/config.ts | 5 ++ src/libs/Navigation/types.ts | 8 +++ src/libs/ReportUtils.ts | 6 ++ .../WorkspaceAdminRestrictedAction.tsx | 68 ++++++++++++++++++ .../WorkspaceOwnerRestrictedAction.tsx | 69 +++++++++++++++++++ .../WorkspaceRestrictedActionPage.tsx | 38 ++++++++++ .../WorkspaceUserRestrictedAction.tsx | 68 ++++++++++++++++++ 15 files changed, 355 insertions(+) create mode 100644 assets/images/simple-illustrations/simple-illustration__lockclosed_orange.svg create mode 100644 src/pages/RestrictedAction/Workspace/WorkspaceAdminRestrictedAction.tsx create mode 100644 src/pages/RestrictedAction/Workspace/WorkspaceOwnerRestrictedAction.tsx create mode 100644 src/pages/RestrictedAction/Workspace/WorkspaceRestrictedActionPage.tsx create mode 100644 src/pages/RestrictedAction/Workspace/WorkspaceUserRestrictedAction.tsx diff --git a/assets/images/simple-illustrations/simple-illustration__lockclosed_orange.svg b/assets/images/simple-illustrations/simple-illustration__lockclosed_orange.svg new file mode 100644 index 000000000000..91af173f0357 --- /dev/null +++ b/assets/images/simple-illustrations/simple-illustration__lockclosed_orange.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ROUTES.ts b/src/ROUTES.ts index c1fdd68951fa..5fd4d2e88645 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -908,6 +908,10 @@ const ROUTES = { route: 'settings/workspaces/:policyID/accounting/quickbooks-online/import/taxes', getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/quickbooks-online/import/taxes` as const, }, + RESTRICTED_ACTION: { + route: 'restricted-action/workspace/:policyID', + getRoute: (policyID: string) => `restricted-action/workspace/${policyID}` as const, + }, } as const; /** diff --git a/src/SCREENS.ts b/src/SCREENS.ts index f884cca94ef5..270799810fb6 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -141,6 +141,7 @@ const SCREENS = { TRAVEL: 'Travel', SEARCH_REPORT: 'SearchReport', SETTINGS_CATEGORIES: 'SettingsCategories', + RESTRICTED_ACTION: 'RestrictedAction', }, ONBOARDING_MODAL: { ONBOARDING: 'Onboarding', @@ -378,6 +379,7 @@ const SCREENS = { KEYBOARD_SHORTCUTS: 'KeyboardShortcuts', TRANSACTION_RECEIPT: 'TransactionReceipt', FEATURE_TRAINING_ROOT: 'FeatureTraining_Root', + RESTRICTED_ACTION_ROOT: 'RestrictedAction_Root', } as const; type Screen = DeepValueOf; diff --git a/src/components/Icon/Illustrations.ts b/src/components/Icon/Illustrations.ts index 3fe36239d631..1cec6eed496a 100644 --- a/src/components/Icon/Illustrations.ts +++ b/src/components/Icon/Illustrations.ts @@ -94,6 +94,7 @@ import WalletAlt from '@assets/images/simple-illustrations/simple-illustration__ import Workflows from '@assets/images/simple-illustrations/simple-illustration__workflows.svg'; import ExpensifyApprovedLogoLight from '@assets/images/subscription-details__approvedlogo--light.svg'; import ExpensifyApprovedLogo from '@assets/images/subscription-details__approvedlogo.svg'; +import LockClosedOrange from '@assets/images/simple-illustrations/simple-illustration__lockclosed_orange.svg' export { Abracadabra, @@ -192,4 +193,5 @@ export { SendMoney, CheckmarkCircle, CreditCardEyes, + LockClosedOrange, }; diff --git a/src/languages/en.ts b/src/languages/en.ts index bf3803c7606d..3fb446536c9c 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2683,6 +2683,18 @@ export default { errorDescriptionPartTwo: 'reach out to Concierge', errorDescriptionPartThree: 'for help.', }, + restrictedAction: { + restricted: 'Restricted', + expensesAreCurrentlyRestricted: ({workspaceName}) => `Expenses to ${workspaceName} are currently restricted`, + workspaceOwnerWillNeedToAddOrUpdatePaymentCard: ({workspaceOwnerName}) => `Workspace owner, ${workspaceOwnerName} will need to add or update the payment card on file to unlock new workspace activity.`, + youWillNeedToAddOrUpdatePaymentCard: 'You\'ll need to add or update the payment card on file to unlock new workspace activity.', + addPaymentCardToUnlock: 'Add a payment card to unlock', + addPaymentCardToContinueUsingWorkspace: 'Add a payment card to continue using this workspace', + pleaseReachOutToYourWorkspaceAdmin: 'Please reach out to your workspace admin for any questions.', + chatWithYourAdmin: 'Chat with your admin', + chatInAdmins: 'Chat in #admins', + addPaymentCard: 'Add payment card', + } }, getAssistancePage: { title: 'Get assistance', diff --git a/src/languages/es.ts b/src/languages/es.ts index 4c900e23acc5..ac2a135d1055 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2721,6 +2721,18 @@ export default { errorDescriptionPartTwo: 'contacta con el conserje', errorDescriptionPartThree: 'por ayuda.', }, + restrictedAction: { + restricted: 'Restringido', + expensesAreCurrentlyRestricted: ({ workspaceName }) => `Los gastos para ${workspaceName} están actualmente restringidos`, + pleaseReachOutToYourWorkspaceAdmin: 'Si tienes alguna pregunta, ponte en contacto con el administrador de su espacio de trabajo.', + chatWithYourAdmin: 'Chatea con tu administrador', + workspaceOwnerWillNeedToAddOrUpdatePaymentCard: ({workspaceOwnerName}) => `El propietario del espacio de trabajo, ${workspaceOwnerName} tendrá que añadir o actualizar la tarjeta de pago registrada para desbloquear nueva actividad en el espacio de trabajo.`, + youWillNeedToAddOrUpdatePaymentCard: 'Debes añadir o actualizar la tarjeta de pago registrada para desbloquear nueva actividad en el espacio de trabajo.', + addPaymentCardToUnlock: 'Añade una tarjeta de pago para desbloquearlo', + addPaymentCardToContinueUsingWorkspace: 'Añade una tarjeta de pago para seguir utilizando este espacio de trabajo', + chatInAdmins: 'Chatea en #admins', + addPaymentCard: 'Agregar tarjeta de pago' + } }, getAssistancePage: { title: 'Obtener ayuda', diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index 0577fdcfc5aa..a6efe5fa5aed 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -372,6 +372,10 @@ const SearchReportModalStackNavigator = createModalStackNavigator require('../../../../pages/home/ReportScreen').default as React.ComponentType, }); +const RestrictedActionModalStackNavigator = createModalStackNavigator({ + [SCREENS.RESTRICTED_ACTION_ROOT]: () => require('../../../../pages/RestrictedAction/Workspace/WorkspaceRestrictedActionPage').default as React.ComponentType, +}); + export { AddPersonalBankAccountModalStackNavigator, EditRequestStackNavigator, @@ -400,4 +404,5 @@ export { TaskModalStackNavigator, WalletStatementStackNavigator, SearchReportModalStackNavigator, + RestrictedActionModalStackNavigator, }; diff --git a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx index be23969417f7..e58a895b6024 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx @@ -144,6 +144,10 @@ function RightModalNavigator({navigation}: RightModalNavigatorProps) { name={SCREENS.RIGHT_MODAL.SEARCH_REPORT} component={ModalStackNavigators.SearchReportModalStackNavigator} /> + diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 1b4288a9b3a9..a8751ca0ba84 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -740,6 +740,11 @@ const config: LinkingOptions['config'] = { [SCREENS.SEARCH.REPORT_RHP]: ROUTES.SEARCH_REPORT.route, }, }, + [SCREENS.RIGHT_MODAL.RESTRICTED_ACTION]: { + screens: { + [SCREENS.RESTRICTED_ACTION_ROOT]: ROUTES.RESTRICTED_ACTION.route, + }, + }, }, }, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index f90a91fe0f19..06cb8d805850 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -770,6 +770,7 @@ type RightModalNavigatorParamList = { [SCREENS.RIGHT_MODAL.PRIVATE_NOTES]: NavigatorScreenParams; [SCREENS.RIGHT_MODAL.TRAVEL]: NavigatorScreenParams; [SCREENS.RIGHT_MODAL.SEARCH_REPORT]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.RESTRICTED_ACTION]: NavigatorScreenParams; }; type TravelNavigatorParamList = { @@ -943,6 +944,12 @@ type SearchReportParamList = { }; }; +type RestrictedActionParamList = { + [SCREENS.RESTRICTED_ACTION_ROOT]: { + policyID: string; + }; +}; + type RootStackParamList = PublicScreensParamList & AuthScreensParamList & LeftModalNavigatorParamList; type BottomTabName = keyof BottomTabNavigatorParamList; @@ -1007,4 +1014,5 @@ export type { WalletStatementNavigatorParamList, WelcomeVideoModalNavigatorParamList, SearchReportParamList, + RestrictedActionParamList, }; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index a02b24c20e35..746f8f4483af 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -6964,6 +6964,11 @@ function shouldShowMerchantColumn(transactions: Transaction[]) { return transactions.some((transaction) => isExpenseReport(allReports?.[transaction.reportID] ?? {})); } +function findPolicyExpenseChatByPolicyID(policyID: string): OnyxEntry { + return Object.values(allReports ?? {}).find((report) => report?.isPolicyExpenseChat && report.policyID === policyID); +} + + export { addDomainToShortMention, areAllRequestsBeingSmartScanned, @@ -7236,6 +7241,7 @@ export { isDraftReport, changeMoneyRequestHoldStatus, createDraftWorkspaceAndNavigateToConfirmationScreen, + findPolicyExpenseChatByPolicyID, }; export type { diff --git a/src/pages/RestrictedAction/Workspace/WorkspaceAdminRestrictedAction.tsx b/src/pages/RestrictedAction/Workspace/WorkspaceAdminRestrictedAction.tsx new file mode 100644 index 000000000000..31c6ae37186d --- /dev/null +++ b/src/pages/RestrictedAction/Workspace/WorkspaceAdminRestrictedAction.tsx @@ -0,0 +1,68 @@ +import React, {useCallback} from 'react'; +import {View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import Button from '@components/Button'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import * as Illustrations from '@components/Icon/Illustrations'; +import ImageSVG from '@components/ImageSVG'; +import ScreenWrapper from '@components/ScreenWrapper'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as Report from '@libs/actions/Report'; +import Navigation from '@libs/Navigation/Navigation'; +import * as PolicyUtils from '@libs/PolicyUtils'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; + +type WorkspaceUserRestrictedActionProps = { + policyID: string; +}; + +function WorkspaceUserRestrictedAction({policyID}: WorkspaceUserRestrictedActionProps) { + const {translate} = useLocalize(); + const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); + const styles = useThemeStyles(); + + const onPress = useCallback(() => { + const reportID = `${PolicyUtils.getPolicy(policyID)?.chatReportIDAdmins}` ?? '-1'; + Report.openReport(reportID); + Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportID)); + }, [policyID]); + + return ( + + Navigation.goBack()} + /> + + + + + {translate('workspace.restrictedAction.expensesAreCurrentlyRestricted', {workspaceName: policy?.name})} + + + {translate('workspace.restrictedAction.workspaceOwnerWillNeedToAddOrUpdatePaymentCard', {workspaceOwnerName: policy?.owner})} + + +