From b71feac08e665f7d266d4cc9cc559d372551999e Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 26 Mar 2024 10:41:12 +0100 Subject: [PATCH 1/5] migrate step date --- ...uestStepDate.js => IOURequestStepDate.tsx} | 100 +++++++----------- 1 file changed, 41 insertions(+), 59 deletions(-) rename src/pages/iou/request/step/{IOURequestStepDate.js => IOURequestStepDate.tsx} (59%) diff --git a/src/pages/iou/request/step/IOURequestStepDate.js b/src/pages/iou/request/step/IOURequestStepDate.tsx similarity index 59% rename from src/pages/iou/request/step/IOURequestStepDate.js rename to src/pages/iou/request/step/IOURequestStepDate.tsx index f7b8b1ca3869..6147124a0c22 100644 --- a/src/pages/iou/request/step/IOURequestStepDate.js +++ b/src/pages/iou/request/step/IOURequestStepDate.tsx @@ -1,58 +1,44 @@ -import lodashGet from 'lodash/get'; import lodashIsEmpty from 'lodash/isEmpty'; -import PropTypes from 'prop-types'; import React from 'react'; +import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; -import categoryPropTypes from '@components/categoryPropTypes'; import DatePicker from '@components/DatePicker'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; -import tagPropTypes from '@components/tagPropTypes'; -import transactionPropTypes from '@components/transactionPropTypes'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import compose from '@libs/compose'; import * as IOUUtils from '@libs/IOUUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as TransactionUtils from '@libs/TransactionUtils'; import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import {policyPropTypes} from '@src/pages/workspace/withPolicy'; import INPUT_IDS from '@src/types/form/MoneyRequestDateForm'; -import IOURequestStepRoutePropTypes from './IOURequestStepRoutePropTypes'; +import type * as OnyxTypes from '@src/types/onyx'; import StepScreenWrapper from './StepScreenWrapper'; import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; +import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound'; import withWritableReportOrNotFound from './withWritableReportOrNotFound'; -const propTypes = { - /** Navigation route context info provided by react navigation */ - route: IOURequestStepRoutePropTypes.isRequired, - - /** Onyx Props */ - /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ - transaction: transactionPropTypes, - +type IOURequestStepDateOnyxProps = { /** The draft transaction that holds data to be persisted on the current transaction */ - splitDraftTransaction: transactionPropTypes, + splitDraftTransaction: OnyxEntry; /** The policy of the report */ - policy: policyPropTypes.policy, + policy: OnyxEntry; /** Collection of categories attached to a policy */ - policyCategories: PropTypes.objectOf(categoryPropTypes), + policyCategories: OnyxEntry; /** Collection of tags attached to a policy */ - policyTags: tagPropTypes, + policyTags: OnyxEntry; }; -const defaultProps = { - transaction: {}, - splitDraftTransaction: {}, - policy: null, - policyTags: null, - policyCategories: null, -}; +type IOURequestStepDateProps = { + /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ + transaction: OnyxEntry; +} & IOURequestStepDateOnyxProps & + WithWritableReportOrNotFoundProps; function IOURequestStepDate({ route: { @@ -63,7 +49,7 @@ function IOURequestStepDate({ policy, policyTags, policyCategories, -}) { +}: IOURequestStepDateProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); const isEditing = action === CONST.IOU.ACTION.EDIT; @@ -75,11 +61,7 @@ function IOURequestStepDate({ Navigation.goBack(backTo); }; - /** - * @param {Object} value - * @param {String} value.moneyRequestCreated - */ - const updateDate = (value) => { + const updateDate = (value: {moneyRequestCreated: string}) => { const newCreated = value.moneyRequestCreated; // Only update created if it has changed @@ -90,15 +72,15 @@ function IOURequestStepDate({ // In the split flow, when editing we use SPLIT_TRANSACTION_DRAFT to save draft value if (isEditingSplitBill) { - IOU.setDraftSplitTransaction(transaction.transactionID, {created: newCreated}); + IOU.setDraftSplitTransaction(transaction?.transactionID ?? '0', {created: newCreated}); navigateBack(); return; } - IOU.setMoneyRequestCreated(transaction.transactionID, newCreated, action === CONST.IOU.ACTION.CREATE); + IOU.setMoneyRequestCreated(transaction?.transactionID ?? '0', newCreated, action === CONST.IOU.ACTION.CREATE); if (isEditing) { - IOU.updateMoneyRequestDate(transaction.transactionID, reportID, newCreated, policy, policyTags, policyCategories); + IOU.updateMoneyRequestDate(transaction?.transactionID ?? '0', reportID, newCreated, policy, policyTags, policyCategories); } navigateBack(); @@ -108,7 +90,7 @@ function IOURequestStepDate({ @@ -132,28 +114,28 @@ function IOURequestStepDate({ ); } -IOURequestStepDate.propTypes = propTypes; -IOURequestStepDate.defaultProps = defaultProps; IOURequestStepDate.displayName = 'IOURequestStepDate'; -export default compose( - withWritableReportOrNotFound, - withFullTransactionOrNotFound, - withOnyx({ - splitDraftTransaction: { - key: ({route}) => { - const transactionID = lodashGet(route, 'params.transactionID', 0); - return `${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`; - }, - }, - policy: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`, - }, - policyCategories: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report ? report.policyID : '0'}`, - }, - policyTags: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '0'}`, +// eslint-disable-next-line rulesdir/no-negated-variables +const IOURequestStepDateWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepDate); +// eslint-disable-next-line rulesdir/no-negated-variables +const IOURequestStepDateWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepDateWithWritableReportOrNotFound); + +export default withOnyx({ + splitDraftTransaction: { + key: ({route}) => { + const transactionID = route?.params.transactionID ?? 0; + return `${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`; }, - }), -)(IOURequestStepDate); + }, + policy: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`, + }, + policyCategories: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report ? report.policyID : '0'}`, + }, + policyTags: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '0'}`, + }, + // @ts-expect-error TODO: Remove this once withFullTransactionOrNotFound (https://github.com/Expensify/App/issues/36123) is migrated to TypeScript. +})(IOURequestStepDateWithFullTransactionOrNotFound); From 85621d354773be097de823606f41e677957adec0 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 26 Mar 2024 12:46:17 +0100 Subject: [PATCH 2/5] migrate IOURequestStepDescription --- src/libs/Navigation/types.ts | 19 +- .../iou/request/step/IOURequestStepDate.tsx | 11 +- ...ption.js => IOURequestStepDescription.tsx} | 169 +++++++----------- .../request/step/IOURequestStepWaypoint.tsx | 9 +- .../step/withWritableReportOrNotFound.tsx | 8 +- 5 files changed, 95 insertions(+), 121 deletions(-) rename src/pages/iou/request/step/{IOURequestStepDescription.js => IOURequestStepDescription.tsx} (56%) diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 3f85aec3a560..b8859e9635d4 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -336,47 +336,48 @@ type MoneyRequestNavigatorParamList = { iouType: string; reportID: string; currency: string; - backTo: string; + backTo: Routes; }; [SCREENS.MONEY_REQUEST.STEP_DATE]: { action: ValueOf; iouType: ValueOf; transactionID: string; reportID: string; - backTo: string; + backTo: Routes; }; [SCREENS.MONEY_REQUEST.STEP_DESCRIPTION]: { action: ValueOf; iouType: ValueOf; transactionID: string; reportID: string; - backTo: string; + backTo: Routes; + reportActionID: string; }; [SCREENS.MONEY_REQUEST.STEP_CATEGORY]: { action: ValueOf; iouType: ValueOf; transactionID: string; reportID: string; - backTo: string; + backTo: Routes; }; [SCREENS.MONEY_REQUEST.STEP_TAX_AMOUNT]: { iouType: string; transactionID: string; reportID: string; - backTo: string; + backTo: Routes; }; [SCREENS.MONEY_REQUEST.STEP_TAG]: { action: ValueOf; iouType: ValueOf; transactionID: string; reportID: string; - backTo: string; + backTo: Routes; }; [SCREENS.MONEY_REQUEST.STEP_TAX_RATE]: { iouType: string; transactionID: string; reportID: string; - backTo: string; + backTo: Routes; }; [SCREENS.MONEY_REQUEST.STEP_WAYPOINT]: { iouType: ValueOf; @@ -391,7 +392,7 @@ type MoneyRequestNavigatorParamList = { iouType: ValueOf; transactionID: string; reportID: string; - backTo: string; + backTo: Routes; }; [SCREENS.IOU_SEND.ENABLE_PAYMENTS]: undefined; [SCREENS.IOU_SEND.ADD_BANK_ACCOUNT]: undefined; @@ -407,7 +408,7 @@ type MoneyRequestNavigatorParamList = { iouType: ValueOf; transactionID: string; reportID: string; - backTo: string; + backTo: Routes; }; [SCREENS.MONEY_REQUEST.RECEIPT]: { iouType: string; diff --git a/src/pages/iou/request/step/IOURequestStepDate.tsx b/src/pages/iou/request/step/IOURequestStepDate.tsx index 6147124a0c22..0dc3f79df15f 100644 --- a/src/pages/iou/request/step/IOURequestStepDate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDate.tsx @@ -13,6 +13,7 @@ import * as TransactionUtils from '@libs/TransactionUtils'; import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import type SCREENS from '@src/SCREENS'; import INPUT_IDS from '@src/types/form/MoneyRequestDateForm'; import type * as OnyxTypes from '@src/types/onyx'; import StepScreenWrapper from './StepScreenWrapper'; @@ -34,11 +35,11 @@ type IOURequestStepDateOnyxProps = { policyTags: OnyxEntry; }; -type IOURequestStepDateProps = { - /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ - transaction: OnyxEntry; -} & IOURequestStepDateOnyxProps & - WithWritableReportOrNotFoundProps; +type IOURequestStepDateProps = IOURequestStepDateOnyxProps & + WithWritableReportOrNotFoundProps & { + /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ + transaction: OnyxEntry; + }; function IOURequestStepDate({ route: { diff --git a/src/pages/iou/request/step/IOURequestStepDescription.js b/src/pages/iou/request/step/IOURequestStepDescription.tsx similarity index 56% rename from src/pages/iou/request/step/IOURequestStepDescription.js rename to src/pages/iou/request/step/IOURequestStepDescription.tsx index 8c3327a5ee5c..be4187af0cf5 100644 --- a/src/pages/iou/request/step/IOURequestStepDescription.js +++ b/src/pages/iou/request/step/IOURequestStepDescription.tsx @@ -1,81 +1,56 @@ import {useFocusEffect} from '@react-navigation/native'; -import lodashGet from 'lodash/get'; import lodashIsEmpty from 'lodash/isEmpty'; -import PropTypes from 'prop-types'; import React, {useCallback, useRef} from 'react'; import {View} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; -import categoryPropTypes from '@components/categoryPropTypes'; import FormProvider from '@components/Form/FormProvider'; import InputWrapperWithRef from '@components/Form/InputWrapper'; -import tagPropTypes from '@components/tagPropTypes'; +import type {AnimatedTextInputRef} from '@components/RNTextInput'; import TextInput from '@components/TextInput'; -import transactionPropTypes from '@components/transactionPropTypes'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import compose from '@libs/compose'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as ReportUtils from '@libs/ReportUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; import updateMultilineInputRange from '@libs/updateMultilineInputRange'; -import reportActionPropTypes from '@pages/home/report/reportActionPropTypes'; -import reportPropTypes from '@pages/reportPropTypes'; import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import {policyPropTypes} from '@src/pages/workspace/withPolicy'; +import type SCREENS from '@src/SCREENS'; import INPUT_IDS from '@src/types/form/MoneyRequestDescriptionForm'; -import IOURequestStepRoutePropTypes from './IOURequestStepRoutePropTypes'; +import type * as OnyxTypes from '@src/types/onyx'; import StepScreenWrapper from './StepScreenWrapper'; import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; +import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound'; import withWritableReportOrNotFound from './withWritableReportOrNotFound'; -const propTypes = { - /** Navigation route context info provided by react navigation */ - route: IOURequestStepRoutePropTypes.isRequired, - - /** Onyx Props */ - /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ - transaction: transactionPropTypes, - +type IOURequestStepDescriptionOnyxProps = { /** The draft transaction that holds data to be persisted on the current transaction */ - splitDraftTransaction: transactionPropTypes, + splitDraftTransaction: OnyxEntry; /** The policy of the report */ - policy: policyPropTypes.policy, + policy: OnyxEntry; /** Collection of categories attached to a policy */ - policyCategories: PropTypes.objectOf(categoryPropTypes), + policyCategories: OnyxEntry; /** Collection of tags attached to a policy */ - policyTags: tagPropTypes, + policyTags: OnyxEntry; /** The actions from the parent report */ - reportActions: PropTypes.shape(reportActionPropTypes), + reportActions: OnyxEntry; /** Session info for the currently logged in user. */ - session: PropTypes.shape({ - /** Currently logged in user accountID */ - accountID: PropTypes.number, - - /** Currently logged in user email */ - email: PropTypes.string, - }).isRequired, - - /** The report attached to the transaction */ - report: reportPropTypes, + session: OnyxEntry; }; -const defaultProps = { - transaction: {}, - splitDraftTransaction: {}, - policy: null, - policyTags: null, - policyCategories: null, - reportActions: {}, - report: {}, -}; +type IOURequestStepDescriptionProps = IOURequestStepDescriptionOnyxProps & + WithWritableReportOrNotFoundProps & { + /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ + transaction: OnyxEntry; + }; function IOURequestStepDescription({ route: { @@ -89,15 +64,14 @@ function IOURequestStepDescription({ reportActions, session, report, -}) { +}: IOURequestStepDescriptionProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); - const inputRef = useRef(null); - const focusTimeoutRef = useRef(null); + const inputRef = useRef(null); + const focusTimeoutRef = useRef | null>(null); // In the split flow, when editing we use SPLIT_TRANSACTION_DRAFT to save draft value const isEditingSplitBill = iouType === CONST.IOU.TYPE.SPLIT && action === CONST.IOU.ACTION.EDIT; - const currentDescription = - isEditingSplitBill && !lodashIsEmpty(splitDraftTransaction) ? lodashGet(splitDraftTransaction, 'comment.comment', '') : lodashGet(transaction, 'comment.comment', ''); + const currentDescription = isEditingSplitBill && !lodashIsEmpty(splitDraftTransaction) ? splitDraftTransaction?.comment.comment ?? '' : transaction?.comment.comment ?? ''; useFocusEffect( useCallback(() => { focusTimeoutRef.current = setTimeout(() => { @@ -115,17 +89,15 @@ function IOURequestStepDescription({ ); /** - * @param {Object} values - * @param {String} values.title * @returns {Object} - An object containing the errors for each inputID */ - const validate = useCallback((values) => { + const validate = useCallback((value: {moneyRequestComment: string}) => { const errors = {}; - if (values.moneyRequestComment.length > CONST.DESCRIPTION_LIMIT) { + if (value.moneyRequestComment.length > CONST.DESCRIPTION_LIMIT) { ErrorUtils.addErrorMessage(errors, 'moneyRequestComment', [ 'common.error.characterLimitExceedCounter', - {length: values.moneyRequestComment.length, limit: CONST.DESCRIPTION_LIMIT}, + {length: value.moneyRequestComment.length, limit: CONST.DESCRIPTION_LIMIT}, ]); } @@ -136,11 +108,7 @@ function IOURequestStepDescription({ Navigation.goBack(backTo); }; - /** - * @param {Object} value - * @param {String} value.moneyRequestComment - */ - const updateComment = (value) => { + const updateComment = (value: {moneyRequestComment: string}) => { const newComment = value.moneyRequestComment.trim(); // Only update comment if it has changed @@ -151,24 +119,25 @@ function IOURequestStepDescription({ // In the split flow, when editing we use SPLIT_TRANSACTION_DRAFT to save draft value if (isEditingSplitBill) { - IOU.setDraftSplitTransaction(transaction.transactionID, {comment: newComment}); + IOU.setDraftSplitTransaction(transaction?.transactionID ?? '0', {comment: newComment}); navigateBack(); return; } - IOU.setMoneyRequestDescription(transaction.transactionID, newComment, action === CONST.IOU.ACTION.CREATE); + IOU.setMoneyRequestDescription(transaction?.transactionID ?? '0', newComment, action === CONST.IOU.ACTION.CREATE); if (action === CONST.IOU.ACTION.EDIT) { - IOU.updateMoneyRequestDescription(transaction.transactionID, reportID, newComment, policy, policyTags, policyCategories); + IOU.updateMoneyRequestDescription(transaction?.transactionID ?? '0', reportID, newComment, policy, policyTags, policyCategories); } navigateBack(); }; - const reportAction = reportActions[report.parentReportActionID || reportActionID]; + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- nullish coalescing doesn't achieve the same result in this case + const reportAction = reportActions?.[report?.parentReportActionID || reportActionID] ?? null; const isEditing = action === CONST.IOU.ACTION.EDIT; const isSplitBill = iouType === CONST.IOU.TYPE.SPLIT; - const canEditSplitBill = isSplitBill && reportAction && session.accountID === reportAction.actorAccountID && TransactionUtils.areRequiredFieldsEmpty(transaction); + const canEditSplitBill = isSplitBill && reportAction && session?.accountID === reportAction.actorAccountID && TransactionUtils.areRequiredFieldsEmpty(transaction); // eslint-disable-next-line rulesdir/no-negated-variables const shouldShowNotFoundPage = isEditing && (isSplitBill ? !canEditSplitBill : !ReportUtils.canEditMoneyRequest(reportAction)); return ( @@ -213,46 +182,46 @@ function IOURequestStepDescription({ ); } -IOURequestStepDescription.propTypes = propTypes; -IOURequestStepDescription.defaultProps = defaultProps; IOURequestStepDescription.displayName = 'IOURequestStepDescription'; -export default compose( - withWritableReportOrNotFound, - withFullTransactionOrNotFound, - withOnyx({ - splitDraftTransaction: { - key: ({route}) => { - const transactionID = lodashGet(route, 'params.transactionID', 0); - return `${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`; - }, - }, - policy: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`, - }, - policyCategories: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report ? report.policyID : '0'}`, - }, - policyTags: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '0'}`, +// eslint-disable-next-line rulesdir/no-negated-variables +const IOURequestStepDescriptionWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepDescription); +// eslint-disable-next-line rulesdir/no-negated-variables +const IOURequestStepDescriptionWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepDescriptionWithWritableReportOrNotFound); + +export default withOnyx({ + splitDraftTransaction: { + key: ({route}) => { + const transactionID = route?.params.transactionID ?? 0; + return `${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`; }, - reportActions: { - key: ({ - report, - route: { - params: {action, iouType}, - }, - }) => { - let reportID = '0'; - if (action === CONST.IOU.ACTION.EDIT) { - reportID = iouType === CONST.IOU.TYPE.SPLIT ? report.reportID : report.parentReportID; - } - return `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`; + }, + policy: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`, + }, + policyCategories: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report ? report.policyID : '0'}`, + }, + policyTags: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '0'}`, + }, + reportActions: { + key: ({ + report, + route: { + params: {action, iouType}, }, - canEvict: false, - }, - session: { - key: ONYXKEYS.SESSION, + }) => { + let reportID = '0'; + if (action === CONST.IOU.ACTION.EDIT) { + reportID = iouType === CONST.IOU.TYPE.SPLIT ? report?.reportID ?? '0' : report?.parentReportID ?? '0'; + } + return `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`; }, - }), -)(IOURequestStepDescription); + canEvict: false, + }, + session: { + key: ONYXKEYS.SESSION, + }, + // @ts-expect-error TODO: Remove this once withFullTransactionOrNotFound (https://github.com/Expensify/App/issues/36123) is migrated to TypeScript. +})(IOURequestStepDescriptionWithFullTransactionOrNotFound); diff --git a/src/pages/iou/request/step/IOURequestStepWaypoint.tsx b/src/pages/iou/request/step/IOURequestStepWaypoint.tsx index 4e61ac944aac..a186288e8a27 100644 --- a/src/pages/iou/request/step/IOURequestStepWaypoint.tsx +++ b/src/pages/iou/request/step/IOURequestStepWaypoint.tsx @@ -27,6 +27,7 @@ import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import type SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; import type {Waypoint} from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; @@ -41,10 +42,10 @@ type IOURequestStepWaypointOnyxProps = { userLocation: OnyxEntry; }; -type IOURequestStepWaypointProps = { - transaction: OnyxEntry; -} & IOURequestStepWaypointOnyxProps & - WithWritableReportOrNotFoundProps; +type IOURequestStepWaypointProps = IOURequestStepWaypointOnyxProps & + WithWritableReportOrNotFoundProps & { + transaction: OnyxEntry; + }; function IOURequestStepWaypoint({ route: { diff --git a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx index d5d27d8268b1..31f590c192d1 100644 --- a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx +++ b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx @@ -17,11 +17,13 @@ type WithWritableReportOrNotFoundOnyxProps = { report: OnyxEntry; }; -type Route = RouteProp; +type MoneyRequestStepType = typeof SCREENS.MONEY_REQUEST.STEP_WAYPOINT | typeof SCREENS.MONEY_REQUEST.STEP_DESCRIPTION; -type WithWritableReportOrNotFoundProps = WithWritableReportOrNotFoundOnyxProps & {route: Route}; +type Route = RouteProp; -export default function ( +type WithWritableReportOrNotFoundProps = WithWritableReportOrNotFoundOnyxProps & {route: Route}; + +export default function , TRef>( WrappedComponent: ComponentType>, ): React.ComponentType, keyof WithWritableReportOrNotFoundOnyxProps>> { // eslint-disable-next-line rulesdir/no-negated-variables From 9d8e8a1985cb31d7fd1343971d46cb466e7cc4d9 Mon Sep 17 00:00:00 2001 From: war-in Date: Wed, 27 Mar 2024 09:42:03 +0100 Subject: [PATCH 3/5] add missing types --- src/pages/iou/request/step/IOURequestStepDate.tsx | 6 +++++- src/pages/iou/request/step/IOURequestStepDescription.tsx | 9 +++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepDate.tsx b/src/pages/iou/request/step/IOURequestStepDate.tsx index 0dc3f79df15f..96e9f9207764 100644 --- a/src/pages/iou/request/step/IOURequestStepDate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDate.tsx @@ -21,6 +21,10 @@ import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound'; import withWritableReportOrNotFound from './withWritableReportOrNotFound'; +type MoneyRequestCreated = { + moneyRequestCreated: string; +}; + type IOURequestStepDateOnyxProps = { /** The draft transaction that holds data to be persisted on the current transaction */ splitDraftTransaction: OnyxEntry; @@ -62,7 +66,7 @@ function IOURequestStepDate({ Navigation.goBack(backTo); }; - const updateDate = (value: {moneyRequestCreated: string}) => { + const updateDate = (value: MoneyRequestCreated) => { const newCreated = value.moneyRequestCreated; // Only update created if it has changed diff --git a/src/pages/iou/request/step/IOURequestStepDescription.tsx b/src/pages/iou/request/step/IOURequestStepDescription.tsx index be4187af0cf5..829615f9fecd 100644 --- a/src/pages/iou/request/step/IOURequestStepDescription.tsx +++ b/src/pages/iou/request/step/IOURequestStepDescription.tsx @@ -21,11 +21,16 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import INPUT_IDS from '@src/types/form/MoneyRequestDescriptionForm'; import type * as OnyxTypes from '@src/types/onyx'; +import type {Errors} from '@src/types/onyx/OnyxCommon'; import StepScreenWrapper from './StepScreenWrapper'; import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound'; import withWritableReportOrNotFound from './withWritableReportOrNotFound'; +type MoneyRequestComment = { + moneyRequestComment: string; +}; + type IOURequestStepDescriptionOnyxProps = { /** The draft transaction that holds data to be persisted on the current transaction */ splitDraftTransaction: OnyxEntry; @@ -89,9 +94,9 @@ function IOURequestStepDescription({ ); /** - * @returns {Object} - An object containing the errors for each inputID + * @returns - An object containing the errors for each inputID */ - const validate = useCallback((value: {moneyRequestComment: string}) => { + const validate = useCallback((value: MoneyRequestComment): Errors => { const errors = {}; if (value.moneyRequestComment.length > CONST.DESCRIPTION_LIMIT) { From fffd56bf9950c09b43bbed2e665c62a8854822c2 Mon Sep 17 00:00:00 2001 From: war-in Date: Wed, 27 Mar 2024 12:10:26 +0100 Subject: [PATCH 4/5] fix wrong HOC order --- .../iou/request/step/IOURequestStepDate.tsx | 17 +++++++++-------- .../request/step/IOURequestStepDescription.tsx | 17 +++++++++-------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepDate.tsx b/src/pages/iou/request/step/IOURequestStepDate.tsx index 96e9f9207764..11cffd500199 100644 --- a/src/pages/iou/request/step/IOURequestStepDate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDate.tsx @@ -121,12 +121,7 @@ function IOURequestStepDate({ IOURequestStepDate.displayName = 'IOURequestStepDate'; -// eslint-disable-next-line rulesdir/no-negated-variables -const IOURequestStepDateWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepDate); -// eslint-disable-next-line rulesdir/no-negated-variables -const IOURequestStepDateWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepDateWithWritableReportOrNotFound); - -export default withOnyx({ +const IOURequestStepDateWithOnyx = withOnyx({ splitDraftTransaction: { key: ({route}) => { const transactionID = route?.params.transactionID ?? 0; @@ -142,5 +137,11 @@ export default withOnyx({ policyTags: { key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '0'}`, }, - // @ts-expect-error TODO: Remove this once withFullTransactionOrNotFound (https://github.com/Expensify/App/issues/36123) is migrated to TypeScript. -})(IOURequestStepDateWithFullTransactionOrNotFound); +})(IOURequestStepDate); + +// eslint-disable-next-line rulesdir/no-negated-variables +const IOURequestStepDateWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepDateWithOnyx); +// eslint-disable-next-line rulesdir/no-negated-variables +const IOURequestStepDateWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepDateWithWritableReportOrNotFound); + +export default IOURequestStepDateWithFullTransactionOrNotFound; diff --git a/src/pages/iou/request/step/IOURequestStepDescription.tsx b/src/pages/iou/request/step/IOURequestStepDescription.tsx index 829615f9fecd..3fa695e26723 100644 --- a/src/pages/iou/request/step/IOURequestStepDescription.tsx +++ b/src/pages/iou/request/step/IOURequestStepDescription.tsx @@ -189,12 +189,7 @@ function IOURequestStepDescription({ IOURequestStepDescription.displayName = 'IOURequestStepDescription'; -// eslint-disable-next-line rulesdir/no-negated-variables -const IOURequestStepDescriptionWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepDescription); -// eslint-disable-next-line rulesdir/no-negated-variables -const IOURequestStepDescriptionWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepDescriptionWithWritableReportOrNotFound); - -export default withOnyx({ +const IOURequestStepDescriptionWithOnyx = withOnyx({ splitDraftTransaction: { key: ({route}) => { const transactionID = route?.params.transactionID ?? 0; @@ -228,5 +223,11 @@ export default withOnyx Date: Thu, 28 Mar 2024 08:38:43 +0100 Subject: [PATCH 5/5] review suggestions --- .../iou/request/step/IOURequestStepDate.tsx | 7 ++----- .../request/step/IOURequestStepDescription.tsx | 16 ++++++---------- .../step/withWritableReportOrNotFound.tsx | 8 ++++---- 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepDate.tsx b/src/pages/iou/request/step/IOURequestStepDate.tsx index 11cffd500199..682204a4510f 100644 --- a/src/pages/iou/request/step/IOURequestStepDate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDate.tsx @@ -5,6 +5,7 @@ import {withOnyx} from 'react-native-onyx'; import DatePicker from '@components/DatePicker'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; +import type {FormOnyxValues} from '@components/Form/types'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as IOUUtils from '@libs/IOUUtils'; @@ -21,10 +22,6 @@ import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound'; import withWritableReportOrNotFound from './withWritableReportOrNotFound'; -type MoneyRequestCreated = { - moneyRequestCreated: string; -}; - type IOURequestStepDateOnyxProps = { /** The draft transaction that holds data to be persisted on the current transaction */ splitDraftTransaction: OnyxEntry; @@ -66,7 +63,7 @@ function IOURequestStepDate({ Navigation.goBack(backTo); }; - const updateDate = (value: MoneyRequestCreated) => { + const updateDate = (value: FormOnyxValues) => { const newCreated = value.moneyRequestCreated; // Only update created if it has changed diff --git a/src/pages/iou/request/step/IOURequestStepDescription.tsx b/src/pages/iou/request/step/IOURequestStepDescription.tsx index 3fa695e26723..d075ed81c956 100644 --- a/src/pages/iou/request/step/IOURequestStepDescription.tsx +++ b/src/pages/iou/request/step/IOURequestStepDescription.tsx @@ -6,6 +6,7 @@ import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; import InputWrapperWithRef from '@components/Form/InputWrapper'; +import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; import type {AnimatedTextInputRef} from '@components/RNTextInput'; import TextInput from '@components/TextInput'; import useLocalize from '@hooks/useLocalize'; @@ -21,16 +22,11 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import INPUT_IDS from '@src/types/form/MoneyRequestDescriptionForm'; import type * as OnyxTypes from '@src/types/onyx'; -import type {Errors} from '@src/types/onyx/OnyxCommon'; import StepScreenWrapper from './StepScreenWrapper'; import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound'; import withWritableReportOrNotFound from './withWritableReportOrNotFound'; -type MoneyRequestComment = { - moneyRequestComment: string; -}; - type IOURequestStepDescriptionOnyxProps = { /** The draft transaction that holds data to be persisted on the current transaction */ splitDraftTransaction: OnyxEntry; @@ -73,7 +69,7 @@ function IOURequestStepDescription({ const styles = useThemeStyles(); const {translate} = useLocalize(); const inputRef = useRef(null); - const focusTimeoutRef = useRef | null>(null); + const focusTimeoutRef = useRef(null); // In the split flow, when editing we use SPLIT_TRANSACTION_DRAFT to save draft value const isEditingSplitBill = iouType === CONST.IOU.TYPE.SPLIT && action === CONST.IOU.ACTION.EDIT; const currentDescription = isEditingSplitBill && !lodashIsEmpty(splitDraftTransaction) ? splitDraftTransaction?.comment.comment ?? '' : transaction?.comment.comment ?? ''; @@ -96,13 +92,13 @@ function IOURequestStepDescription({ /** * @returns - An object containing the errors for each inputID */ - const validate = useCallback((value: MoneyRequestComment): Errors => { + const validate = useCallback((values: FormOnyxValues): FormInputErrors => { const errors = {}; - if (value.moneyRequestComment.length > CONST.DESCRIPTION_LIMIT) { + if (values.moneyRequestComment.length > CONST.DESCRIPTION_LIMIT) { ErrorUtils.addErrorMessage(errors, 'moneyRequestComment', [ 'common.error.characterLimitExceedCounter', - {length: value.moneyRequestComment.length, limit: CONST.DESCRIPTION_LIMIT}, + {length: values.moneyRequestComment.length, limit: CONST.DESCRIPTION_LIMIT}, ]); } @@ -113,7 +109,7 @@ function IOURequestStepDescription({ Navigation.goBack(backTo); }; - const updateComment = (value: {moneyRequestComment: string}) => { + const updateComment = (value: FormOnyxValues) => { const newComment = value.moneyRequestComment.trim(); // Only update comment if it has changed diff --git a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx index 31f590c192d1..de49a451da08 100644 --- a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx +++ b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx @@ -17,13 +17,13 @@ type WithWritableReportOrNotFoundOnyxProps = { report: OnyxEntry; }; -type MoneyRequestStepType = typeof SCREENS.MONEY_REQUEST.STEP_WAYPOINT | typeof SCREENS.MONEY_REQUEST.STEP_DESCRIPTION; +type MoneyRequestRouteName = typeof SCREENS.MONEY_REQUEST.STEP_WAYPOINT | typeof SCREENS.MONEY_REQUEST.STEP_DESCRIPTION; -type Route = RouteProp; +type Route = RouteProp; -type WithWritableReportOrNotFoundProps = WithWritableReportOrNotFoundOnyxProps & {route: Route}; +type WithWritableReportOrNotFoundProps = WithWritableReportOrNotFoundOnyxProps & {route: Route}; -export default function , TRef>( +export default function , TRef>( WrappedComponent: ComponentType>, ): React.ComponentType, keyof WithWritableReportOrNotFoundOnyxProps>> { // eslint-disable-next-line rulesdir/no-negated-variables