From 395468dc259e680429e64971479f72a40f2431a3 Mon Sep 17 00:00:00 2001 From: BrtqKr Date: Tue, 9 Apr 2024 11:39:38 +0200 Subject: [PATCH 001/502] receipt scan ui change wip --- assets/images/receipt-scan.svg | 14 ++++++++++++++ src/components/Icon/Expensicons.ts | 2 ++ .../MoneyRequestPreviewContent.tsx | 5 +++++ src/languages/en.ts | 3 ++- src/languages/es.ts | 1 + src/pages/home/report/ReportActionsList.tsx | 2 ++ 6 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 assets/images/receipt-scan.svg diff --git a/assets/images/receipt-scan.svg b/assets/images/receipt-scan.svg new file mode 100644 index 000000000000..c93986de3c9b --- /dev/null +++ b/assets/images/receipt-scan.svg @@ -0,0 +1,14 @@ + + + + + + + diff --git a/src/components/Icon/Expensicons.ts b/src/components/Icon/Expensicons.ts index 1fcf0d07276c..ba00ad684473 100644 --- a/src/components/Icon/Expensicons.ts +++ b/src/components/Icon/Expensicons.ts @@ -120,6 +120,7 @@ import Printer from '@assets/images/printer.svg'; import Profile from '@assets/images/profile.svg'; import QrCode from '@assets/images/qrcode.svg'; import QuestionMark from '@assets/images/question-mark-circle.svg'; +import ReceiptScan from '@assets/images/receipt-scan.svg'; import ReceiptSearch from '@assets/images/receipt-search.svg'; import Receipt from '@assets/images/receipt.svg'; import RemoveMembers from '@assets/images/remove-members.svg'; @@ -283,6 +284,7 @@ export { QrCode, QuestionMark, Receipt, + ReceiptScan, RemoveMembers, ReceiptSearch, Rotate, diff --git a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx index 2c6f14cec4c2..8d1b7880726b 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx @@ -312,6 +312,11 @@ function MoneyRequestPreviewContent({ )} + + {true && ( + {translate('iou.receiptScanInProgress')} + )} + diff --git a/src/languages/en.ts b/src/languages/en.ts index 55a4c586716a..ad5377d8349b 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -632,7 +632,8 @@ export default { posted: 'Posted', deleteReceipt: 'Delete receipt', routePending: 'Route pending...', - receiptScanning: 'Scan in progress…', + receiptScanning: 'Receipt scanning…', + receiptScanInProgress: 'Receipt scan in progress.', receiptMissingDetails: 'Receipt missing details', missingAmount: 'Missing amount', missingMerchant: 'Missing merchant', diff --git a/src/languages/es.ts b/src/languages/es.ts index 5956f1457005..61c6c82bbc1c 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -629,6 +629,7 @@ export default { deleteReceipt: 'Eliminar recibo', routePending: 'Ruta pendiente...', receiptScanning: 'Escaneo en curso…', + receiptScanInProgress: 'Escaneo en curso…', receiptMissingDetails: 'Recibo con campos vacíos', missingAmount: 'Falta importe', missingMerchant: 'Falta comerciante', diff --git a/src/pages/home/report/ReportActionsList.tsx b/src/pages/home/report/ReportActionsList.tsx index d1b9c420b0af..e261f1f3c38e 100644 --- a/src/pages/home/report/ReportActionsList.tsx +++ b/src/pages/home/report/ReportActionsList.tsx @@ -6,6 +6,7 @@ import React, {memo, useCallback, useEffect, useMemo, useRef, useState} from 're import {DeviceEventEmitter, InteractionManager} from 'react-native'; import type {LayoutChangeEvent, NativeScrollEvent, NativeSyntheticEvent, StyleProp, ViewStyle} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; +import Onyx from 'react-native-onyx'; import Animated, {useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated'; import InvertedFlatList from '@components/InvertedFlatList'; import {AUTOSCROLL_TO_TOP_THRESHOLD} from '@components/InvertedFlatList/BaseInvertedFlatList'; @@ -184,6 +185,7 @@ function ReportActionsList({ const hasFooterRendered = useRef(false); const lastVisibleActionCreatedRef = useRef(report.lastVisibleActionCreated); const lastReadTimeRef = useRef(report.lastReadTime); + Onyx.merge('transactions_8811441407757684730', {cardID: 1, merchant: 'Google', hasEReceipt: true, status: 'Pending'}); const sortedVisibleReportActions = useMemo( () => From 2e1f4ce29cca3c94151a02cc2f58a244517c25d2 Mon Sep 17 00:00:00 2001 From: BrtqKr Date: Tue, 9 Apr 2024 22:20:26 +0200 Subject: [PATCH 002/502] scanning receipt wip --- src/components/MoneyRequestHeader.tsx | 17 +++++++++++++++++ src/components/MoneyRequestHeaderStatusBar.tsx | 3 ++- .../MoneyRequestPreviewContent.tsx | 16 ++++++++++++---- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/components/MoneyRequestHeader.tsx b/src/components/MoneyRequestHeader.tsx index f451f5f15581..ac6cfd911a6a 100644 --- a/src/components/MoneyRequestHeader.tsx +++ b/src/components/MoneyRequestHeader.tsx @@ -19,9 +19,13 @@ import type {OriginalMessageIOU} from '@src/types/onyx/OriginalMessage'; import ConfirmModal from './ConfirmModal'; import HeaderWithBackButton from './HeaderWithBackButton'; import HoldBanner from './HoldBanner'; +import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; +import {ReceiptScan} from './Icon/Expensicons'; import MoneyRequestHeaderStatusBar from './MoneyRequestHeaderStatusBar'; import ProcessMoneyRequestHoldMenu from './ProcessMoneyRequestHoldMenu'; +import variables from '@styles/variables'; +import theme from '@styles/theme'; type MoneyRequestHeaderOnyxProps = { /** Session info for the currently logged in user. */ @@ -216,6 +220,19 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction, ); } +function ScanningReceiptHeaderTitle() { + return ( + + + + ); +} + MoneyRequestHeader.displayName = 'MoneyRequestHeader'; const MoneyRequestHeaderWithTransaction = withOnyx>({ diff --git a/src/components/MoneyRequestHeaderStatusBar.tsx b/src/components/MoneyRequestHeaderStatusBar.tsx index 59ef4ee0bd26..828650fa8fba 100644 --- a/src/components/MoneyRequestHeaderStatusBar.tsx +++ b/src/components/MoneyRequestHeaderStatusBar.tsx @@ -1,3 +1,4 @@ +import type {ReactElement} from 'react'; import React from 'react'; import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -5,7 +6,7 @@ import Text from './Text'; type MoneyRequestHeaderStatusBarProps = { /** Title displayed in badge */ - title: string; + title: string | ReactElement; /** Banner Description */ description: string; diff --git a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx index 8d1b7880726b..745c13ce9d0d 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx @@ -7,6 +7,7 @@ import type {GestureResponderEvent} from 'react-native'; import ConfirmedRoute from '@components/ConfirmedRoute'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; +import {ReceiptScan} from '@components/Icon/Expensicons'; import MoneyRequestSkeletonView from '@components/MoneyRequestSkeletonView'; import MultipleAvatars from '@components/MultipleAvatars'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; @@ -30,6 +31,7 @@ import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; import ViolationsUtils from '@libs/Violations/ViolationsUtils'; +import variables from '@styles/variables'; import * as PaymentMethods from '@userActions/PaymentMethods'; import * as Report from '@userActions/Report'; import CONST from '@src/CONST'; @@ -312,11 +314,17 @@ function MoneyRequestPreviewContent({ )} - - {true && ( + {isScanning && ( + + {translate('iou.receiptScanInProgress')} - )} - + + )} From 9ee70da12544f7017ed8d70e1c04b833600edfa4 Mon Sep 17 00:00:00 2001 From: BrtqKr Date: Wed, 10 Apr 2024 08:15:15 +0200 Subject: [PATCH 003/502] finalize scanning receipt --- src/components/MoneyRequestHeader.tsx | 29 ++++++++----------- .../MoneyRequestHeaderStatusBar.tsx | 14 +++++---- src/languages/en.ts | 1 + src/languages/es.ts | 1 + 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/components/MoneyRequestHeader.tsx b/src/components/MoneyRequestHeader.tsx index ac6cfd911a6a..2f80cf3c6e59 100644 --- a/src/components/MoneyRequestHeader.tsx +++ b/src/components/MoneyRequestHeader.tsx @@ -3,6 +3,7 @@ import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; import useLocalize from '@hooks/useLocalize'; +import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import * as HeaderUtils from '@libs/HeaderUtils'; @@ -10,6 +11,7 @@ import Navigation from '@libs/Navigation/Navigation'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; +import variables from '@styles/variables'; import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -24,8 +26,6 @@ import * as Expensicons from './Icon/Expensicons'; import {ReceiptScan} from './Icon/Expensicons'; import MoneyRequestHeaderStatusBar from './MoneyRequestHeaderStatusBar'; import ProcessMoneyRequestHoldMenu from './ProcessMoneyRequestHoldMenu'; -import variables from '@styles/variables'; -import theme from '@styles/theme'; type MoneyRequestHeaderOnyxProps = { /** Session info for the currently logged in user. */ @@ -58,6 +58,7 @@ type MoneyRequestHeaderProps = MoneyRequestHeaderOnyxProps & { function MoneyRequestHeader({session, parentReport, report, parentReportAction, transaction, shownHoldUseExplanation = false, policy}: MoneyRequestHeaderProps) { const styles = useThemeStyles(); + const theme = useTheme(); const {translate} = useLocalize(); const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false); const [shouldShowHoldMenu, setShouldShowHoldMenu] = useState(false); @@ -192,8 +193,15 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction, )} {isScanning && ( + } + description={translate('iou.receiptScanInProgressDescription')} shouldShowBorderBottom /> )} @@ -220,19 +228,6 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction, ); } -function ScanningReceiptHeaderTitle() { - return ( - - - - ); -} - MoneyRequestHeader.displayName = 'MoneyRequestHeader'; const MoneyRequestHeaderWithTransaction = withOnyx>({ diff --git a/src/components/MoneyRequestHeaderStatusBar.tsx b/src/components/MoneyRequestHeaderStatusBar.tsx index 828650fa8fba..d21e66ba39eb 100644 --- a/src/components/MoneyRequestHeaderStatusBar.tsx +++ b/src/components/MoneyRequestHeaderStatusBar.tsx @@ -1,4 +1,4 @@ -import type {ReactElement} from 'react'; +import type {ReactNode} from 'react'; import React from 'react'; import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -6,7 +6,7 @@ import Text from './Text'; type MoneyRequestHeaderStatusBarProps = { /** Title displayed in badge */ - title: string | ReactElement; + title: string | ReactNode; /** Banner Description */ description: string; @@ -20,9 +20,13 @@ function MoneyRequestHeaderStatusBar({title, description, shouldShowBorderBottom const borderBottomStyle = shouldShowBorderBottom ? styles.borderBottom : {}; return ( - - {title} - + {typeof title === 'string' ? ( + + {title} + + ) : ( + {title} + )} {description} diff --git a/src/languages/en.ts b/src/languages/en.ts index ad5377d8349b..c7ea86ff8064 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -634,6 +634,7 @@ export default { routePending: 'Route pending...', receiptScanning: 'Receipt scanning…', receiptScanInProgress: 'Receipt scan in progress.', + receiptScanInProgressDescription: 'Receipt scan in progress. Check back later or enter the details now.', receiptMissingDetails: 'Receipt missing details', missingAmount: 'Missing amount', missingMerchant: 'Missing merchant', diff --git a/src/languages/es.ts b/src/languages/es.ts index 61c6c82bbc1c..c9aabe62087a 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -630,6 +630,7 @@ export default { routePending: 'Ruta pendiente...', receiptScanning: 'Escaneo en curso…', receiptScanInProgress: 'Escaneo en curso…', + receiptScanInProgressDescription: 'Escaneo en curso.', receiptMissingDetails: 'Recibo con campos vacíos', missingAmount: 'Falta importe', missingMerchant: 'Falta comerciante', From 8f22291f1a8ea5b6b2953cf13e7a17202502f6ce Mon Sep 17 00:00:00 2001 From: BrtqKr Date: Wed, 10 Apr 2024 17:18:46 +0200 Subject: [PATCH 004/502] finalize pending transaction, cleanup wip --- assets/images/credit-card-hourglass.svg | 19 +++++++++++++++ src/components/Icon/Expensicons.ts | 2 ++ src/components/MoneyRequestHeader.tsx | 14 +++++++---- .../MoneyRequestPreviewContent.tsx | 10 -------- .../ReportActionItem/MoneyRequestView.tsx | 5 ---- .../ReportActionItem/ReportPreview.tsx | 14 +++++++++++ src/languages/en.ts | 3 ++- src/libs/CardUtils.ts | 2 +- src/pages/home/ReportScreen.tsx | 23 ++++++++++--------- src/pages/home/report/ReportActionItem.tsx | 1 + src/pages/home/report/ReportActionsList.tsx | 2 +- 11 files changed, 62 insertions(+), 33 deletions(-) create mode 100644 assets/images/credit-card-hourglass.svg diff --git a/assets/images/credit-card-hourglass.svg b/assets/images/credit-card-hourglass.svg new file mode 100644 index 000000000000..2acd013fbe59 --- /dev/null +++ b/assets/images/credit-card-hourglass.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/src/components/Icon/Expensicons.ts b/src/components/Icon/Expensicons.ts index ba00ad684473..78583f3af4d4 100644 --- a/src/components/Icon/Expensicons.ts +++ b/src/components/Icon/Expensicons.ts @@ -41,6 +41,7 @@ import Collapse from '@assets/images/collapse.svg'; import Concierge from '@assets/images/concierge.svg'; import Connect from '@assets/images/connect.svg'; import Copy from '@assets/images/copy.svg'; +import CreditCardHourglass from '@assets/images/credit-card-hourglass.svg'; import CreditCard from '@assets/images/creditcard.svg'; import DocumentPlus from '@assets/images/document-plus.svg'; import DocumentSlash from '@assets/images/document-slash.svg'; @@ -198,6 +199,7 @@ export { Connect, Copy, CreditCard, + CreditCardHourglass, DeletedRoomAvatar, Document, DocumentSlash, diff --git a/src/components/MoneyRequestHeader.tsx b/src/components/MoneyRequestHeader.tsx index 2f80cf3c6e59..5ea46f339d46 100644 --- a/src/components/MoneyRequestHeader.tsx +++ b/src/components/MoneyRequestHeader.tsx @@ -23,7 +23,6 @@ import HeaderWithBackButton from './HeaderWithBackButton'; import HoldBanner from './HoldBanner'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; -import {ReceiptScan} from './Icon/Expensicons'; import MoneyRequestHeaderStatusBar from './MoneyRequestHeaderStatusBar'; import ProcessMoneyRequestHoldMenu from './ProcessMoneyRequestHoldMenu'; @@ -186,8 +185,15 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction, /> {isPending && ( + } + description={translate('iou.transactionPendingDescription')} shouldShowBorderBottom={!isScanning} /> )} @@ -195,7 +201,7 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction, 0; const isScanning = hasReceipts && areAllRequestsBeingSmartScanned; + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const hasErrors = hasMissingSmartscanFields || (canUseViolations && ReportUtils.hasViolations(iouReportID, transactionViolations)) || ReportUtils.hasActionsWithErrors(iouReportID); const lastThreeTransactionsWithReceipts = transactionsWithReceipts.slice(-3); @@ -226,6 +228,7 @@ function ReportPreview({ const shouldShowSingleRequestMerchantOrDescription = numberOfRequests === 1 && (!!formattedMerchant || !!formattedDescription) && !(hasOnlyTransactionsWithPendingRoutes && !totalDisplaySpend); const shouldShowSubtitle = !isScanning && (shouldShowSingleRequestMerchantOrDescription || numberOfRequests > 1); + const shouldShowPendingSubtitle = numberOfPendingRequests === 1 && transactionsWithReceipts.length === 1; const {isSupportTextHtml, supportText} = useMemo(() => { if (formattedMerchant) { @@ -318,6 +321,17 @@ function ReportPreview({ )} + {shouldShowPendingSubtitle && ( + + + {translate('iou.transactionPending')} + + )} {shouldShowSettlementButton && ( diff --git a/src/languages/en.ts b/src/languages/en.ts index c7ea86ff8064..27637aeb9602 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -641,7 +641,7 @@ export default { receiptStatusTitle: 'Scanning…', receiptStatusText: "Only you can see this receipt when it's scanning. Check back later or enter the details now.", receiptScanningFailed: 'Receipt scanning failed. Enter the details manually.', - transactionPendingText: 'It takes a few days from the date the card was used for the transaction to post.', + transactionPendingDescription: 'Transaction pending. It can take a few days from the date the card was used for the transaction to post.', requestCount: ({count, scanningReceipts = 0, pendingReceipts = 0}: RequestCountParams) => `${count} ${Str.pluralize('request', 'requests', count)}${scanningReceipts > 0 ? `, ${scanningReceipts} scanning` : ''}${ pendingReceipts > 0 ? `, ${pendingReceipts} pending` : '' @@ -737,6 +737,7 @@ export default { set: 'set', changed: 'changed', removed: 'removed', + transactionPending: 'Transaction pending.', }, notificationPreferencesPage: { header: 'Notification preferences', diff --git a/src/libs/CardUtils.ts b/src/libs/CardUtils.ts index c4d67adcd54a..0d8de86f63bc 100644 --- a/src/libs/CardUtils.ts +++ b/src/libs/CardUtils.ts @@ -46,7 +46,7 @@ function isExpensifyCard(cardID?: number) { * @returns boolean if the cardID is in the cardList from ONYX. Includes Expensify Cards. */ function isCorporateCard(cardID: number) { - return !!allCards[cardID]; + return true; } /** diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx index 940cba181db7..e8c00f807e06 100644 --- a/src/pages/home/ReportScreen.tsx +++ b/src/pages/home/ReportScreen.tsx @@ -323,7 +323,7 @@ function ReportScreen({ /> ); - if (isSingleTransactionView) { + if (true) { headerView = ( ReportActionsUtils.getOneTransactionThreadReportID(reportActions ?? []), [reportActions]); - if (ReportUtils.isMoneyRequestReport(report)) { - headerView = ( - - ); - } + // if (ReportUtils.isMoneyRequestReport(report)) { + // headerView = ( + // + // ); + // } /** * When false the ReportActionsView will completely unmount and we will show a loader until it returns true. @@ -603,6 +603,7 @@ function ReportScreen({ ); } + console.log('REPORT SCREEN'); return ( diff --git a/src/pages/home/report/ReportActionItem.tsx b/src/pages/home/report/ReportActionItem.tsx index eeeb5b95273c..02d139780ed0 100644 --- a/src/pages/home/report/ReportActionItem.tsx +++ b/src/pages/home/report/ReportActionItem.tsx @@ -832,6 +832,7 @@ function ReportActionItem({ ? (Object.values(personalDetails ?? {}).filter((details) => whisperedToAccountIDs.includes(details?.accountID ?? -1)) as OnyxTypes.PersonalDetails[]) : []; const displayNamesWithTooltips = isWhisper ? ReportUtils.getDisplayNamesWithTooltips(whisperedToPersonalDetails, isMultipleParticipant) : []; + return ( @@ -196,6 +195,7 @@ function ReportActionsList({ ), [sortedReportActions, isOffline], ); + const lastActionIndex = sortedVisibleReportActions[0]?.reportActionID; const reportActionSize = useRef(sortedVisibleReportActions.length); const hasNewestReportAction = sortedReportActions?.[0].created === report.lastVisibleActionCreated; From efe88ce911f70c4d74fe90d08c42cb17c7b9b0c9 Mon Sep 17 00:00:00 2001 From: BrtqKr Date: Wed, 10 Apr 2024 17:31:16 +0200 Subject: [PATCH 005/502] cleanup --- src/languages/es.ts | 5 +++-- src/pages/home/report/ReportActionsList.tsx | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/languages/es.ts b/src/languages/es.ts index c9aabe62087a..a6a19d2bf35c 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -630,14 +630,14 @@ export default { routePending: 'Ruta pendiente...', receiptScanning: 'Escaneo en curso…', receiptScanInProgress: 'Escaneo en curso…', - receiptScanInProgressDescription: 'Escaneo en curso.', + receiptScanInProgressDescription: ' Escaneando recibo. Vuelva a comprobarlo más tarde o introduzca los detalles ahora.', receiptMissingDetails: 'Recibo con campos vacíos', missingAmount: 'Falta importe', missingMerchant: 'Falta comerciante', receiptStatusTitle: 'Escaneando…', receiptStatusText: 'Solo tú puedes ver este recibo cuando se está escaneando. Vuelve más tarde o introduce los detalles ahora.', receiptScanningFailed: 'El escaneo de recibo ha fallado. Introduce los detalles manualmente.', - transactionPendingText: 'La transacción tarda unos días en contabilizarse desde la fecha en que se utilizó la tarjeta.', + transactionPendingDescription: 'La transacción tarda unos días en contabilizarse desde la fecha en que se utilizó la tarjeta.', requestCount: ({count, scanningReceipts = 0, pendingReceipts = 0}: RequestCountParams) => `${count} ${Str.pluralize('solicitude', 'solicitudes', count)}${scanningReceipts > 0 ? `, ${scanningReceipts} escaneando` : ''}${ pendingReceipts > 0 ? `, ${pendingReceipts} pendiente` : '' @@ -735,6 +735,7 @@ export default { set: 'estableció', changed: 'cambió', removed: 'eliminó', + transactionPending: 'Transaction pending.', }, notificationPreferencesPage: { header: 'Preferencias de avisos', diff --git a/src/pages/home/report/ReportActionsList.tsx b/src/pages/home/report/ReportActionsList.tsx index 0068ed875b82..60a620f186cc 100644 --- a/src/pages/home/report/ReportActionsList.tsx +++ b/src/pages/home/report/ReportActionsList.tsx @@ -6,7 +6,6 @@ import React, {memo, useCallback, useEffect, useMemo, useRef, useState} from 're import {DeviceEventEmitter, InteractionManager} from 'react-native'; import type {LayoutChangeEvent, NativeScrollEvent, NativeSyntheticEvent, StyleProp, ViewStyle} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; -import Onyx from 'react-native-onyx'; import Animated, {useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated'; import InvertedFlatList from '@components/InvertedFlatList'; import {AUTOSCROLL_TO_TOP_THRESHOLD} from '@components/InvertedFlatList/BaseInvertedFlatList'; From 9a664e5d4db4201533fe1d9c9180b6fe4bdf81a9 Mon Sep 17 00:00:00 2001 From: BrtqKr Date: Wed, 10 Apr 2024 17:43:25 +0200 Subject: [PATCH 006/502] cleanup --- src/pages/home/ReportScreen.tsx | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx index e8c00f807e06..940cba181db7 100644 --- a/src/pages/home/ReportScreen.tsx +++ b/src/pages/home/ReportScreen.tsx @@ -323,7 +323,7 @@ function ReportScreen({ /> ); - if (true) { + if (isSingleTransactionView) { headerView = ( ReportActionsUtils.getOneTransactionThreadReportID(reportActions ?? []), [reportActions]); - // if (ReportUtils.isMoneyRequestReport(report)) { - // headerView = ( - // - // ); - // } + if (ReportUtils.isMoneyRequestReport(report)) { + headerView = ( + + ); + } /** * When false the ReportActionsView will completely unmount and we will show a loader until it returns true. @@ -603,7 +603,6 @@ function ReportScreen({ ); } - console.log('REPORT SCREEN'); return ( From d315efb2d08469d717e820189c2d4a388976cfee Mon Sep 17 00:00:00 2001 From: BrtqKr Date: Wed, 10 Apr 2024 17:57:36 +0200 Subject: [PATCH 007/502] cleanup --- src/libs/CardUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/CardUtils.ts b/src/libs/CardUtils.ts index 0d8de86f63bc..c4d67adcd54a 100644 --- a/src/libs/CardUtils.ts +++ b/src/libs/CardUtils.ts @@ -46,7 +46,7 @@ function isExpensifyCard(cardID?: number) { * @returns boolean if the cardID is in the cardList from ONYX. Includes Expensify Cards. */ function isCorporateCard(cardID: number) { - return true; + return !!allCards[cardID]; } /** From 4e08e070c709b6e8350d3cbe05221a8b56098ac0 Mon Sep 17 00:00:00 2001 From: BrtqKr Date: Thu, 11 Apr 2024 00:26:01 +0200 Subject: [PATCH 008/502] cleanup translations --- src/languages/es.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/languages/es.ts b/src/languages/es.ts index a6a19d2bf35c..877d745fa59c 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -628,16 +628,16 @@ export default { posted: 'Contabilizado', deleteReceipt: 'Eliminar recibo', routePending: 'Ruta pendiente...', - receiptScanning: 'Escaneo en curso…', - receiptScanInProgress: 'Escaneo en curso…', - receiptScanInProgressDescription: ' Escaneando recibo. Vuelva a comprobarlo más tarde o introduzca los detalles ahora.', + receiptScanning: 'Escaneando recibo…', + receiptScanInProgress: 'Escaneo en curso.', + receiptScanInProgressDescription: 'Escaneando recibo. Vuelva a comprobarlo más tarde o introduzca los detalles ahora.', receiptMissingDetails: 'Recibo con campos vacíos', missingAmount: 'Falta importe', missingMerchant: 'Falta comerciante', receiptStatusTitle: 'Escaneando…', receiptStatusText: 'Solo tú puedes ver este recibo cuando se está escaneando. Vuelve más tarde o introduce los detalles ahora.', receiptScanningFailed: 'El escaneo de recibo ha fallado. Introduce los detalles manualmente.', - transactionPendingDescription: 'La transacción tarda unos días en contabilizarse desde la fecha en que se utilizó la tarjeta.', + transactionPendingDescription: 'Transacción pendiente. Esto puede tardar algunos días en registrarse a partir de la fecha en que se utilizó la tarjeta.', requestCount: ({count, scanningReceipts = 0, pendingReceipts = 0}: RequestCountParams) => `${count} ${Str.pluralize('solicitude', 'solicitudes', count)}${scanningReceipts > 0 ? `, ${scanningReceipts} escaneando` : ''}${ pendingReceipts > 0 ? `, ${pendingReceipts} pendiente` : '' @@ -735,7 +735,7 @@ export default { set: 'estableció', changed: 'cambió', removed: 'eliminó', - transactionPending: 'Transaction pending.', + transactionPending: 'Transacción pendiente.', }, notificationPreferencesPage: { header: 'Preferencias de avisos', From 648e333f6178eb2b4699d024936d4ef281aacd7d Mon Sep 17 00:00:00 2001 From: BrtqKr Date: Thu, 11 Apr 2024 00:41:33 +0200 Subject: [PATCH 009/502] fix preview --- .../MoneyRequestPreviewContent.tsx | 12 ++++++++++++ src/pages/home/report/ReportActionsList.tsx | 1 + 2 files changed, 13 insertions(+) diff --git a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx index b0363135e273..e149891b0365 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx @@ -87,6 +87,7 @@ function MoneyRequestPreviewContent({ const requestMerchant = truncate(merchant, {length: CONST.REQUEST_PREVIEW.MAX_LENGTH}); const hasReceipt = TransactionUtils.hasReceipt(transaction); const isScanning = hasReceipt && TransactionUtils.isReceiptBeingScanned(transaction); + const isPending = TransactionUtils.isPending(transaction); const isOnHold = TransactionUtils.isOnHold(transaction); const isSettlementOrApprovalPartial = Boolean(iouReport?.pendingFields?.partial); const isPartialHold = isSettlementOrApprovalPartial && isOnHold; @@ -315,6 +316,17 @@ function MoneyRequestPreviewContent({ {translate('iou.receiptScanInProgress')} )} + {isPending && ( + + + {translate('iou.transactionPending')} + + )} diff --git a/src/pages/home/report/ReportActionsList.tsx b/src/pages/home/report/ReportActionsList.tsx index 60a620f186cc..0068ed875b82 100644 --- a/src/pages/home/report/ReportActionsList.tsx +++ b/src/pages/home/report/ReportActionsList.tsx @@ -6,6 +6,7 @@ import React, {memo, useCallback, useEffect, useMemo, useRef, useState} from 're import {DeviceEventEmitter, InteractionManager} from 'react-native'; import type {LayoutChangeEvent, NativeScrollEvent, NativeSyntheticEvent, StyleProp, ViewStyle} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; +import Onyx from 'react-native-onyx'; import Animated, {useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated'; import InvertedFlatList from '@components/InvertedFlatList'; import {AUTOSCROLL_TO_TOP_THRESHOLD} from '@components/InvertedFlatList/BaseInvertedFlatList'; From f2bcf10e8e12bef7242a95adbab46f0a3352e04c Mon Sep 17 00:00:00 2001 From: BrtqKr Date: Thu, 11 Apr 2024 15:57:59 +0200 Subject: [PATCH 010/502] wip --- ios/Podfile.lock | 2 +- src/components/MoneyRequestHeader.tsx | 2 ++ .../MoneyRequestPreviewContent.tsx | 1 + .../ReportActionItem/ReportPreview.tsx | 14 +++++++++++++- src/libs/ReportUtils.ts | 1 + src/pages/home/ReportScreen.tsx | 2 ++ src/pages/home/report/ReportActionsList.tsx | 19 +++++++++++++++++++ 7 files changed, 39 insertions(+), 2 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 32a8bca75bcd..94bd6e35f31d 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1921,7 +1921,7 @@ SPEC CHECKSUMS: SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 Turf: 13d1a92d969ca0311bbc26e8356cca178ce95da2 VisionCamera: 9f26224fce1233ffdad9fa4e56863e3de2190dc0 - Yoga: e64aa65de36c0832d04e8c7bd614396c77a80047 + Yoga: 13c8ef87792450193e117976337b8527b49e8c03 PODFILE CHECKSUM: a431c146e1501391834a2f299a74093bac53b530 diff --git a/src/components/MoneyRequestHeader.tsx b/src/components/MoneyRequestHeader.tsx index 5ea46f339d46..909b6e6f71f6 100644 --- a/src/components/MoneyRequestHeader.tsx +++ b/src/components/MoneyRequestHeader.tsx @@ -165,6 +165,8 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction, }); } + console.log('MONEY REQUEST HEADER'); + return ( <> diff --git a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx index e149891b0365..2a56e2f2405d 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx @@ -67,6 +67,7 @@ function MoneyRequestPreviewContent({ const {isSmallScreenWidth, windowWidth} = useWindowDimensions(); const parser = new ExpensiMark(); + console.warn('TRANSACTION ', transaction); const sessionAccountID = session?.accountID; const managerID = iouReport?.managerID ?? -1; const ownerAccountID = iouReport?.ownerAccountID ?? -1; diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx index 40c9f1afcc21..5b9c2269028c 100644 --- a/src/components/ReportActionItem/ReportPreview.tsx +++ b/src/components/ReportActionItem/ReportPreview.tsx @@ -228,7 +228,8 @@ function ReportPreview({ const shouldShowSingleRequestMerchantOrDescription = numberOfRequests === 1 && (!!formattedMerchant || !!formattedDescription) && !(hasOnlyTransactionsWithPendingRoutes && !totalDisplaySpend); const shouldShowSubtitle = !isScanning && (shouldShowSingleRequestMerchantOrDescription || numberOfRequests > 1); - const shouldShowPendingSubtitle = numberOfPendingRequests === 1 && transactionsWithReceipts.length === 1; + const shouldShowScanningSubtitle = numberOfScanningReceipts === 1 && allTransactions.length === 1; + const shouldShowPendingSubtitle = numberOfPendingRequests === 1 && allTransactions.length === 1; const {isSupportTextHtml, supportText} = useMemo(() => { if (formattedMerchant) { @@ -321,6 +322,17 @@ function ReportPreview({ )} + {shouldShowScanningSubtitle && ( + + + {translate('iou.receiptScanInProgress')} + + )} {shouldShowPendingSubtitle && ( ): boolean { */ function isMoneyRequest(reportOrID: OnyxEntry | string): boolean { const report = typeof reportOrID === 'string' ? allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportOrID}`] ?? null : reportOrID; + console.log('REPORT ', report); return isIOURequest(report) || isExpenseRequest(report); } diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx index 940cba181db7..de02342ff414 100644 --- a/src/pages/home/ReportScreen.tsx +++ b/src/pages/home/ReportScreen.tsx @@ -323,6 +323,8 @@ function ReportScreen({ /> ); + console.warn('ReportUtils.isMoneyRequest(report) ', ReportUtils.isMoneyRequest(report)); + if (isSingleTransactionView) { headerView = ( { const unsubscriber = Visibility.onVisibilityChange(() => { setIsVisible(Visibility.isVisible()); From c3285b8e4baf6fc2cf64dd0cc17dd3c3fb10c6ec Mon Sep 17 00:00:00 2001 From: BrtqKr Date: Thu, 11 Apr 2024 16:18:56 +0200 Subject: [PATCH 011/502] cleanup --- src/components/MoneyRequestHeader.tsx | 2 -- .../MoneyRequestPreviewContent.tsx | 1 - src/libs/ReportUtils.ts | 1 - src/pages/home/ReportScreen.tsx | 2 -- src/pages/home/report/ReportActionsList.tsx | 20 ------------------- 5 files changed, 26 deletions(-) diff --git a/src/components/MoneyRequestHeader.tsx b/src/components/MoneyRequestHeader.tsx index 909b6e6f71f6..5ea46f339d46 100644 --- a/src/components/MoneyRequestHeader.tsx +++ b/src/components/MoneyRequestHeader.tsx @@ -165,8 +165,6 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction, }); } - console.log('MONEY REQUEST HEADER'); - return ( <> diff --git a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx index 2a56e2f2405d..e149891b0365 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx @@ -67,7 +67,6 @@ function MoneyRequestPreviewContent({ const {isSmallScreenWidth, windowWidth} = useWindowDimensions(); const parser = new ExpensiMark(); - console.warn('TRANSACTION ', transaction); const sessionAccountID = session?.accountID; const managerID = iouReport?.managerID ?? -1; const ownerAccountID = iouReport?.ownerAccountID ?? -1; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index f03a5051d634..fec64efaac7f 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -1282,7 +1282,6 @@ function isTrackExpenseReport(report: OnyxEntry): boolean { */ function isMoneyRequest(reportOrID: OnyxEntry | string): boolean { const report = typeof reportOrID === 'string' ? allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportOrID}`] ?? null : reportOrID; - console.log('REPORT ', report); return isIOURequest(report) || isExpenseRequest(report); } diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx index de02342ff414..940cba181db7 100644 --- a/src/pages/home/ReportScreen.tsx +++ b/src/pages/home/ReportScreen.tsx @@ -323,8 +323,6 @@ function ReportScreen({ /> ); - console.warn('ReportUtils.isMoneyRequest(report) ', ReportUtils.isMoneyRequest(report)); - if (isSingleTransactionView) { headerView = ( { const unsubscriber = Visibility.onVisibilityChange(() => { setIsVisible(Visibility.isVisible()); From fea7ada105b4d1cbc82e9ff5ebf723e9b40c07b9 Mon Sep 17 00:00:00 2001 From: BrtqKr Date: Mon, 15 Apr 2024 11:56:37 +0200 Subject: [PATCH 012/502] fix typography --- src/components/MoneyRequestHeader.tsx | 8 ++++---- .../MoneyRequestPreview/MoneyRequestPreviewContent.tsx | 8 ++++++-- src/components/ReportActionItem/ReportPreview.tsx | 8 ++++++-- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/components/MoneyRequestHeader.tsx b/src/components/MoneyRequestHeader.tsx index 5ea46f339d46..7557799472e1 100644 --- a/src/components/MoneyRequestHeader.tsx +++ b/src/components/MoneyRequestHeader.tsx @@ -188,8 +188,8 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction, title={ } @@ -202,8 +202,8 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction, title={ } diff --git a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx index 08d693dd109a..63950e3fe8d0 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx @@ -313,7 +313,9 @@ function MoneyRequestPreviewContent({ width={variables.iconSizeExtraSmall} fill={theme.textSupporting} /> - {translate('iou.receiptScanInProgress')} + + {translate('iou.receiptScanInProgress')} + )} {isPending && ( @@ -324,7 +326,9 @@ function MoneyRequestPreviewContent({ width={variables.iconSizeExtraSmall} fill={theme.textSupporting} /> - {translate('iou.transactionPending')} + + {translate('iou.transactionPending')} + )} diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx index 231b1176423b..2b5034708dac 100644 --- a/src/components/ReportActionItem/ReportPreview.tsx +++ b/src/components/ReportActionItem/ReportPreview.tsx @@ -330,7 +330,9 @@ function ReportPreview({ width={variables.iconSizeExtraSmall} fill={theme.textSupporting} /> - {translate('iou.receiptScanInProgress')} + + {translate('iou.receiptScanInProgress')} + )} {shouldShowPendingSubtitle && ( @@ -341,7 +343,9 @@ function ReportPreview({ width={variables.iconSizeExtraSmall} fill={theme.textSupporting} /> - {translate('iou.transactionPending')} + + {translate('iou.transactionPending')} + )} From dd4ae04abcefd6e6768ca036bbf32744a02c493c Mon Sep 17 00:00:00 2001 From: BrtqKr Date: Mon, 15 Apr 2024 17:16:42 +0200 Subject: [PATCH 013/502] style fixes --- src/components/MoneyRequestHeader.tsx | 4 ++-- src/components/MoneyRequestHeaderStatusBar.tsx | 2 +- .../MoneyRequestPreviewContent.tsx | 8 ++------ src/components/ReportActionItem/ReportPreview.tsx | 12 ++++-------- 4 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/components/MoneyRequestHeader.tsx b/src/components/MoneyRequestHeader.tsx index 7557799472e1..c50913bc2d31 100644 --- a/src/components/MoneyRequestHeader.tsx +++ b/src/components/MoneyRequestHeader.tsx @@ -190,7 +190,7 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction, src={Expensicons.CreditCardHourglass} height={variables.iconSizeSmall} width={variables.iconSizeSmall} - fill={theme.textSupporting} + fill={theme.icon} /> } description={translate('iou.transactionPendingDescription')} @@ -204,7 +204,7 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction, src={Expensicons.ReceiptScan} height={variables.iconSizeSmall} width={variables.iconSizeSmall} - fill={theme.textSupporting} + fill={theme.icon} /> } description={translate('iou.receiptScanInProgressDescription')} diff --git a/src/components/MoneyRequestHeaderStatusBar.tsx b/src/components/MoneyRequestHeaderStatusBar.tsx index d21e66ba39eb..0052768a4cf0 100644 --- a/src/components/MoneyRequestHeaderStatusBar.tsx +++ b/src/components/MoneyRequestHeaderStatusBar.tsx @@ -25,7 +25,7 @@ function MoneyRequestHeaderStatusBar({title, description, shouldShowBorderBottom {title} ) : ( - {title} + {title} )} {description} diff --git a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx index 63950e3fe8d0..c234eb749653 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx @@ -313,9 +313,7 @@ function MoneyRequestPreviewContent({ width={variables.iconSizeExtraSmall} fill={theme.textSupporting} /> - - {translate('iou.receiptScanInProgress')} - + {translate('iou.receiptScanInProgress')} )} {isPending && ( @@ -326,9 +324,7 @@ function MoneyRequestPreviewContent({ width={variables.iconSizeExtraSmall} fill={theme.textSupporting} /> - - {translate('iou.transactionPending')} - + {translate('iou.transactionPending')} )} diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx index 2b5034708dac..766680fd378b 100644 --- a/src/components/ReportActionItem/ReportPreview.tsx +++ b/src/components/ReportActionItem/ReportPreview.tsx @@ -328,11 +328,9 @@ function ReportPreview({ src={Expensicons.ReceiptScan} height={variables.iconSizeExtraSmall} width={variables.iconSizeExtraSmall} - fill={theme.textSupporting} + fill={theme.icon} /> - - {translate('iou.receiptScanInProgress')} - + {translate('iou.receiptScanInProgress')} )} {shouldShowPendingSubtitle && ( @@ -341,11 +339,9 @@ function ReportPreview({ src={Expensicons.CreditCardHourglass} height={variables.iconSizeExtraSmall} width={variables.iconSizeExtraSmall} - fill={theme.textSupporting} + fill={theme.icon} /> - - {translate('iou.transactionPending')} - + {translate('iou.transactionPending')} )} From 92a626574ba95b9dd448df13967533aa41318b6c Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Mon, 15 Apr 2024 22:01:51 +0100 Subject: [PATCH 014/502] Participants onyx migration --- src/libs/migrateOnyx.ts | 2 + src/libs/migrations/Participants.ts | 60 +++++++++++++++++++++++++++++ src/types/onyx/Report.ts | 2 - 3 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 src/libs/migrations/Participants.ts diff --git a/src/libs/migrateOnyx.ts b/src/libs/migrateOnyx.ts index 412a8e00f052..674b5b8242dc 100644 --- a/src/libs/migrateOnyx.ts +++ b/src/libs/migrateOnyx.ts @@ -2,6 +2,7 @@ import Log from './Log'; import CheckForPreviousReportActionID from './migrations/CheckForPreviousReportActionID'; import KeyReportActionsDraftByReportActionID from './migrations/KeyReportActionsDraftByReportActionID'; import NVPMigration from './migrations/NVPMigration'; +import Participants from './migrations/Participants'; import PronounsMigration from './migrations/PronounsMigration'; import RemoveEmptyReportActionsDrafts from './migrations/RemoveEmptyReportActionsDrafts'; import RenameReceiptFilename from './migrations/RenameReceiptFilename'; @@ -21,6 +22,7 @@ export default function () { RemoveEmptyReportActionsDrafts, NVPMigration, PronounsMigration, + Participants, ]; // Reduce all promises down to a single promise. All promises run in a linear fashion, waiting for the diff --git a/src/libs/migrations/Participants.ts b/src/libs/migrations/Participants.ts new file mode 100644 index 000000000000..0e0cd8722348 --- /dev/null +++ b/src/libs/migrations/Participants.ts @@ -0,0 +1,60 @@ +import Onyx from 'react-native-onyx'; +import type {NullishDeep, OnyxCollection} from 'react-native-onyx'; +import Log from '@libs/Log'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {Report} from '@src/types/onyx'; +import type {Participant, Participants} from '@src/types/onyx/Report'; + +type ReportKey = `${typeof ONYXKEYS.COLLECTION.REPORT}${string}`; +type OldReport = Report & {participantAccountIDs?: number[]; visibleChatMemberAccountIDs?: number[]}; +type OldReportCollection = Record>; + +function getReports(): Promise> { + return new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT, + waitForCollectionCallback: true, + callback: (reports) => { + Onyx.disconnect(connectionID); + return resolve(reports); + }, + }); + }); +} + +export default function (): Promise { + return getReports().then((reports) => { + if (!reports) { + Log.info('[Migrate Onyx] Skipped Participants migration because there are no reports'); + return; + } + + const collection = Object.entries(reports).reduce((reportsCollection, [onyxKey, report]) => { + // If we have participantAccountIDs then this report is eligible for migration + if (report?.participantAccountIDs) { + const visibleParticipants = new Set(report.visibleChatMemberAccountIDs); + const participants = report.participantAccountIDs.reduce((reportParticipants, accountID) => { + const participant: Participant = { + hidden: !visibleParticipants.has(accountID), + }; + + // eslint-disable-next-line no-param-reassign + reportParticipants[accountID] = participant; + return reportParticipants; + }, {}); + + // eslint-disable-next-line no-param-reassign + reportsCollection[onyxKey as ReportKey] = { + participants, + participantAccountIDs: null, + visibleChatMemberAccountIDs: null, + }; + } + + return reportsCollection; + }, {}); + + // eslint-disable-next-line rulesdir/prefer-actions-set-data + return Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT, collection).then(() => Log.info('[Migrate Onyx] Ran migration Participants successfully')); + }); +} diff --git a/src/types/onyx/Report.ts b/src/types/onyx/Report.ts index fe3eec6dc11e..b271255b06a6 100644 --- a/src/types/onyx/Report.ts +++ b/src/types/onyx/Report.ts @@ -140,8 +140,6 @@ type Report = OnyxCommon.OnyxValueWithOfflineFeedback< ownerAccountID?: number; ownerEmail?: string; participants?: Participants; - participantAccountIDs?: number[]; - visibleChatMemberAccountIDs?: number[]; total?: number; unheldTotal?: number; currency?: string; From 02b2315b9e91a1b96800045c82d23bedb018b164 Mon Sep 17 00:00:00 2001 From: ntdiary <2471314@gmail.com> Date: Tue, 16 Apr 2024 22:56:51 +0800 Subject: [PATCH 015/502] clean up mobile safari code --- src/libs/updateMultilineInputRange/index.ts | 11 ++---- .../report/ReportActionItemMessageEdit.tsx | 35 ++++--------------- 2 files changed, 9 insertions(+), 37 deletions(-) diff --git a/src/libs/updateMultilineInputRange/index.ts b/src/libs/updateMultilineInputRange/index.ts index f5d71c5e2038..d0bc1c306dac 100644 --- a/src/libs/updateMultilineInputRange/index.ts +++ b/src/libs/updateMultilineInputRange/index.ts @@ -1,4 +1,3 @@ -import * as Browser from '@libs/Browser'; import type UpdateMultilineInputRange from './types'; /** @@ -17,14 +16,10 @@ const updateMultilineInputRange: UpdateMultilineInputRange = (input, shouldAutoF if ('value' in input && input.value && input.setSelectionRange) { const length = input.value.length; - - // For mobile Safari, updating the selection prop on an unfocused input will cause it to automatically gain focus - // and subsequent programmatic focus shifts (e.g., modal focus trap) to show the blue frame (:focus-visible style), - // so we need to ensure that it is only updated after focus. - const shouldSetSelection = !(Browser.isMobileSafari() && !shouldAutoFocus); - if (shouldSetSelection) { - input.setSelectionRange(length, length); + if (!shouldAutoFocus) { + return; } + input.setSelectionRange(length, length); // eslint-disable-next-line no-param-reassign input.scrollTop = input.scrollHeight; } diff --git a/src/pages/home/report/ReportActionItemMessageEdit.tsx b/src/pages/home/report/ReportActionItemMessageEdit.tsx index fc3c92434fc4..8920f789e167 100644 --- a/src/pages/home/report/ReportActionItemMessageEdit.tsx +++ b/src/pages/home/report/ReportActionItemMessageEdit.tsx @@ -22,7 +22,6 @@ import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; -import * as Browser from '@libs/Browser'; import * as ComposerUtils from '@libs/ComposerUtils'; import * as EmojiUtils from '@libs/EmojiUtils'; import focusComposerWithDelay from '@libs/focusComposerWithDelay'; @@ -68,7 +67,6 @@ type ReportActionItemMessageEditProps = { const emojiButtonID = 'emojiButton'; const messageEditInput = 'messageEditInput'; -const isMobileSafari = Browser.isMobileSafari(); const shouldUseForcedSelectionRange = shouldUseEmojiPickerSelection(); function ReportActionItemMessageEdit( @@ -84,14 +82,6 @@ function ReportActionItemMessageEdit( const {isSmallScreenWidth} = useWindowDimensions(); const prevDraftMessage = usePrevious(draftMessage); - const getInitialSelection = () => { - if (isMobileSafari) { - return {start: 0, end: 0}; - } - - const length = draftMessage.length; - return {start: length, end: length}; - }; const emojisPresentBefore = useRef([]); const [draft, setDraft] = useState(() => { if (draftMessage) { @@ -99,7 +89,7 @@ function ReportActionItemMessageEdit( } return draftMessage; }); - const [selection, setSelection] = useState(getInitialSelection); + const [selection, setSelection] = useState({start: 0, end: 0}); const [isFocused, setIsFocused] = useState(false); const {hasExceededMaxCommentLength, validateCommentMaxLength} = useHandleExceedMaxCommentLength(); const [modal, setModal] = useState({ @@ -171,23 +161,10 @@ function ReportActionItemMessageEdit( ); useEffect(() => { - // For mobile Safari, updating the selection prop on an unfocused input will cause it to automatically gain focus - // and subsequent programmatic focus shifts (e.g., modal focus trap) to show the blue frame (:focus-visible style), - // so we need to ensure that it is only updated after focus. - if (isMobileSafari) { - setDraft((prevDraft) => { - setSelection({ - start: prevDraft.length, - end: prevDraft.length, - }); - return prevDraft; - }); - - // Scroll content of textInputRef to bottom - if (textInputRef.current) { - textInputRef.current.scrollTop = textInputRef.current.scrollHeight; - } - } + setSelection({ + start: draftMessage.length, + end: draftMessage.length, + }); return () => { InputFocus.callback(() => setIsFocused(false)); @@ -208,7 +185,7 @@ function ReportActionItemMessageEdit( // Show the main composer when the focused message is deleted from another client // to prevent the main composer stays hidden until we swtich to another chat. setShouldShowComposeInputKeyboardAware(true); - }; + } // eslint-disable-next-line react-hooks/exhaustive-deps -- this cleanup needs to be called only on unmount }, [action.reportActionID]); From a743ffcb12f76928915760d1524fc9eb036489b6 Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 17 Apr 2024 15:10:05 +0700 Subject: [PATCH 016/502] fix empty chat displayed in focus mode --- src/libs/ReportUtils.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index f31b4a780c5a..5b3f0e66ffd8 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -4470,11 +4470,23 @@ function buildOptimisticMoneyRequestEntities( return [createdActionForChat, createdActionForIOUReport, iouAction, transactionThread, createdActionForTransactionThread]; } +// Check if the report is empty report +function isEmptyReport(report: OnyxEntry): boolean { + if (!report) { + return true; + } + const lastVisibleMessage = ReportActionsUtils.getLastVisibleMessage(report.reportID); + return !report.lastMessageText && !report.lastMessageTranslationKey && !lastVisibleMessage.lastMessageText && !lastVisibleMessage.lastMessageTranslationKey; +} + function isUnread(report: OnyxEntry): boolean { if (!report) { return false; } + if (isEmptyReport(report)) { + return false; + } // lastVisibleActionCreated and lastReadTime are both datetime strings and can be compared directly const lastVisibleActionCreated = report.lastVisibleActionCreated ?? ''; const lastReadTime = report.lastReadTime ?? ''; @@ -4678,8 +4690,8 @@ function shouldReportBeInOptionList({ if (hasDraftComment || requiresAttentionFromCurrentUser(report)) { return true; } - const lastVisibleMessage = ReportActionsUtils.getLastVisibleMessage(report.reportID); - const isEmptyChat = !report.lastMessageText && !report.lastMessageTranslationKey && !lastVisibleMessage.lastMessageText && !lastVisibleMessage.lastMessageTranslationKey; + + const isEmptyChat = isEmptyReport(report); const canHideReport = shouldHideReport(report, currentReportId); // Include reports if they are pinned From 787ad3b011378172c0bc70d454d962a6a8676e36 Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 17 Apr 2024 15:58:57 +0700 Subject: [PATCH 017/502] fix jest test --- tests/unit/SidebarOrderTest.ts | 16 +++++++----- tests/unit/SidebarTest.ts | 2 ++ tests/unit/UnreadIndicatorUpdaterTest.ts | 32 ++++++++++++++++++++---- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/tests/unit/SidebarOrderTest.ts b/tests/unit/SidebarOrderTest.ts index 2758d43fb81e..0b8ec5b1385f 100644 --- a/tests/unit/SidebarOrderTest.ts +++ b/tests/unit/SidebarOrderTest.ts @@ -861,10 +861,10 @@ describe('Sidebar', () => { it('alphabetizes chats', () => { LHNTestUtils.getDefaultRenderedSidebarLinks(); - const report1 = LHNTestUtils.getFakeReport([1, 2], 3, true); - const report2 = LHNTestUtils.getFakeReport([3, 4], 2, true); - const report3 = LHNTestUtils.getFakeReport([5, 6], 1, true); - const report4 = LHNTestUtils.getFakeReport([7, 8], 0, true); + const report1 = {...LHNTestUtils.getFakeReport([1, 2], 3, true), lastMessageText: 'test'}; + const report2 = {...LHNTestUtils.getFakeReport([3, 4], 2, true), lastMessageText: 'test'}; + const report3 = {...LHNTestUtils.getFakeReport([5, 6], 1, true), lastMessageText: 'test'}; + const report4 = {...LHNTestUtils.getFakeReport([7, 8], 0, true), lastMessageText: 'test'}; const reportCollectionDataSet: ReportCollectionDataSet = { [`${ONYXKEYS.COLLECTION.REPORT}${report1.reportID}`]: report1, @@ -918,9 +918,13 @@ describe('Sidebar', () => { chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM, statusNum: CONST.REPORT.STATUS_NUM.CLOSED, stateNum: CONST.REPORT.STATE_NUM.APPROVED, + lastMessageText: 'test', }; - const report2 = LHNTestUtils.getFakeReport([3, 4], 2, true); - const report3 = LHNTestUtils.getFakeReport([5, 6], 1, true); + const report2 = { + ...LHNTestUtils.getFakeReport([3, 4], 2, true), + lastMessageText: 'test', + }; + const report3 = {...LHNTestUtils.getFakeReport([5, 6], 1, true), lastMessageText: 'test'}; // Given the user is in all betas const betas = [CONST.BETAS.DEFAULT_ROOMS]; diff --git a/tests/unit/SidebarTest.ts b/tests/unit/SidebarTest.ts index 23ea0d377634..75f8fa256c57 100644 --- a/tests/unit/SidebarTest.ts +++ b/tests/unit/SidebarTest.ts @@ -42,6 +42,7 @@ describe('Sidebar', () => { chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM, statusNum: CONST.REPORT.STATUS_NUM.CLOSED, stateNum: CONST.REPORT.STATE_NUM.APPROVED, + lastMessageText: 'test', }; const action = { @@ -94,6 +95,7 @@ describe('Sidebar', () => { chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM, statusNum: CONST.REPORT.STATUS_NUM.CLOSED, stateNum: CONST.REPORT.STATE_NUM.APPROVED, + lastMessageText: 'test', }; const action = { ...LHNTestUtils.getFakeReportAction('email1@test.com', 3), diff --git a/tests/unit/UnreadIndicatorUpdaterTest.ts b/tests/unit/UnreadIndicatorUpdaterTest.ts index a5f58b57793a..22141eee791d 100644 --- a/tests/unit/UnreadIndicatorUpdaterTest.ts +++ b/tests/unit/UnreadIndicatorUpdaterTest.ts @@ -6,9 +6,23 @@ describe('UnreadIndicatorUpdaterTest', () => { describe('should return correct number of unread reports', () => { it('given last read time < last visible action created', () => { const reportsToBeUsed = { - 1: {reportID: '1', reportName: 'test', type: CONST.REPORT.TYPE.EXPENSE, lastReadTime: '2023-07-08 07:15:44.030', lastVisibleActionCreated: '2023-08-08 07:15:44.030'}, - 2: {reportID: '2', reportName: 'test', type: CONST.REPORT.TYPE.TASK, lastReadTime: '2023-02-05 09:12:05.000', lastVisibleActionCreated: '2023-02-06 07:15:44.030'}, - 3: {reportID: '3', reportName: 'test', type: CONST.REPORT.TYPE.TASK}, + 1: { + reportID: '1', + reportName: 'test', + type: CONST.REPORT.TYPE.EXPENSE, + lastReadTime: '2023-07-08 07:15:44.030', + lastVisibleActionCreated: '2023-08-08 07:15:44.030', + lastMessageText: 'test', + }, + 2: { + reportID: '2', + reportName: 'test', + type: CONST.REPORT.TYPE.TASK, + lastReadTime: '2023-02-05 09:12:05.000', + lastVisibleActionCreated: '2023-02-06 07:15:44.030', + lastMessageText: 'test', + }, + 3: {reportID: '3', reportName: 'test', type: CONST.REPORT.TYPE.TASK, lastMessageText: 'test'}, }; expect(getUnreadReportsForUnreadIndicator(reportsToBeUsed, '3').length).toBe(2); }); @@ -31,9 +45,17 @@ describe('UnreadIndicatorUpdaterTest', () => { notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, lastReadTime: '2023-07-08 07:15:44.030', lastVisibleActionCreated: '2023-08-08 07:15:44.030', + lastMessageText: 'test', + }, + 2: { + reportID: '2', + reportName: 'test', + type: CONST.REPORT.TYPE.TASK, + lastReadTime: '2023-02-05 09:12:05.000', + lastVisibleActionCreated: '2023-02-06 07:15:44.030', + lastMessageText: 'test', }, - 2: {reportID: '2', reportName: 'test', type: CONST.REPORT.TYPE.TASK, lastReadTime: '2023-02-05 09:12:05.000', lastVisibleActionCreated: '2023-02-06 07:15:44.030'}, - 3: {reportID: '3', reportName: 'test', type: CONST.REPORT.TYPE.TASK}, + 3: {reportID: '3', reportName: 'test', type: CONST.REPORT.TYPE.TASK, lastMessageText: 'test'}, }; expect(getUnreadReportsForUnreadIndicator(reportsToBeUsed, '3').length).toBe(1); }); From ed168c1a2206d839926655ad4bc7d3334ebdc510 Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Wed, 17 Apr 2024 22:50:28 +0200 Subject: [PATCH 018/502] feat: setup Terms and Fees step --- src/languages/en.ts | 4 + src/languages/es.ts | 4 + .../TermsAndFees/TermsAndFees.tsx | 58 ++++++++++ .../TermsAndFees/substeps/FeesStep.tsx | 24 ++++ .../TermsAndFees/substeps/TermsStep.tsx | 106 ++++++++++++++++++ 5 files changed, 196 insertions(+) create mode 100644 src/pages/EnablePayments/TermsAndFees/TermsAndFees.tsx create mode 100644 src/pages/EnablePayments/TermsAndFees/substeps/FeesStep.tsx create mode 100644 src/pages/EnablePayments/TermsAndFees/substeps/TermsStep.tsx diff --git a/src/languages/en.ts b/src/languages/en.ts index fda7acc309bd..2aab5f00c830 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1564,6 +1564,7 @@ export default { }, termsStep: { headerTitle: 'Terms and fees', + headerTitleRefactor: 'Fees and terms', haveReadAndAgree: 'I have read and agree to receive ', electronicDisclosures: 'electronic disclosures', agreeToThe: 'I agree to the', @@ -1574,6 +1575,9 @@ export default { noOverdraftOrCredit: 'No overdraft/credit feature.', electronicFundsWithdrawal: 'Electronic funds withdrawal', standard: 'Standard', + takeALookAtSomeFees: 'Take a look at some fees.', + checkPlease: 'Check please.', + agreeToTerms: 'Agree to the terms and you’ll be good to go!', shortTermsForm: { expensifyPaymentsAccount: ({walletProgram}: WalletProgramParams) => `The Expensify Wallet is issued by ${walletProgram}.`, perPurchase: 'Per purchase', diff --git a/src/languages/es.ts b/src/languages/es.ts index 46a8d051bdfe..acdf9978de0b 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1585,6 +1585,7 @@ export default { }, termsStep: { headerTitle: 'Condiciones y tarifas', + headerTitleRefactor: 'Tarifas y condiciones', haveReadAndAgree: 'He leído y acepto recibir ', electronicDisclosures: 'divulgaciones electrónicas', agreeToThe: 'Estoy de acuerdo con el ', @@ -1595,6 +1596,9 @@ export default { noOverdraftOrCredit: 'Sin función de sobregiro/crédito', electronicFundsWithdrawal: 'Retiro electrónico de fondos', standard: 'Estándar', + takeALookAtSomeFees: 'Echa un vistazo a algunas tarifas.', + checkPlease: 'Por favor, revisa.', + agreeToTerms: 'Debes aceptar los términos y condiciones para continuar.', shortTermsForm: { expensifyPaymentsAccount: ({walletProgram}: WalletProgramParams) => `La billetera Expensify es emitida por ${walletProgram}.`, perPurchase: 'Por compra', diff --git a/src/pages/EnablePayments/TermsAndFees/TermsAndFees.tsx b/src/pages/EnablePayments/TermsAndFees/TermsAndFees.tsx new file mode 100644 index 000000000000..7e26f652efe8 --- /dev/null +++ b/src/pages/EnablePayments/TermsAndFees/TermsAndFees.tsx @@ -0,0 +1,58 @@ +import React from 'react'; +import {View} from 'react-native'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; +import ScreenWrapper from '@components/ScreenWrapper'; +import useLocalize from '@hooks/useLocalize'; +import useSubStep from '@hooks/useSubStep'; +import type {SubStepProps} from '@hooks/useSubStep/types'; +import useThemeStyles from '@hooks/useThemeStyles'; +import CONST from '@src/CONST'; +import FeesStep from './substeps/FeesStep'; +import TermsStep from './substeps/TermsStep'; + +const termsAndFeesSubsteps: Array> = [FeesStep, TermsStep]; + +function TermsAndFees() { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + + const submit = () => {}; + const {componentToRender: SubStep, isEditing, screenIndex, nextScreen, prevScreen, moveTo} = useSubStep({bodyContent: termsAndFeesSubsteps, startFrom: 0, onFinished: submit}); + + const handleBackButtonPress = () => { + if (screenIndex === 0) { + return; + } + prevScreen(); + }; + + return ( + + + + + + + + ); +} + +TermsAndFees.displayName = 'TermsAndFees'; + +export default TermsAndFees; diff --git a/src/pages/EnablePayments/TermsAndFees/substeps/FeesStep.tsx b/src/pages/EnablePayments/TermsAndFees/substeps/FeesStep.tsx new file mode 100644 index 000000000000..78ff371b747c --- /dev/null +++ b/src/pages/EnablePayments/TermsAndFees/substeps/FeesStep.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import {useOnyx} from 'react-native-onyx'; +import ScrollView from '@components/ScrollView'; +import useThemeStyles from '@hooks/useThemeStyles'; +import LongTermsForm from '@pages/EnablePayments/TermsPage/LongTermsForm'; +import ShortTermsForm from '@pages/EnablePayments/TermsPage/ShortTermsForm'; +import ONYXKEYS from '@src/ONYXKEYS'; + +function FeesStep() { + const styles = useThemeStyles(); + const [userWallet] = useOnyx(ONYXKEYS.USER_WALLET); + + return ( + + + + + ); +} + +export default FeesStep; diff --git a/src/pages/EnablePayments/TermsAndFees/substeps/TermsStep.tsx b/src/pages/EnablePayments/TermsAndFees/substeps/TermsStep.tsx new file mode 100644 index 000000000000..e77bf7db4817 --- /dev/null +++ b/src/pages/EnablePayments/TermsAndFees/substeps/TermsStep.tsx @@ -0,0 +1,106 @@ +import React, {useEffect, useState} from 'react'; +import {View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import CheckboxWithLabel from '@components/CheckboxWithLabel'; +import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton'; +import ScrollView from '@components/ScrollView'; +import Text from '@components/Text'; +import TextLink from '@components/TextLink'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as ErrorUtils from '@libs/ErrorUtils'; +import * as BankAccounts from '@userActions/BankAccounts'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; + +function HaveReadAndAgreeLabel() { + const {translate} = useLocalize(); + + return ( + + {`${translate('termsStep.haveReadAndAgree')}`} + {`${translate('termsStep.electronicDisclosures')}.`} + + ); +} + +function AgreeToTheLabel() { + const {translate} = useLocalize(); + + return ( + + {`${translate('termsStep.agreeToThe')} `} + {`${translate('common.privacy')} `} + {`${translate('common.and')} `} + {`${translate('termsStep.walletAgreement')}.`} + + ); +} + +function TermsStep() { + const styles = useThemeStyles(); + const [hasAcceptedDisclosure, setHasAcceptedDisclosure] = useState(false); + const [hasAcceptedPrivacyPolicyAndWalletAgreement, setHasAcceptedPrivacyPolicyAndWalletAgreement] = useState(false); + const [error, setError] = useState(false); + const {translate} = useLocalize(); + + const [walletTerms] = useOnyx(ONYXKEYS.WALLET_TERMS); + + const errorMessage = error ? 'common.error.acceptTerms' : ErrorUtils.getLatestErrorMessage(walletTerms ?? {}) ?? ''; + + const toggleDisclosure = () => { + setHasAcceptedDisclosure(!hasAcceptedDisclosure); + }; + + const togglePrivacyPolicy = () => { + setHasAcceptedPrivacyPolicyAndWalletAgreement(!hasAcceptedPrivacyPolicyAndWalletAgreement); + }; + + /** clear error */ + useEffect(() => { + if (!hasAcceptedDisclosure || !hasAcceptedPrivacyPolicyAndWalletAgreement) { + return; + } + + setError(false); + }, [hasAcceptedDisclosure, hasAcceptedPrivacyPolicyAndWalletAgreement]); + + return ( + + {translate('termsStep.checkPlease')} + {translate('termsStep.agreeToTerms')} + + + { + if (!hasAcceptedDisclosure || !hasAcceptedPrivacyPolicyAndWalletAgreement) { + setError(true); + return; + } + + setError(false); + BankAccounts.acceptWalletTerms({ + hasAcceptedTerms: hasAcceptedDisclosure && hasAcceptedPrivacyPolicyAndWalletAgreement, + reportID: walletTerms?.chatReportID ?? '', + }); + }} + message={errorMessage} + isAlertVisible={error || Boolean(errorMessage)} + isLoading={!!walletTerms?.isLoading} + containerStyles={[styles.mh0, styles.mv4]} + /> + + ); +} + +export default TermsStep; From 7574fc9acbe20a012b7d92a90ff1523d20b373d6 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 18 Apr 2024 13:19:08 +0100 Subject: [PATCH 019/502] add taxAmount param to updateMoneyRequestAmountAndCurrency --- src/libs/actions/IOU.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 83caa65e1d77..43cc73df9c97 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -4449,6 +4449,7 @@ type UpdateMoneyRequestAmountAndCurrencyParams = { transactionThreadReportID: string; currency: string; amount: number; + taxAmount?: number; policy?: OnyxEntry; policyTagList?: OnyxEntry; policyCategories?: OnyxEntry; @@ -4460,6 +4461,7 @@ function updateMoneyRequestAmountAndCurrency({ transactionThreadReportID, currency, amount, + taxAmount, policy, policyTagList, policyCategories, @@ -4467,6 +4469,7 @@ function updateMoneyRequestAmountAndCurrency({ const transactionChanges = { amount, currency, + ...(taxAmount && {taxAmount}), }; const {params, onyxData} = getUpdateMoneyRequestParams( transactionID, From 1ed12dfe94efdb4cf61a0cf865e98b2dd08f71ee Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 18 Apr 2024 13:19:58 +0100 Subject: [PATCH 020/502] should optimistically update tax amount when updating expense amount --- .../iou/request/step/IOURequestStepAmount.tsx | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepAmount.tsx b/src/pages/iou/request/step/IOURequestStepAmount.tsx index cb8e51120f01..7b56049811fc 100644 --- a/src/pages/iou/request/step/IOURequestStepAmount.tsx +++ b/src/pages/iou/request/step/IOURequestStepAmount.tsx @@ -16,7 +16,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; -import type {Transaction} from '@src/types/onyx'; +import type {Policy, TaxRatesWithDefault, Transaction} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import StepScreenWrapper from './StepScreenWrapper'; import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; @@ -33,6 +33,9 @@ type IOURequestStepAmountOnyxProps = { /** The draft transaction object being modified in Onyx */ draftTransaction: OnyxEntry; + + /** The policy which the user has access to and which the report is tied to */ + policy: OnyxEntry; }; type IOURequestStepAmountProps = IOURequestStepAmountOnyxProps & @@ -40,7 +43,15 @@ type IOURequestStepAmountProps = IOURequestStepAmountOnyxProps & /** The transaction object being modified in Onyx */ transaction: OnyxEntry; }; - +function getTaxAmount(transaction: OnyxEntry, taxRates: TaxRatesWithDefault | undefined, newAmount: number) { + if (!transaction?.amount) { + return; + } + const transactionTaxCode = transaction?.taxCode ?? ''; + const defaultTaxValue = taxRates?.defaultValue; + const taxPercentage = (transactionTaxCode ? taxRates?.taxes[transactionTaxCode]?.value : defaultTaxValue) ?? ''; + return CurrencyUtils.convertToBackendAmount(TransactionUtils.calculateTaxAmount(taxPercentage, newAmount)); +} function IOURequestStepAmount({ report, route: { @@ -49,6 +60,7 @@ function IOURequestStepAmount({ transaction, splitDraftTransaction, draftTransaction, + policy, }: IOURequestStepAmountProps) { const {translate} = useLocalize(); const textInput = useRef(null); @@ -148,7 +160,9 @@ function IOURequestStepAmount({ return; } - IOU.updateMoneyRequestAmountAndCurrency({transactionID, transactionThreadReportID: reportID, currency, amount: newAmount}); + const taxAmount = getTaxAmount(transaction, policy?.taxRates, newAmount); + + IOU.updateMoneyRequestAmountAndCurrency({transactionID, transactionThreadReportID: reportID, currency, amount: newAmount, taxAmount}); Navigation.dismissModal(); }; @@ -190,6 +204,9 @@ export default withWritableReportOrNotFound( return `${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`; }, }, + policy: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`, + }, })(IOURequestStepAmount), ), ); From 1c16b1aeab10ab4e85462dcc9b50cb399d6588f7 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 18 Apr 2024 13:33:58 +0100 Subject: [PATCH 021/502] add UpdateMoneyRequestTaxRateParams types to updateMoneyRequestTaxRate --- src/libs/actions/IOU.ts | 18 ++++++++++-------- .../request/step/IOURequestStepTaxRatePage.tsx | 9 ++++++++- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 43cc73df9c97..04dd151506bb 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -2379,15 +2379,17 @@ function updateMoneyRequestTaxAmount( API.write('UpdateMoneyRequestTaxAmount', params, onyxData); } +type UpdateMoneyRequestTaxRateParams = { + transactionID: string; + optimisticReportActionID: string; + taxCode: string; + policy: OnyxEntry; + policyTagList: OnyxEntry; + policyCategories: OnyxEntry; +}; + /** Updates the created tax rate of an expense */ -function updateMoneyRequestTaxRate( - transactionID: string, - optimisticReportActionID: string, - taxCode: string, - policy: OnyxEntry, - policyTagList: OnyxEntry, - policyCategories: OnyxEntry, -) { +function updateMoneyRequestTaxRate({transactionID, optimisticReportActionID, taxCode, policy, policyTagList, policyCategories}: UpdateMoneyRequestTaxRateParams) { const transactionChanges = { taxCode, }; diff --git a/src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx b/src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx index da3a244a2db2..3e14610652df 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx +++ b/src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx @@ -74,7 +74,14 @@ function IOURequestStepTaxRatePage({ navigateBack(); return; } - IOU.updateMoneyRequestTaxRate(transaction?.transactionID ?? '', report?.reportID ?? '', newTaxCode, policy, policyTags, policyCategories); + IOU.updateMoneyRequestTaxRate({ + transactionID: transaction?.transactionID ?? '', + optimisticReportActionID: report?.reportID ?? '', + taxCode: newTaxCode, + policy, + policyTagList: policyTags, + policyCategories, + }); navigateBack(); return; } From 8dce58a29da1500c7178168f31affbb669abeb4a Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 18 Apr 2024 13:37:51 +0100 Subject: [PATCH 022/502] add taxAmount to UpdateMoneyRequestTaxRateParams types --- src/libs/actions/IOU.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 04dd151506bb..53fc9e408a06 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -2383,15 +2383,17 @@ type UpdateMoneyRequestTaxRateParams = { transactionID: string; optimisticReportActionID: string; taxCode: string; + taxAmount?: number; policy: OnyxEntry; policyTagList: OnyxEntry; policyCategories: OnyxEntry; }; /** Updates the created tax rate of an expense */ -function updateMoneyRequestTaxRate({transactionID, optimisticReportActionID, taxCode, policy, policyTagList, policyCategories}: UpdateMoneyRequestTaxRateParams) { +function updateMoneyRequestTaxRate({transactionID, optimisticReportActionID, taxCode, taxAmount, policy, policyTagList, policyCategories}: UpdateMoneyRequestTaxRateParams) { const transactionChanges = { taxCode, + ...(taxAmount && {taxAmount}), }; const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, optimisticReportActionID, transactionChanges, policy, policyTagList, policyCategories, true); API.write('UpdateMoneyRequestTaxRate', params, onyxData); From 228c47705cc4a06d8d0a343be222e8e952523039 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 18 Apr 2024 14:36:36 +0100 Subject: [PATCH 023/502] should optimistically update tax amount when updating tax rate --- .../iou/request/step/IOURequestStepTaxRatePage.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx b/src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx index 3e14610652df..55d43370c477 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx +++ b/src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx @@ -68,6 +68,12 @@ function IOURequestStepTaxRatePage({ : transactionTaxCode && TransactionUtils.getTaxName(taxRates.taxes, transactionTaxCode)); const updateTaxRates = (taxes: OptionsListUtils.TaxRatesOption) => { + if (!transaction || !taxes.text || !taxRates) { + Navigation.goBack(backTo); + return; + } + const taxAmount = getTaxAmount(taxRates, taxes.text, TransactionUtils.getAmount(transaction, false, true)); + if (isEditing) { const newTaxCode = taxes.data.code; if (newTaxCode === undefined || newTaxCode === TransactionUtils.getTaxCode(transaction)) { @@ -78,6 +84,7 @@ function IOURequestStepTaxRatePage({ transactionID: transaction?.transactionID ?? '', optimisticReportActionID: report?.reportID ?? '', taxCode: newTaxCode, + taxAmount: CurrencyUtils.convertToBackendAmount(taxAmount ?? 0), policy, policyTagList: policyTags, policyCategories, @@ -85,11 +92,7 @@ function IOURequestStepTaxRatePage({ navigateBack(); return; } - if (!transaction || !taxes.text || !taxRates) { - Navigation.goBack(backTo); - return; - } - const taxAmount = getTaxAmount(taxRates, taxes.text, transaction?.amount); + if (taxAmount === undefined) { Navigation.goBack(backTo); return; From a0ac9bac20da8c89b5a5f2e9bbaee1e314e7bb49 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 18 Apr 2024 14:39:33 +0100 Subject: [PATCH 024/502] fix lint --- src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx b/src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx index 55d43370c477..c310e88dc928 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx +++ b/src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx @@ -73,7 +73,7 @@ function IOURequestStepTaxRatePage({ return; } const taxAmount = getTaxAmount(taxRates, taxes.text, TransactionUtils.getAmount(transaction, false, true)); - + if (isEditing) { const newTaxCode = taxes.data.code; if (newTaxCode === undefined || newTaxCode === TransactionUtils.getTaxCode(transaction)) { From 0999bf7371971d8c50f9f39a9e03dc25023a2bea Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Thu, 18 Apr 2024 18:48:35 +0200 Subject: [PATCH 025/502] feat: rename terms and feex, fix styling, create temporary test route --- src/ROUTES.ts | 2 + src/SCREENS.ts | 2 + .../ModalStackNavigators/index.tsx | 2 + src/libs/Navigation/linkingConfig/config.ts | 5 +++ .../FeesAndTerms.tsx} | 8 ++-- .../FeesAndTerms/substeps/FeesStep.tsx | 37 +++++++++++++++++++ .../substeps/TermsStep.tsx | 32 ++++++++-------- .../TermsAndFees/substeps/FeesStep.tsx | 24 ------------ .../TermsPage/ShortTermsForm.tsx | 16 ++++---- src/styles/index.ts | 5 ++- 10 files changed, 80 insertions(+), 53 deletions(-) rename src/pages/EnablePayments/{TermsAndFees/TermsAndFees.tsx => FeesAndTerms/FeesAndTerms.tsx} (93%) create mode 100644 src/pages/EnablePayments/FeesAndTerms/substeps/FeesStep.tsx rename src/pages/EnablePayments/{TermsAndFees => FeesAndTerms}/substeps/TermsStep.tsx (79%) delete mode 100644 src/pages/EnablePayments/TermsAndFees/substeps/FeesStep.tsx diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 46f2e2fef049..2ed8be54f408 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -119,6 +119,8 @@ const ROUTES = { SETTINGS_ADD_BANK_ACCOUNT: 'settings/wallet/add-bank-account', SETTINGS_ADD_BANK_ACCOUNT_REFACTOR: 'settings/wallet/add-bank-account-refactor', SETTINGS_ENABLE_PAYMENTS: 'settings/wallet/enable-payments', + // TODO: Added temporarily for testing purposes, remove after refactor - https://github.com/Expensify/App/issues/36648 + SETTINGS_ENABLE_PAYMENTS_TEMPORARY_TERMS: 'settings/wallet/enable-payments-temporary-terms', SETTINGS_WALLET_CARD_DIGITAL_DETAILS_UPDATE_ADDRESS: { route: 'settings/wallet/card/:domain/digital-details/update-address', getRoute: (domain: string) => `settings/wallet/card/${domain}/digital-details/update-address` as const, diff --git a/src/SCREENS.ts b/src/SCREENS.ts index acbb4b507b65..cf5723c43d31 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -84,6 +84,8 @@ const SCREENS = { TRANSFER_BALANCE: 'Settings_Wallet_Transfer_Balance', CHOOSE_TRANSFER_ACCOUNT: 'Settings_Wallet_Choose_Transfer_Account', ENABLE_PAYMENTS: 'Settings_Wallet_EnablePayments', + // TODO: Added temporarily for testing purposes, remove after refactor - https://github.com/Expensify/App/issues/36648 + ENABLE_PAYMENTS_TEMPORARY_TERMS: 'Settings_Wallet_EnablePayments_Temporary_Terms', CARD_ACTIVATE: 'Settings_Wallet_Card_Activate', REPORT_VIRTUAL_CARD_FRAUD: 'Settings_Wallet_ReportVirtualCardFraud', CARDS_DIGITAL_DETAILS_UPDATE_ADDRESS: 'Settings_Wallet_Cards_Digital_Details_Update_Address', diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index a596acf0a3ac..711e911fe9f1 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -215,6 +215,8 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/settings/Wallet/TransferBalancePage').default as React.ComponentType, [SCREENS.SETTINGS.WALLET.CHOOSE_TRANSFER_ACCOUNT]: () => require('../../../../pages/settings/Wallet/ChooseTransferAccountPage').default as React.ComponentType, [SCREENS.SETTINGS.WALLET.ENABLE_PAYMENTS]: () => require('../../../../pages/EnablePayments/EnablePaymentsPage').default as React.ComponentType, + // TODO: Added temporarily for testing purposes, remove after refactor - https://github.com/Expensify/App/issues/36648 + [SCREENS.SETTINGS.WALLET.ENABLE_PAYMENTS_TEMPORARY_TERMS]: () => require('../../../../pages/EnablePayments/FeesAndTerms/FeesAndTerms').default as React.ComponentType, [SCREENS.SETTINGS.ADD_DEBIT_CARD]: () => require('../../../../pages/settings/Wallet/AddDebitCardPage').default as React.ComponentType, [SCREENS.SETTINGS.ADD_BANK_ACCOUNT]: () => require('../../../../pages/AddPersonalBankAccountPage').default as React.ComponentType, [SCREENS.SETTINGS.ADD_BANK_ACCOUNT_REFACTOR]: () => require('../../../../pages/EnablePayments/AddBankAccount/AddBankAccount').default as React.ComponentType, diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 05b7190fa181..c19ce019a621 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -156,6 +156,11 @@ const config: LinkingOptions['config'] = { path: ROUTES.SETTINGS_ENABLE_PAYMENTS, exact: true, }, + // TODO: Added temporarily for testing purposes, remove after refactor - https://github.com/Expensify/App/issues/36648 + [SCREENS.SETTINGS.WALLET.ENABLE_PAYMENTS_TEMPORARY_TERMS]: { + path: ROUTES.SETTINGS_ENABLE_PAYMENTS_TEMPORARY_TERMS, + exact: true, + }, [SCREENS.SETTINGS.WALLET.TRANSFER_BALANCE]: { path: ROUTES.SETTINGS_WALLET_TRANSFER_BALANCE, exact: true, diff --git a/src/pages/EnablePayments/TermsAndFees/TermsAndFees.tsx b/src/pages/EnablePayments/FeesAndTerms/FeesAndTerms.tsx similarity index 93% rename from src/pages/EnablePayments/TermsAndFees/TermsAndFees.tsx rename to src/pages/EnablePayments/FeesAndTerms/FeesAndTerms.tsx index 7e26f652efe8..76955e860f13 100644 --- a/src/pages/EnablePayments/TermsAndFees/TermsAndFees.tsx +++ b/src/pages/EnablePayments/FeesAndTerms/FeesAndTerms.tsx @@ -13,7 +13,7 @@ import TermsStep from './substeps/TermsStep'; const termsAndFeesSubsteps: Array> = [FeesStep, TermsStep]; -function TermsAndFees() { +function FeesAndTerms() { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -29,7 +29,7 @@ function TermsAndFees() { return ( + {translate('termsStep.takeALookAtSomeFees')} + + + +