From 4f87b179df5eb79621c333a0607cea84b9610ead Mon Sep 17 00:00:00 2001 From: VickyStash Date: Tue, 23 Jan 2024 15:26:10 +0100 Subject: [PATCH 1/5] [TS migration] Migrate 'WorkspaceBills' page --- ...tion.js => WorkspaceBillsFirstSection.tsx} | 76 ++++++++----------- ...VBAView.js => WorkspaceBillsNoVBAView.tsx} | 30 ++++---- .../workspace/bills/WorkspaceBillsPage.js | 42 ---------- .../workspace/bills/WorkspaceBillsPage.tsx | 35 +++++++++ ...lsVBAView.js => WorkspaceBillsVBAView.tsx} | 28 ++++--- 5 files changed, 93 insertions(+), 118 deletions(-) rename src/pages/workspace/bills/{WorkspaceBillsFirstSection.js => WorkspaceBillsFirstSection.tsx} (54%) rename src/pages/workspace/bills/{WorkspaceBillsNoVBAView.js => WorkspaceBillsNoVBAView.tsx} (50%) delete mode 100644 src/pages/workspace/bills/WorkspaceBillsPage.js create mode 100644 src/pages/workspace/bills/WorkspaceBillsPage.tsx rename src/pages/workspace/bills/{WorkspaceBillsVBAView.js => WorkspaceBillsVBAView.tsx} (59%) diff --git a/src/pages/workspace/bills/WorkspaceBillsFirstSection.js b/src/pages/workspace/bills/WorkspaceBillsFirstSection.tsx similarity index 54% rename from src/pages/workspace/bills/WorkspaceBillsFirstSection.js rename to src/pages/workspace/bills/WorkspaceBillsFirstSection.tsx index 3f7f59180c8b..5931e8b14843 100644 --- a/src/pages/workspace/bills/WorkspaceBillsFirstSection.js +++ b/src/pages/workspace/bills/WorkspaceBillsFirstSection.tsx @@ -1,56 +1,47 @@ import Str from 'expensify-common/lib/str'; -import PropTypes from 'prop-types'; import React from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; import CopyTextToClipboard from '@components/CopyTextToClipboard'; import * as Expensicons from '@components/Icon/Expensicons'; import * as Illustrations from '@components/Icon/Illustrations'; import Section from '@components/Section'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; +import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import compose from '@libs/compose'; -import userPropTypes from '@pages/settings/userPropTypes'; import * as Link from '@userActions/Link'; import ONYXKEYS from '@src/ONYXKEYS'; +import type {Session, User} from '@src/types/onyx'; -const propTypes = { - /** The policy ID currently being configured */ - policyID: PropTypes.string.isRequired, - - ...withLocalizePropTypes, - - /* From Onyx */ +type WorkspaceBillsFirstSectionOnyxProps = { /** Session of currently logged in user */ - session: PropTypes.shape({ - /** Email address */ - email: PropTypes.string.isRequired, - }), + session: OnyxEntry; /** Information about the logged in user's account */ - user: userPropTypes, + user: OnyxEntry; }; -const defaultProps = { - session: { - email: null, - }, - user: {}, +type WorkspaceBillsFirstSectionProps = WorkspaceBillsFirstSectionOnyxProps & { + /** The policy ID currently being configured */ + policyID: string; }; -function WorkspaceBillsFirstSection(props) { +function WorkspaceBillsFirstSection({session, policyID, user}: WorkspaceBillsFirstSectionProps) { const styles = useThemeStyles(); - const emailDomain = Str.extractEmailDomain(props.session.email); - const manageYourBillsUrl = `reports?policyID=${props.policyID}&from=all&type=bill&showStates=Open,Processing,Approved,Reimbursed,Archived&isAdvancedFilterMode=true`; + const {translate} = useLocalize(); + + const emailDomain = Str.extractEmailDomain(session?.email ?? ''); + const manageYourBillsUrl = `reports?policyID=${policyID}&from=all&type=bill&showStates=Open,Processing,Approved,Reimbursed,Archived&isAdvancedFilterMode=true`; + return (
Link.openOldDotLink(manageYourBillsUrl), icon: Expensicons.Bill, shouldShowRightIcon: true, @@ -59,40 +50,35 @@ function WorkspaceBillsFirstSection(props) { link: () => Link.buildOldDotURL(manageYourBillsUrl), }, ]} - containerStyles={[styles.cardSection]} + containerStyles={styles.cardSection} > - + - {props.translate('workspace.bills.askYourVendorsBeforeEmail')} - {props.user.isFromPublicDomain ? ( + {translate('workspace.bills.askYourVendorsBeforeEmail')} + {user?.isFromPublicDomain ? ( Link.openExternalLink('https://community.expensify.com/discussion/7500/how-to-pay-your-company-bills-in-expensify/')}> example.com@expensify.cash ) : ( )} - {props.translate('workspace.bills.askYourVendorsAfterEmail')} + {translate('workspace.bills.askYourVendorsAfterEmail')}
); } -WorkspaceBillsFirstSection.propTypes = propTypes; -WorkspaceBillsFirstSection.defaultProps = defaultProps; WorkspaceBillsFirstSection.displayName = 'WorkspaceBillsFirstSection'; -export default compose( - withLocalize, - withOnyx({ - session: { - key: ONYXKEYS.SESSION, - }, - user: { - key: ONYXKEYS.USER, - }, - }), -)(WorkspaceBillsFirstSection); +export default withOnyx({ + session: { + key: ONYXKEYS.SESSION, + }, + user: { + key: ONYXKEYS.USER, + }, +})(WorkspaceBillsFirstSection); diff --git a/src/pages/workspace/bills/WorkspaceBillsNoVBAView.js b/src/pages/workspace/bills/WorkspaceBillsNoVBAView.tsx similarity index 50% rename from src/pages/workspace/bills/WorkspaceBillsNoVBAView.js rename to src/pages/workspace/bills/WorkspaceBillsNoVBAView.tsx index 8211f70163d5..72f4d0ad2b8e 100644 --- a/src/pages/workspace/bills/WorkspaceBillsNoVBAView.js +++ b/src/pages/workspace/bills/WorkspaceBillsNoVBAView.tsx @@ -1,45 +1,43 @@ -import PropTypes from 'prop-types'; import React from 'react'; import {View} from 'react-native'; import ConnectBankAccountButton from '@components/ConnectBankAccountButton'; import * as Illustrations from '@components/Icon/Illustrations'; import Section from '@components/Section'; import Text from '@components/Text'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; +import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import WorkspaceBillsFirstSection from './WorkspaceBillsFirstSection'; -const propTypes = { +type WorkspaceBillsNoVBAViewProps = { /** The policy ID currently being configured */ - policyID: PropTypes.string.isRequired, - - ...withLocalizePropTypes, + policyID: string; }; -function WorkspaceBillsNoVBAView(props) { +function WorkspaceBillsNoVBAView({policyID}: WorkspaceBillsNoVBAViewProps) { const styles = useThemeStyles(); + const {translate} = useLocalize(); + return ( <> - +
- - {props.translate('workspace.bills.unlockNoVBACopy')} + + {translate('workspace.bills.unlockNoVBACopy')}
); } -WorkspaceBillsNoVBAView.propTypes = propTypes; WorkspaceBillsNoVBAView.displayName = 'WorkspaceBillsNoVBAView'; -export default withLocalize(WorkspaceBillsNoVBAView); +export default WorkspaceBillsNoVBAView; diff --git a/src/pages/workspace/bills/WorkspaceBillsPage.js b/src/pages/workspace/bills/WorkspaceBillsPage.js deleted file mode 100644 index c607071a4365..000000000000 --- a/src/pages/workspace/bills/WorkspaceBillsPage.js +++ /dev/null @@ -1,42 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; -import WorkspacePageWithSections from '@pages/workspace/WorkspacePageWithSections'; -import CONST from '@src/CONST'; -import WorkspaceBillsNoVBAView from './WorkspaceBillsNoVBAView'; -import WorkspaceBillsVBAView from './WorkspaceBillsVBAView'; - -const propTypes = { - /** The route object passed to this page from the navigator */ - route: PropTypes.shape({ - /** Each parameter passed via the URL */ - params: PropTypes.shape({ - /** The policyID that is being configured */ - policyID: PropTypes.string.isRequired, - }).isRequired, - }).isRequired, - - ...withLocalizePropTypes, -}; - -function WorkspaceBillsPage(props) { - return ( - - {(hasVBA, policyID) => ( - <> - {!hasVBA && } - {hasVBA && } - - )} - - ); -} - -WorkspaceBillsPage.propTypes = propTypes; -WorkspaceBillsPage.displayName = 'WorkspaceBillsPage'; -export default withLocalize(WorkspaceBillsPage); diff --git a/src/pages/workspace/bills/WorkspaceBillsPage.tsx b/src/pages/workspace/bills/WorkspaceBillsPage.tsx new file mode 100644 index 000000000000..da86839f39c1 --- /dev/null +++ b/src/pages/workspace/bills/WorkspaceBillsPage.tsx @@ -0,0 +1,35 @@ +import type {StackScreenProps} from '@react-navigation/stack'; +import React from 'react'; +import useLocalize from '@hooks/useLocalize'; +import type {SettingsNavigatorParamList} from '@navigation/types'; +import WorkspacePageWithSections from '@pages/workspace/WorkspacePageWithSections'; +import CONST from '@src/CONST'; +import type SCREENS from '@src/SCREENS'; +import WorkspaceBillsNoVBAView from './WorkspaceBillsNoVBAView'; +import WorkspaceBillsVBAView from './WorkspaceBillsVBAView'; + +type WorkspaceBillsPageProps = StackScreenProps; + +function WorkspaceBillsPage({route}: WorkspaceBillsPageProps) { + const {translate} = useLocalize(); + + return ( + + {(hasVBA: boolean, policyID: string) => ( + <> + {!hasVBA && } + {hasVBA && } + + )} + + ); +} + +WorkspaceBillsPage.displayName = 'WorkspaceBillsPage'; + +export default WorkspaceBillsPage; diff --git a/src/pages/workspace/bills/WorkspaceBillsVBAView.js b/src/pages/workspace/bills/WorkspaceBillsVBAView.tsx similarity index 59% rename from src/pages/workspace/bills/WorkspaceBillsVBAView.js rename to src/pages/workspace/bills/WorkspaceBillsVBAView.tsx index dd9c1c7fbaf6..ae06fac378dd 100644 --- a/src/pages/workspace/bills/WorkspaceBillsVBAView.js +++ b/src/pages/workspace/bills/WorkspaceBillsVBAView.tsx @@ -1,36 +1,35 @@ -import PropTypes from 'prop-types'; import React from 'react'; import {View} from 'react-native'; import * as Expensicons from '@components/Icon/Expensicons'; import * as Illustrations from '@components/Icon/Illustrations'; import Section from '@components/Section'; import Text from '@components/Text'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; +import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Link from '@userActions/Link'; import WorkspaceBillsFirstSection from './WorkspaceBillsFirstSection'; -const propTypes = { +type WorkspaceBillsVBAViewProps = { /** The policy ID currently being configured */ - policyID: PropTypes.string.isRequired, - - ...withLocalizePropTypes, + policyID: string; }; -function WorkspaceBillsVBAView(props) { +function WorkspaceBillsVBAView({policyID}: WorkspaceBillsVBAViewProps) { const styles = useThemeStyles(); - const reportsUrl = `reports?policyID=${props.policyID}&from=all&type=bill&showStates=Processing,Approved&isAdvancedFilterMode=true`; + const {translate} = useLocalize(); + + const reportsUrl = `reports?policyID=${policyID}&from=all&type=bill&showStates=Processing,Approved&isAdvancedFilterMode=true`; return ( <> - +
Link.openOldDotLink(reportsUrl), icon: Expensicons.Bill, shouldShowRightIcon: true, @@ -40,15 +39,14 @@ function WorkspaceBillsVBAView(props) { }, ]} > - - {props.translate('workspace.bills.VBACopy')} + + {translate('workspace.bills.VBACopy')}
); } -WorkspaceBillsVBAView.propTypes = propTypes; WorkspaceBillsVBAView.displayName = 'WorkspaceBillsVBAView'; -export default withLocalize(WorkspaceBillsVBAView); +export default WorkspaceBillsVBAView; From d3a6b8cacbf2d83b1b0a67e0f332be6ebfd4f725 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Tue, 23 Jan 2024 16:36:51 +0100 Subject: [PATCH 2/5] Update PolicyRoute type --- src/pages/workspace/WorkspacePageWithSections.tsx | 6 +++--- src/pages/workspace/invoices/WorkspaceInvoicesPage.tsx | 9 ++++----- src/pages/workspace/withPolicy.tsx | 8 ++++++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/pages/workspace/WorkspacePageWithSections.tsx b/src/pages/workspace/WorkspacePageWithSections.tsx index 8817f813a990..a469e5bd4dff 100644 --- a/src/pages/workspace/WorkspacePageWithSections.tsx +++ b/src/pages/workspace/WorkspacePageWithSections.tsx @@ -1,4 +1,3 @@ -import type {RouteProp} from '@react-navigation/native'; import React, {useEffect, useMemo, useRef} from 'react'; import type {ReactNode} from 'react'; import {View} from 'react-native'; @@ -14,6 +13,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import BankAccount from '@libs/models/BankAccount'; import Navigation from '@libs/Navigation/Navigation'; import * as PolicyUtils from '@libs/PolicyUtils'; +import type {PolicyRoute} from '@pages/workspace/withPolicy'; import * as BankAccounts from '@userActions/BankAccounts'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -40,10 +40,10 @@ type WorkspacePageWithSectionsProps = WithPolicyAndFullscreenLoadingProps & headerText: string; /** The route object passed to this page from the navigator */ - route: RouteProp<{params: {policyID: string}}>; + route: PolicyRoute; /** Main content of the page */ - children: (hasVBA?: boolean, policyID?: string, isUsingECard?: boolean) => ReactNode; + children: (hasVBA: boolean, policyID: string, isUsingECard: boolean) => ReactNode; /** Content to be added as fixed footer */ footer?: ReactNode; diff --git a/src/pages/workspace/invoices/WorkspaceInvoicesPage.tsx b/src/pages/workspace/invoices/WorkspaceInvoicesPage.tsx index 79ff76204c69..ffd9a700ae7e 100644 --- a/src/pages/workspace/invoices/WorkspaceInvoicesPage.tsx +++ b/src/pages/workspace/invoices/WorkspaceInvoicesPage.tsx @@ -1,15 +1,14 @@ -import type {RouteProp} from '@react-navigation/native'; +import type {StackScreenProps} from '@react-navigation/stack'; import React from 'react'; import useLocalize from '@hooks/useLocalize'; +import type {SettingsNavigatorParamList} from '@navigation/types'; import WorkspacePageWithSections from '@pages/workspace/WorkspacePageWithSections'; import CONST from '@src/CONST'; +import type SCREENS from '@src/SCREENS'; import WorkspaceInvoicesNoVBAView from './WorkspaceInvoicesNoVBAView'; import WorkspaceInvoicesVBAView from './WorkspaceInvoicesVBAView'; -/** Defined route object that contains the policyID param, WorkspacePageWithSections is a common component for Workspaces and expect the route prop that includes the policyID */ -type WorkspaceInvoicesPageProps = { - route: RouteProp<{params: {policyID: string}}>; -}; +type WorkspaceInvoicesPageProps = StackScreenProps; function WorkspaceInvoicesPage({route}: WorkspaceInvoicesPageProps) { const {translate} = useLocalize(); diff --git a/src/pages/workspace/withPolicy.tsx b/src/pages/workspace/withPolicy.tsx index ec38b61fb0dc..184a847a483e 100644 --- a/src/pages/workspace/withPolicy.tsx +++ b/src/pages/workspace/withPolicy.tsx @@ -5,13 +5,17 @@ import type {ComponentType, ForwardedRef, RefAttributes} from 'react'; import React, {forwardRef} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; +import type {SettingsNavigatorParamList} from '@navigation/types'; import policyMemberPropType from '@pages/policyMemberPropType'; import * as Policy from '@userActions/Policy'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import type SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; -type PolicyRoute = RouteProp<{params: {policyID: string}}>; +type PolicyRouteName = typeof SCREENS.WORKSPACE.BILLS | typeof SCREENS.WORKSPACE.INVOICES; + +type PolicyRoute = RouteProp; function getPolicyIDFromRoute(route: PolicyRoute): string { return route?.params?.policyID ?? ''; @@ -131,4 +135,4 @@ export default function (WrappedComponent: } export {policyPropTypes, policyDefaultProps}; -export type {WithPolicyOnyxProps, WithPolicyProps}; +export type {WithPolicyOnyxProps, WithPolicyProps, PolicyRoute}; From b32efdb4e7d53002629a67add427b7c0b2731358 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Tue, 23 Jan 2024 16:41:11 +0100 Subject: [PATCH 3/5] Fix lint error --- src/pages/workspace/WorkspacePageWithSections.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspacePageWithSections.tsx b/src/pages/workspace/WorkspacePageWithSections.tsx index a469e5bd4dff..8b45bfad771c 100644 --- a/src/pages/workspace/WorkspacePageWithSections.tsx +++ b/src/pages/workspace/WorkspacePageWithSections.tsx @@ -13,13 +13,13 @@ import useThemeStyles from '@hooks/useThemeStyles'; import BankAccount from '@libs/models/BankAccount'; import Navigation from '@libs/Navigation/Navigation'; import * as PolicyUtils from '@libs/PolicyUtils'; -import type {PolicyRoute} from '@pages/workspace/withPolicy'; import * as BankAccounts from '@userActions/BankAccounts'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {Route} from '@src/ROUTES'; import type {Policy, ReimbursementAccount, User} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import type {PolicyRoute} from './withPolicy'; import type {WithPolicyAndFullscreenLoadingProps} from './withPolicyAndFullscreenLoading'; import withPolicyAndFullscreenLoading from './withPolicyAndFullscreenLoading'; From 62d407ab050d8b98ae227732e987615d1b48c369 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Wed, 24 Jan 2024 11:49:23 +0100 Subject: [PATCH 4/5] Minor code improvement --- src/pages/workspace/withPolicy.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/pages/workspace/withPolicy.tsx b/src/pages/workspace/withPolicy.tsx index 184a847a483e..d2b087e00443 100644 --- a/src/pages/workspace/withPolicy.tsx +++ b/src/pages/workspace/withPolicy.tsx @@ -13,9 +13,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; -type PolicyRouteName = typeof SCREENS.WORKSPACE.BILLS | typeof SCREENS.WORKSPACE.INVOICES; - -type PolicyRoute = RouteProp; +type PolicyRoute = RouteProp; function getPolicyIDFromRoute(route: PolicyRoute): string { return route?.params?.policyID ?? ''; From 824d49eb33bcb9bea04af2932d58b0ec4446cdb3 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Mon, 29 Jan 2024 09:27:53 +0100 Subject: [PATCH 5/5] Simplify PolicyRoute typing --- src/pages/workspace/WorkspacePageWithSections.tsx | 2 +- src/pages/workspace/withPolicy.tsx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pages/workspace/WorkspacePageWithSections.tsx b/src/pages/workspace/WorkspacePageWithSections.tsx index 5047ea270dd7..65189a3c6468 100644 --- a/src/pages/workspace/WorkspacePageWithSections.tsx +++ b/src/pages/workspace/WorkspacePageWithSections.tsx @@ -93,7 +93,7 @@ function WorkspacePageWithSections({ const isLoading = reimbursementAccount?.isLoading ?? true; const achState = reimbursementAccount?.achData?.state ?? ''; const isUsingECard = user?.isUsingExpensifyCard ?? false; - const policyID = route.params.policyID; + const policyID = route.params?.policyID ?? ''; const policyName = policy?.name; const hasVBA = achState === BankAccount.STATE.OPEN; const content = children(hasVBA, policyID, isUsingECard); diff --git a/src/pages/workspace/withPolicy.tsx b/src/pages/workspace/withPolicy.tsx index d2b087e00443..aee03f1f74e9 100644 --- a/src/pages/workspace/withPolicy.tsx +++ b/src/pages/workspace/withPolicy.tsx @@ -5,6 +5,7 @@ import type {ComponentType, ForwardedRef, RefAttributes} from 'react'; import React, {forwardRef} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; +import type {ValueOf} from 'type-fest'; import type {SettingsNavigatorParamList} from '@navigation/types'; import policyMemberPropType from '@pages/policyMemberPropType'; import * as Policy from '@userActions/Policy'; @@ -13,7 +14,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; -type PolicyRoute = RouteProp; +type PolicyRoute = RouteProp>; function getPolicyIDFromRoute(route: PolicyRoute): string { return route?.params?.policyID ?? '';