From 747b8ea2f6bbc67d1f412fbbb12cb01687928067 Mon Sep 17 00:00:00 2001 From: brunovjk Date: Fri, 12 Apr 2024 10:37:04 -0300 Subject: [PATCH 01/24] Replace all uses of the Old Component with the New Component --- .../MoneyTemporaryForRefactorRequestConfirmationList.tsx | 5 ++++- src/pages/iou/SplitBillDetailsPage.tsx | 4 +--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx index 21815f00253b..6a63dcc9ff7d 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx @@ -112,7 +112,7 @@ type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps & selectedParticipants: Participant[]; /** Payee of the money request with login */ - payeePersonalDetails?: OnyxTypes.PersonalDetails; + payeePersonalDetails?: OnyxEntry; /** Can the participants be modified or not */ canModifyParticipants?: boolean; @@ -686,6 +686,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ transaction?.transactionID ?? '', reportID, Navigation.getActiveRouteWithoutParams(), + reportActionID, ), ); }} @@ -797,6 +798,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ transaction?.transactionID ?? '', reportID, Navigation.getActiveRouteWithoutParams(), + reportActionID, ), ) } @@ -829,6 +831,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ transaction?.transactionID ?? '', reportID, Navigation.getActiveRouteWithoutParams(), + reportActionID, ), ) } diff --git a/src/pages/iou/SplitBillDetailsPage.tsx b/src/pages/iou/SplitBillDetailsPage.tsx index 91aa37dd01c2..fca3b713dec8 100644 --- a/src/pages/iou/SplitBillDetailsPage.tsx +++ b/src/pages/iou/SplitBillDetailsPage.tsx @@ -5,7 +5,7 @@ import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import MoneyRequestConfirmationList from '@components/MoneyRequestConfirmationList'; +import MoneyRequestConfirmationList from '@components/MoneyTemporaryForRefactorRequestConfirmationList'; import MoneyRequestHeaderStatusBar from '@components/MoneyRequestHeaderStatusBar'; import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; @@ -85,7 +85,6 @@ function SplitBillDetailsPage({personalDetails, report, route, reportActions, tr merchant: splitMerchant, created: splitCreated, category: splitCategory, - tag: splitTag, billable: splitBillable, } = ReportUtils.getTransactionDetails(isEditingSplitBill && draftTransaction ? draftTransaction : transaction) ?? {}; @@ -117,7 +116,6 @@ function SplitBillDetailsPage({personalDetails, report, route, reportActions, tr iouCreated={splitCreated} iouMerchant={splitMerchant} iouCategory={splitCategory} - iouTag={splitTag} iouIsBillable={splitBillable} iouType={CONST.IOU.TYPE.SPLIT} isReadOnly={!isEditingSplitBill} From dc3e2e5533dcf142648939169380811ed0bd7ccf Mon Sep 17 00:00:00 2001 From: brunovjk Date: Fri, 12 Apr 2024 10:40:24 -0300 Subject: [PATCH 02/24] Remove Old Component --- .../MoneyRequestConfirmationList.tsx | 906 ------------------ 1 file changed, 906 deletions(-) delete mode 100755 src/components/MoneyRequestConfirmationList.tsx diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx deleted file mode 100755 index cadad07b6585..000000000000 --- a/src/components/MoneyRequestConfirmationList.tsx +++ /dev/null @@ -1,906 +0,0 @@ -import {useIsFocused} from '@react-navigation/native'; -import {format} from 'date-fns'; -import React, {useCallback, useEffect, useMemo, useReducer, useState} from 'react'; -import type {StyleProp, ViewStyle} from 'react-native'; -import {View} from 'react-native'; -import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; -import type {ValueOf} from 'type-fest'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; -import useLocalize from '@hooks/useLocalize'; -import usePermissions from '@hooks/usePermissions'; -import useTheme from '@hooks/useTheme'; -import useThemeStyles from '@hooks/useThemeStyles'; -import * as CurrencyUtils from '@libs/CurrencyUtils'; -import type {DefaultMileageRate} from '@libs/DistanceRequestUtils'; -import DistanceRequestUtils from '@libs/DistanceRequestUtils'; -import * as IOUUtils from '@libs/IOUUtils'; -import Log from '@libs/Log'; -import * as MoneyRequestUtils from '@libs/MoneyRequestUtils'; -import Navigation from '@libs/Navigation/Navigation'; -import * as OptionsListUtils from '@libs/OptionsListUtils'; -import * as PolicyUtils from '@libs/PolicyUtils'; -import * as ReceiptUtils from '@libs/ReceiptUtils'; -import * as ReportUtils from '@libs/ReportUtils'; -import * as TransactionUtils from '@libs/TransactionUtils'; -import * as IOU from '@userActions/IOU'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import type {Route} from '@src/ROUTES'; -import ROUTES from '@src/ROUTES'; -import type * as OnyxTypes from '@src/types/onyx'; -import type {Participant} from '@src/types/onyx/IOU'; -import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; -import type {ReceiptSource} from '@src/types/onyx/Transaction'; -import ButtonWithDropdownMenu from './ButtonWithDropdownMenu'; -import type {DropdownOption} from './ButtonWithDropdownMenu/types'; -import ConfirmedRoute from './ConfirmedRoute'; -import FormHelpMessage from './FormHelpMessage'; -import MenuItemWithTopDescription from './MenuItemWithTopDescription'; -import OptionsSelector from './OptionsSelector'; -import ReceiptEmptyState from './ReceiptEmptyState'; -import ReceiptImage from './ReceiptImage'; -import SettlementButton from './SettlementButton'; -import ShowMoreButton from './ShowMoreButton'; -import Switch from './Switch'; -import Text from './Text'; - -type IouType = ValueOf; - -type MoneyRequestConfirmationListOnyxProps = { - /** Collection of categories attached to a policy */ - policyCategories: OnyxEntry; - - /** Collection of tags attached to a policy */ - policyTags: OnyxEntry; - - /** The policy of the report */ - policy: OnyxEntry; - - /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ - iou: OnyxEntry; - - /** The session of the logged in user */ - session: OnyxEntry; - - /** Unit and rate used for if the money request is a distance request */ - mileageRate: OnyxEntry; -}; -type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps & { - /** Callback to inform parent modal of success */ - onConfirm?: (selectedParticipants: Array) => void; - - /** Callback to parent modal to send money */ - onSendMoney?: (paymentMethod: IouType | PaymentMethodType | undefined) => void; - - /** Callback to inform a participant is selected */ - onSelectParticipant?: (option: Participant) => void; - - /** Should we request a single or multiple participant selection from user */ - hasMultipleParticipants: boolean; - - /** IOU amount */ - iouAmount: number; - - /** IOU comment */ - iouComment?: string; - - /** IOU currency */ - iouCurrencyCode?: string; - - /** IOU type */ - iouType?: IouType; - - /** IOU date */ - iouCreated?: string; - - /** IOU merchant */ - iouMerchant?: string; - - /** IOU Category */ - iouCategory?: string; - - /** IOU Tag */ - iouTag?: string; - - /** IOU isBillable */ - iouIsBillable?: boolean; - - /** Callback to toggle the billable state */ - onToggleBillable?: (isOn: boolean) => void; - - /** Selected participants from MoneyRequestModal with login / accountID */ - selectedParticipants: Array; - - /** Payee of the money request with login */ - payeePersonalDetails?: OnyxEntry; - - /** Can the participants be modified or not */ - canModifyParticipants?: boolean; - - /** Should the list be read only, and not editable? */ - isReadOnly?: boolean; - - /** Depending on expense report or personal IOU report, respective bank account route */ - bankAccountRoute?: Route; - - /** The policyID of the request */ - policyID?: string; - - /** The reportID of the request */ - reportID?: string; - - /** File path of the receipt */ - receiptPath?: ReceiptSource; - - /** File name of the receipt */ - receiptFilename?: string; - - /** List styles for OptionsSelector */ - listStyles?: StyleProp; - - /** ID of the transaction that represents the money request */ - transactionID?: string; - - /** Transaction that represents the money request */ - transaction?: OnyxEntry; - - /** Whether the money request is a distance request */ - isDistanceRequest?: boolean; - - /** Whether the money request is a scan request */ - isScanRequest?: boolean; - - /** Whether we're editing a split bill */ - isEditingSplitBill?: boolean; - - /** Whether we should show the amount, date, and merchant fields. */ - shouldShowSmartScanFields?: boolean; - - /** A flag for verifying that the current report is a sub-report of a workspace chat */ - isPolicyExpenseChat?: boolean; - - /** Whether smart scan failed */ - hasSmartScanFailed?: boolean; - - /** The ID of the report action */ - reportActionID?: string; -}; - -function MoneyRequestConfirmationList({ - transaction = null, - onSendMoney, - onConfirm, - onSelectParticipant, - iouType = CONST.IOU.TYPE.REQUEST, - isScanRequest = false, - iouAmount, - policyCategories, - mileageRate, - isDistanceRequest = false, - policy, - isPolicyExpenseChat = false, - iouCategory = '', - shouldShowSmartScanFields = true, - isEditingSplitBill, - policyTags, - iouCurrencyCode, - iouMerchant, - hasMultipleParticipants, - selectedParticipants: selectedParticipantsProp, - payeePersonalDetails: payeePersonalDetailsProp, - iou = { - id: '', - amount: 0, - currency: CONST.CURRENCY.USD, - comment: '', - merchant: '', - category: '', - tag: '', - billable: false, - created: '', - participants: [], - receiptPath: '', - }, - canModifyParticipants: canModifyParticipantsProp = false, - session, - isReadOnly = false, - bankAccountRoute = '', - policyID = '', - reportID = '', - receiptPath = '', - iouComment, - receiptFilename = '', - listStyles, - iouCreated, - iouIsBillable = false, - onToggleBillable, - iouTag = '', - transactionID = '', - hasSmartScanFailed, - reportActionID, -}: MoneyRequestConfirmationListProps) { - const theme = useTheme(); - const styles = useThemeStyles(); - const {translate, toLocaleDigit} = useLocalize(); - const {canUseViolations} = usePermissions(); - const currentUserPersonalDetails = useCurrentUserPersonalDetails(); - - const isTypeRequest = iouType === CONST.IOU.TYPE.REQUEST; - const isSplitBill = iouType === CONST.IOU.TYPE.SPLIT; - const isTypeSend = iouType === CONST.IOU.TYPE.SEND; - - const isSplitWithScan = isSplitBill && isScanRequest; - - const {unit, rate, currency} = mileageRate ?? { - unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - rate: 0, - currency: CONST.CURRENCY.USD, - }; - const distance = transaction?.routes?.route0.distance ?? 0; - const shouldCalculateDistanceAmount = isDistanceRequest && iouAmount === 0; - const taxRates = policy?.taxRates; - - // A flag for showing the categories field - const shouldShowCategories = isPolicyExpenseChat && (!!iouCategory || OptionsListUtils.hasEnabledOptions(Object.values(policyCategories ?? {}))); - // A flag and a toggler for showing the rest of the form fields - const [shouldExpandFields, toggleShouldExpandFields] = useReducer((state) => !state, false); - - // Do not hide fields in case of send money request - const shouldShowAllFields = !!isDistanceRequest || shouldExpandFields || !shouldShowSmartScanFields || isTypeSend || isEditingSplitBill; - - // In Send Money and Split Bill with Scan flow, we don't allow the Merchant or Date to be edited. For distance requests, don't show the merchant as there's already another "Distance" menu item - const shouldShowDate = shouldShowAllFields && !isTypeSend && !isSplitWithScan; - const shouldShowMerchant = shouldShowAllFields && !isTypeSend && !isDistanceRequest && !isSplitWithScan; - - const policyTagLists = useMemo(() => PolicyUtils.getTagLists(policyTags), [policyTags]); - - // A flag for showing the tags field - const shouldShowTags = isPolicyExpenseChat && (!!iouTag || OptionsListUtils.hasEnabledTags(policyTagLists)); - - // A flag for showing tax fields - tax rate and tax amount - const shouldShowTax = isPolicyExpenseChat && (policy?.tax?.trackingEnabled ?? policy?.isTaxTrackingEnabled); - - // A flag for showing the billable field - const shouldShowBillable = !(policy?.disabledFields?.defaultBillable ?? true); - - const hasRoute = TransactionUtils.hasRoute(transaction); - const isDistanceRequestWithPendingRoute = isDistanceRequest && (!hasRoute || !rate); - const formattedAmount = isDistanceRequestWithPendingRoute - ? '' - : CurrencyUtils.convertToDisplayString( - shouldCalculateDistanceAmount ? DistanceRequestUtils.getDistanceRequestAmount(distance, unit, rate ?? 0) : iouAmount, - isDistanceRequest ? currency : iouCurrencyCode, - ); - const formattedTaxAmount = CurrencyUtils.convertToDisplayString(transaction?.taxAmount, iouCurrencyCode); - - const defaultTaxKey = taxRates?.defaultExternalID; - const defaultTaxName = (defaultTaxKey && `${taxRates.taxes[defaultTaxKey].name} (${taxRates.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) ?? ''; - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- nullish coalescing is not working when a left hand side value is '' - const taxRateTitle = transaction?.taxRate?.text || defaultTaxName; - - const isFocused = useIsFocused(); - const [formError, setFormError] = useState(''); - - const [didConfirm, setDidConfirm] = useState(false); - const [didConfirmSplit, setDidConfirmSplit] = useState(false); - - const shouldDisplayFieldError: boolean = useMemo(() => { - if (!isEditingSplitBill) { - return false; - } - - return (!!hasSmartScanFailed && TransactionUtils.hasMissingSmartscanFields(transaction)) || (didConfirmSplit && TransactionUtils.areRequiredFieldsEmpty(transaction)); - }, [isEditingSplitBill, hasSmartScanFailed, transaction, didConfirmSplit]); - - const isMerchantEmpty = !iouMerchant || iouMerchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT; - const shouldDisplayMerchantError = isPolicyExpenseChat && shouldDisplayFieldError && isMerchantEmpty; - - useEffect(() => { - if (shouldDisplayFieldError && didConfirmSplit) { - setFormError('iou.error.genericSmartscanFailureMessage'); - return; - } - if (shouldDisplayFieldError && hasSmartScanFailed) { - setFormError('iou.receiptScanningFailed'); - return; - } - // reset the form error whenever the screen gains or loses focus - setFormError(''); - }, [isFocused, transaction, shouldDisplayFieldError, hasSmartScanFailed, didConfirmSplit]); - - useEffect(() => { - if (!shouldCalculateDistanceAmount) { - return; - } - - const amount = DistanceRequestUtils.getDistanceRequestAmount(distance, unit, rate ?? 0); - IOU.setMoneyRequestAmount(amount); - }, [shouldCalculateDistanceAmount, distance, rate, unit]); - - /** - * Returns the participants with amount - */ - const getParticipantsWithAmount = useCallback( - (participantsList: Array): Array => { - const calculatedIouAmount = IOUUtils.calculateAmount(participantsList.length, iouAmount, iouCurrencyCode ?? ''); - return OptionsListUtils.getIOUConfirmationOptionsFromParticipants( - participantsList, - iouAmount > 0 ? CurrencyUtils.convertToDisplayString(calculatedIouAmount, iouCurrencyCode) : '', - ); - }, - [iouAmount, iouCurrencyCode], - ); - - // If completing a split bill fails, set didConfirm to false to allow the user to edit the fields again - if (isEditingSplitBill && didConfirm) { - setDidConfirm(false); - } - - const splitOrRequestOptions: Array> = useMemo(() => { - let text; - if (isSplitBill && iouAmount === 0) { - text = translate('iou.split'); - } else if ((!!receiptPath && isTypeRequest) || isDistanceRequestWithPendingRoute) { - text = translate('iou.request'); - if (iouAmount !== 0) { - text = translate('iou.requestAmount', {amount: formattedAmount}); - } - } else { - const translationKey = isSplitBill ? 'iou.splitAmount' : 'iou.requestAmount'; - text = translate(translationKey, {amount: formattedAmount}); - } - return [ - { - text: text[0].toUpperCase() + text.slice(1), - value: iouType, - }, - ]; - }, [isSplitBill, isTypeRequest, iouType, iouAmount, receiptPath, formattedAmount, isDistanceRequestWithPendingRoute, translate]); - - const selectedParticipants: Array = useMemo( - () => selectedParticipantsProp.filter((participant) => participant.selected), - [selectedParticipantsProp], - ); - const payeePersonalDetails = useMemo(() => payeePersonalDetailsProp ?? currentUserPersonalDetails, [payeePersonalDetailsProp, currentUserPersonalDetails]); - const canModifyParticipants = !isReadOnly && canModifyParticipantsProp && hasMultipleParticipants; - const shouldDisablePaidBySection = canModifyParticipants; - - const optionSelectorSections: OptionsListUtils.CategorySection[] = useMemo(() => { - const sections = []; - const unselectedParticipants = selectedParticipantsProp.filter((participant) => !participant.selected); - if (hasMultipleParticipants) { - const formattedSelectedParticipants = getParticipantsWithAmount(selectedParticipants); - let formattedParticipantsList = [...new Set([...formattedSelectedParticipants, ...unselectedParticipants])]; - - if (!canModifyParticipants) { - formattedParticipantsList = formattedParticipantsList.map((participant) => ({ - ...participant, - isDisabled: ReportUtils.isOptimisticPersonalDetail(participant.accountID ?? -1), - })); - } - - const myIOUAmount = IOUUtils.calculateAmount(selectedParticipants.length, iouAmount, iouCurrencyCode ?? '', true); - const formattedPayeeOption = OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail( - payeePersonalDetails, - iouAmount > 0 ? CurrencyUtils.convertToDisplayString(myIOUAmount, iouCurrencyCode) : '', - ); - - sections.push( - { - title: translate('moneyRequestConfirmationList.paidBy'), - data: [formattedPayeeOption], - shouldShow: true, - isDisabled: shouldDisablePaidBySection, - }, - { - title: translate('moneyRequestConfirmationList.splitWith'), - data: formattedParticipantsList, - shouldShow: true, - }, - ); - } else { - const formattedSelectedParticipants = selectedParticipantsProp.map((participant) => ({ - ...participant, - isDisabled: ReportUtils.isOptimisticPersonalDetail(participant.accountID ?? -1), - })); - sections.push({ - title: translate('common.to'), - data: formattedSelectedParticipants, - shouldShow: true, - }); - } - return sections; - }, [ - selectedParticipants, - hasMultipleParticipants, - iouAmount, - iouCurrencyCode, - getParticipantsWithAmount, - selectedParticipantsProp, - payeePersonalDetails, - translate, - shouldDisablePaidBySection, - canModifyParticipants, - ]); - - const selectedOptions: Array = useMemo(() => { - if (!hasMultipleParticipants) { - return []; - } - return [...selectedParticipants, OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail(payeePersonalDetails)]; - }, [selectedParticipants, hasMultipleParticipants, payeePersonalDetails]); - - useEffect(() => { - if (!isDistanceRequest) { - return; - } - - /* - Set pending waypoints based on the route status. We should handle this dynamically to cover cases such as: - When the user completes the initial steps of the IOU flow offline and then goes online on the confirmation page. - In this scenario, the route will be fetched from the server, and the waypoints will no longer be pending. - */ - IOU.setMoneyRequestPendingFields(transactionID, {waypoints: isDistanceRequestWithPendingRoute ? CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD : null}); - - const distanceMerchant = DistanceRequestUtils.getDistanceMerchant(hasRoute, distance, unit, rate ?? 0, currency ?? CONST.CURRENCY.USD, translate, toLocaleDigit); - IOU.setMoneyRequestMerchant(transactionID, distanceMerchant, false); - }, [isDistanceRequestWithPendingRoute, hasRoute, distance, unit, rate, currency, translate, toLocaleDigit, isDistanceRequest, transactionID]); - - const selectParticipant = useCallback( - (option: Participant) => { - // Return early if selected option is currently logged in user. - if (option.accountID === session?.accountID) { - return; - } - onSelectParticipant?.(option); - }, - [session?.accountID, onSelectParticipant], - ); - - /** - * Navigate to report details or profile of selected user - */ - const navigateToReportOrUserDetail = (option: ReportUtils.OptionData) => { - if (option.accountID) { - const activeRoute = Navigation.getActiveRouteWithoutParams(); - - Navigation.navigate(ROUTES.PROFILE.getRoute(option.accountID, activeRoute)); - } else if (option.reportID) { - Navigation.navigate(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(option.reportID)); - } - }; - - const confirm = useCallback( - (paymentMethod: IouType | PaymentMethodType | undefined) => { - if (!selectedParticipants.length) { - return; - } - if (iouCategory.length > CONST.API_TRANSACTION_CATEGORY_MAX_LENGTH) { - setFormError('iou.error.invalidCategoryLength'); - return; - } - if (iouType === CONST.IOU.TYPE.SEND) { - if (!paymentMethod) { - return; - } - - setDidConfirm(true); - - Log.info(`[IOU] Sending money via: ${paymentMethod}`); - onSendMoney?.(paymentMethod); - } else { - // validate the amount for distance requests - const decimals = CurrencyUtils.getCurrencyDecimals(iouCurrencyCode); - if (isDistanceRequest && !isDistanceRequestWithPendingRoute && !MoneyRequestUtils.validateAmount(String(iouAmount), decimals)) { - setFormError('common.error.invalidAmount'); - return; - } - - if (isEditingSplitBill && TransactionUtils.areRequiredFieldsEmpty(transaction)) { - setDidConfirmSplit(true); - return; - } - - setDidConfirm(true); - onConfirm?.(selectedParticipants); - } - }, - [ - selectedParticipants, - onSendMoney, - onConfirm, - isEditingSplitBill, - iouType, - isDistanceRequest, - iouCategory, - isDistanceRequestWithPendingRoute, - iouCurrencyCode, - iouAmount, - transaction, - ], - ); - - const footerContent = useMemo(() => { - if (isReadOnly) { - return; - } - - const shouldShowSettlementButton = iouType === CONST.IOU.TYPE.SEND; - const shouldDisableButton = selectedParticipants.length === 0; - - const button = shouldShowSettlementButton ? ( - - ) : ( - confirm(value)} - options={splitOrRequestOptions} - buttonSize={CONST.DROPDOWN_BUTTON_SIZE.LARGE} - enterKeyEventListenerPriority={1} - /> - ); - return ( - <> - {!!formError.length && ( - - )} - {button} - - ); - }, [isReadOnly, iouType, bankAccountRoute, iouCurrencyCode, policyID, selectedParticipants.length, confirm, splitOrRequestOptions, formError, styles.ph1, styles.mb2]); - - const { - image: receiptImage, - thumbnail: receiptThumbnail, - isThumbnail, - fileExtension, - } = receiptPath && receiptFilename ? ReceiptUtils.getThumbnailAndImageURIs(transaction, receiptPath, receiptFilename) : ({} as ReceiptUtils.ThumbnailAndImageURI); - return ( - // @ts-expect-error This component is deprecated and will not be migrated to TypeScript (context: https://expensify.slack.com/archives/C01GTK53T8Q/p1709232289899589?thread_ts=1709156803.359359&cid=C01GTK53T8Q) - - {isDistanceRequest && ( - - - - )} - {/* eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing */} - {receiptImage || receiptThumbnail ? ( - - ) : ( - // The empty receipt component should only show for IOU Requests of a paid policy ("Team" or "Corporate") - PolicyUtils.isPaidGroupPolicy(policy) && - !isDistanceRequest && - iouType === CONST.IOU.TYPE.REQUEST && ( - - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute( - CONST.IOU.ACTION.CREATE, - iouType, - transaction?.transactionID ?? '', - reportID, - Navigation.getActiveRouteWithoutParams(), - ), - ) - } - /> - ) - )} - {shouldShowSmartScanFields && ( - { - if (isDistanceRequest) { - return; - } - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_AMOUNT.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction?.transactionID ?? '', reportID, Navigation.getActiveRouteWithoutParams()), - ); - }} - style={[styles.moneyRequestMenuItem, styles.mt2]} - titleStyle={styles.moneyRequestConfirmationAmount} - disabled={didConfirm} - brickRoadIndicator={shouldDisplayFieldError && TransactionUtils.isAmountMissing(transaction) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} - error={shouldDisplayFieldError && TransactionUtils.isAmountMissing(transaction) ? translate('common.error.enterAmount') : ''} - /> - )} - { - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_DESCRIPTION.getRoute( - CONST.IOU.ACTION.EDIT, - iouType, - transaction?.transactionID ?? '', - reportID, - Navigation.getActiveRouteWithoutParams(), - reportActionID, - ), - ); - }} - style={styles.moneyRequestMenuItem} - titleStyle={styles.flex1} - disabled={didConfirm} - interactive={!isReadOnly} - numberOfLinesTitle={2} - /> - {!shouldShowAllFields && ( - - )} - {shouldShowAllFields && ( - <> - {shouldShowDate && ( - { - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_DATE.getRoute( - CONST.IOU.ACTION.EDIT, - iouType, - transaction?.transactionID ?? '', - reportID, - Navigation.getActiveRouteWithoutParams(), - ), - ); - }} - disabled={didConfirm} - interactive={!isReadOnly} - brickRoadIndicator={shouldDisplayFieldError && TransactionUtils.isCreatedMissing(transaction) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} - error={shouldDisplayFieldError && TransactionUtils.isCreatedMissing(transaction) ? translate('common.error.enterDate') : ''} - /> - )} - {isDistanceRequest && ( - - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute( - CONST.IOU.ACTION.EDIT, - iouType, - transaction?.transactionID ?? '', - reportID, - Navigation.getActiveRouteWithoutParams(), - ), - ) - } - disabled={didConfirm} - interactive={!isReadOnly} - /> - )} - {shouldShowMerchant && ( - { - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_MERCHANT.getRoute( - CONST.IOU.ACTION.EDIT, - iouType, - transaction?.transactionID ?? '', - reportID, - Navigation.getActiveRouteWithoutParams(), - ), - ); - }} - disabled={didConfirm} - interactive={!isReadOnly} - brickRoadIndicator={shouldDisplayMerchantError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} - error={shouldDisplayMerchantError ? translate('common.error.enterMerchant') : ''} - /> - )} - {shouldShowCategories && ( - { - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute( - CONST.IOU.ACTION.EDIT, - iouType, - transaction?.transactionID ?? '', - reportID, - Navigation.getActiveRouteWithoutParams(), - reportActionID, - ), - ); - }} - style={styles.moneyRequestMenuItem} - titleStyle={styles.flex1} - disabled={didConfirm} - interactive={!isReadOnly} - rightLabel={canUseViolations && !!policy?.requiresCategory ? translate('common.required') : ''} - /> - )} - {shouldShowTags && - policyTagLists.map(({name}, index) => ( - { - if (!isEditingSplitBill) { - return; - } - - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_TAG.getRoute( - CONST.IOU.ACTION.EDIT, - CONST.IOU.TYPE.SPLIT, - index, - transaction?.transactionID ?? '', - reportID, - Navigation.getActiveRouteWithoutParams(), - reportActionID, - ), - ); - }} - style={styles.moneyRequestMenuItem} - disabled={didConfirm} - interactive={!isReadOnly} - rightLabel={canUseViolations && !!policy?.requiresTag ? translate('common.required') : ''} - /> - ))} - - {shouldShowTax && ( - - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute( - CONST.IOU.ACTION.CREATE, - iouType, - transaction?.transactionID ?? '', - reportID, - Navigation.getActiveRouteWithoutParams(), - ), - ) - } - disabled={didConfirm} - interactive={!isReadOnly} - /> - )} - - {shouldShowTax && ( - - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute( - CONST.IOU.ACTION.CREATE, - iouType, - transaction?.transactionID ?? '', - reportID, - Navigation.getActiveRouteWithoutParams(), - ), - ) - } - disabled={didConfirm} - interactive={!isReadOnly} - /> - )} - - {shouldShowBillable && ( - - {translate('common.billable')} - onToggleBillable?.(isOn)} - /> - - )} - - )} - - ); -} - -MoneyRequestConfirmationList.displayName = 'MoneyRequestConfirmationList'; - -export default withOnyx({ - session: { - key: ONYXKEYS.SESSION, - }, - policyCategories: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`, - }, - policyTags: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, - }, - mileageRate: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - selector: DistanceRequestUtils.getDefaultMileageRate, - }, - policy: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - }, - iou: { - key: ONYXKEYS.IOU, - }, -})(MoneyRequestConfirmationList); From 032f118290ad6bba28882f408ff0eed6bf3b631d Mon Sep 17 00:00:00 2001 From: brunovjk Date: Fri, 12 Apr 2024 10:45:03 -0300 Subject: [PATCH 03/24] Rename 'MoneyTemporaryForRefactorRequestConfirmationList' and in all its uses --- ...onfirmationList.tsx => MoneyRequestConfirmationList.tsx} | 6 +++--- src/pages/iou/SplitBillDetailsPage.tsx | 2 +- src/pages/iou/request/step/IOURequestStepConfirmation.tsx | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename src/components/{MoneyTemporaryForRefactorRequestConfirmationList.tsx => MoneyRequestConfirmationList.tsx} (99%) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx similarity index 99% rename from src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx rename to src/components/MoneyRequestConfirmationList.tsx index 6a63dcc9ff7d..6e0de099b847 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -168,7 +168,7 @@ const getTaxAmount = (transaction: OnyxEntry, defaultTaxV return TransactionUtils.calculateTaxAmount(percentage, transaction?.amount ?? 0); }; -function MoneyTemporaryForRefactorRequestConfirmationList({ +function MoneyRequestConfirmationList({ transaction = null, onSendMoney, onConfirm, @@ -1034,7 +1034,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ ); } -MoneyTemporaryForRefactorRequestConfirmationList.displayName = 'MoneyTemporaryForRefactorRequestConfirmationList'; +MoneyRequestConfirmationList.displayName = 'MoneyRequestConfirmationList'; export default withOnyx({ session: { @@ -1053,4 +1053,4 @@ export default withOnyx `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, }, -})(MoneyTemporaryForRefactorRequestConfirmationList); +})(MoneyRequestConfirmationList); diff --git a/src/pages/iou/SplitBillDetailsPage.tsx b/src/pages/iou/SplitBillDetailsPage.tsx index fca3b713dec8..c500c4a8175f 100644 --- a/src/pages/iou/SplitBillDetailsPage.tsx +++ b/src/pages/iou/SplitBillDetailsPage.tsx @@ -5,7 +5,7 @@ import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import MoneyRequestConfirmationList from '@components/MoneyTemporaryForRefactorRequestConfirmationList'; +import MoneyRequestConfirmationList from '@components/MoneyRequestConfirmationList'; import MoneyRequestHeaderStatusBar from '@components/MoneyRequestHeaderStatusBar'; import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 83f831708799..c45e05fb5ed3 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -5,7 +5,7 @@ import {withOnyx} from 'react-native-onyx'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import * as Expensicons from '@components/Icon/Expensicons'; -import MoneyRequestConfirmationList from '@components/MoneyTemporaryForRefactorRequestConfirmationList'; +import MoneyRequestConfirmationList from '@components/MoneyRequestConfirmationList'; import {usePersonalDetails} from '@components/OnyxProvider'; import ScreenWrapper from '@components/ScreenWrapper'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; From fc00866d54a65ba7496d1e799d18ecbfa91e2cdc Mon Sep 17 00:00:00 2001 From: brunovjk Date: Sat, 13 Apr 2024 08:59:20 -0300 Subject: [PATCH 04/24] fix lint --- src/components/MoneyRequestConfirmationList.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 8d2f878244bd..6e0de099b847 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -260,10 +260,7 @@ function MoneyRequestConfirmationList({ const formattedTaxAmount = CurrencyUtils.convertToDisplayString(transaction?.taxAmount, iouCurrencyCode); const taxRateTitle = taxRates && transaction ? TransactionUtils.getDefaultTaxName(taxRates, transaction) : ''; - const defaultTaxKey = taxRates?.defaultExternalID; - const defaultTaxName = (defaultTaxKey && `${taxRates.taxes[defaultTaxKey].name} (${taxRates.taxes[defaultTaxKey].value}) ${CONST.DOT_SEPARATOR} ${translate('common.default')}`) ?? ''; - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- nullish coalescing is not working when a left hand side value is '' - const taxRateTitle = transaction?.taxRate?.text || defaultTaxName; + const previousTransactionAmount = usePrevious(transaction?.amount); const isFocused = useIsFocused(); const [formError, setFormError] = useState(''); From 387586a94744bee03b55715c85518535e492e494 Mon Sep 17 00:00:00 2001 From: brunovjk Date: Mon, 15 Apr 2024 08:32:04 -0300 Subject: [PATCH 05/24] Add validation error for category --- src/components/MoneyRequestConfirmationList.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 6e0de099b847..ef266ffc9de5 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -535,6 +535,10 @@ function MoneyRequestConfirmationList({ setMerchantError(true); return; } + if (iouCategory.length > CONST.API_TRANSACTION_CATEGORY_MAX_LENGTH) { + setFormError('iou.error.invalidCategoryLength'); + return; + } if (iouType === CONST.IOU.TYPE.SEND) { if (!paymentMethod) { From 4e8fef9514f8bd16466f3fbbf1a79d6c8e176c54 Mon Sep 17 00:00:00 2001 From: brunovjk Date: Mon, 15 Apr 2024 08:46:33 -0300 Subject: [PATCH 06/24] reuse ShowMoreButton --- .../MoneyRequestConfirmationList.tsx | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index ef266ffc9de5..2ccfeb0bc16e 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -35,13 +35,11 @@ import type {Route} from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/IOU'; import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; -import Button from './Button'; import ButtonWithDropdownMenu from './ButtonWithDropdownMenu'; import type {DropdownOption} from './ButtonWithDropdownMenu/types'; import ConfirmedRoute from './ConfirmedRoute'; import ConfirmModal from './ConfirmModal'; import FormHelpMessage from './FormHelpMessage'; -import * as Expensicons from './Icon/Expensicons'; import MenuItemWithTopDescription from './MenuItemWithTopDescription'; import OptionsSelector from './OptionsSelector'; import PDFThumbnail from './PDFThumbnail'; @@ -50,6 +48,7 @@ import ReceiptImage from './ReceiptImage'; import SettlementButton from './SettlementButton'; import Switch from './Switch'; import Text from './Text'; +import ShowMoreButton from './ShowMoreButton'; type MoneyRequestConfirmationListOnyxProps = { /** Collection of categories attached to a policy */ @@ -1010,19 +1009,10 @@ function MoneyRequestConfirmationList({ } {primaryFields} {!shouldShowAllFields && ( - - -