Repository: Expensify/App
Pull request #60352: Add unreportedExpense to report page
Author: login: sumo-slonik
Created: 2025-04-16T15:15:47Z | Merged: 2025-05-08T18:28:25Z

<!-- If necessary, assign reviewers that know the area or changes well. Feel free to tag any additional reviewers you see fit. -->

### Explanation of Change
Added the ability to move unreported expenses to existing reports according to the design doc. For now, the view is only accessible via a direct link, as header buttons are not yet available on main. Recordings are from internal web environments only.

### Fixed Issues
$ https://github.com/Expensify/App/issues/57655
PROPOSAL:



### Tests
1. **Create an expense for yourself**  
   Manually create a new expense entry where you are both the payer and the receiver.

2. **Create a report**  
   Generate a new report to ensure existing expenses are reported and separated from unreported ones.

3. **Use a direct link to access the unreported expenses tab**  
   Append `/add-unreported-expense` to the report URL to directly navigate to the "Unreported Expenses" tab, even if there’s no header button yet.

4. **Visit the link again and validate the behavior**  
- Open the same link again.
- Check if an **empty state** is shown for unreported expenses.
- Verify that the **"Add Expense"** button works correctly from this view.

- [X] Verify that no errors appear in the JS console

### Offline tests
Unnesesary

### QA Steps
Same as test

- [x] Verify that no errors appear in the JS console

### PR Author Checklist
<!--
This is a checklist for PR authors. Please make sure to complete all tasks and check them off once you do, or else your PR will not be merged!
-->

- [x] I linked the correct issue in the `### Fixed Issues` section above
- [x] I wrote clear testing steps that cover the changes made in this PR
    - [x] I added steps for local testing in the `Tests` section
    - [x] I added steps for the expected offline behavior in the `Offline steps` section
    - [x] I added steps for Staging and/or Production testing in the `QA steps` section
    - [x] I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    - [x] I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    - [x] I tested this PR with a [High Traffic account](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#high-traffic-accounts) against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
- [x] I included screenshots or videos for tests on [all platforms](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#make-sure-you-can-test-on-all-platforms)
- [x] I ran the tests on **all platforms** & verified they passed on:
    - [x] Android: Native
    - [x] Android: mWeb Chrome
    - [x] iOS: Native
    - [x] iOS: mWeb Safari
    - [x] MacOS: Chrome / Safari
    - [x] MacOS: Desktop
- [x] I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
- [x] I followed proper code patterns (see [Reviewing the code](https://github.com/Expensify/App/blob/main/contributingGuides/PR_REVIEW_GUIDELINES.md#reviewing-the-code))
    - [x] I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. `toggleReport` and not `onIconClick`)
    - [x] I verified that comments were added to code that is not self explanatory
    - [x] I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    - [x] I verified any copy / text shown in the product is localized by adding it to `src/languages/*` files and using the [translation method](https://github.com/Expensify/App/blob/4bd99402cebdf4d7394e0d1f260879ea238197eb/src/components/withLocalize.js#L60)
      - [x] If any non-english text was added/modified, I used [JaimeGPT](https://chatgpt.com/g/g-2dgOQl5VM-english-to-spanish-translator-aka-jaimegpt) to get English > Spanish translation. I then posted it in #expensify-open-source and it was approved by an internal Expensify engineer. Link to Slack message:
    - [x] I verified all numbers, amounts, dates and phone numbers shown in the product are using the [localization methods](https://github.com/Expensify/App/blob/4bd99402cebdf4d7394e0d1f260879ea238197eb/src/components/withLocalize.js#L60-L68)
    - [x] I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
    - [x] I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    - [x] I verified the JSDocs style guidelines (in [`STYLE.md`](https://github.com/Expensify/App/blob/main/contributingGuides/STYLE.md#jsdocs)) were followed
- [x] If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
- [x] I followed the guidelines as stated in the [Review Guidelines](https://github.com/Expensify/App/blob/main/contributingGuides/PR_REVIEW_GUIDELINES.md)
- [x] I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like `Avatar`, I verified the components using `Avatar` are working as expected)
- [x] I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
- [x] I verified any variables that can be defined as constants (ie. in CONST.ts or at the top of the file that uses the constant) are defined as such
- [x] I verified that if a function's arguments changed that all usages have also been updated correctly
- [x] If any new file was added I verified that:
    - [x] The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
- [x] If a new CSS style is added I verified that:
    - [x] A similar style doesn't already exist
    - [x] The style can't be created with an existing [StyleUtils](https://github.com/Expensify/App/blob/main/src/styles/utils/index.ts) function (i.e. `StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)`)
- [x] If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
- [x] If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like `Avatar` is modified, I verified that `Avatar` is working as expected in all cases)
- [x] If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
- [x] If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
- [x] If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    - [x] I verified that all the inputs inside a form are aligned with each other.
    - [x] I added `Design` label and/or tagged `@Expensify/design` so the design team can review the changes.
- [x] If a new page is added, I verified it's using the `ScrollView` component to make it scrollable when more elements are added to the page.
- [x] I added [unit tests](https://github.com/Expensify/App/blob/main/tests/README.md) for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
- [x] If the `main` branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the `Test` steps.

### Screenshots/Videos
<details>
<summary>Android: Native</summary>

<!-- add screenshots or videos here -->

</details>

<details>
<summary>Android: mWeb Chrome</summary>

https://github.com/user-attachments/assets/fe5169e9-d0a7-40ec-b121-cba2cc878dae



</details>

<details>
<summary>iOS: Native</summary>

<!-- add screenshots or videos here -->

</details>

<details>
<summary>iOS: mWeb Safari</summary>

https://github.com/user-attachments/assets/f3e444b8-369c-4672-91e4-3872f7a43d09

</details>

<details>
<summary>MacOS: Chrome / Safari</summary>


https://github.com/user-attachments/assets/a480c5eb-2a98-47da-868c-14253e43a0b5


</details>

<details>
<summary>MacOS: Desktop</summary>

<!-- add screenshots or videos here -->

</details>



Diff:
diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index 24a7bb40ec64..200c701593d4 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -2401,6 +2401,10 @@ const ROUTES = {
         route: 'settings/workspaces/:policyID/accounting/sage-intacct/advanced/payment-account',
         getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/sage-intacct/advanced/payment-account` as const,
     },
+    ADD_UNREPORTED_EXPENSE: {
+        route: 'search/r/:reportID/add-unreported-expense',
+        getRoute: (reportID: string | undefined) => `search/r/${reportID}/add-unreported-expense` as const,
+    },
     DEBUG_REPORT: {
         route: 'debug/report/:reportID',
         getRoute: (reportID: string | undefined) => `debug/report/${reportID}` as const,
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index 59e3996cd55c..0b9854a47f6d 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -215,6 +215,7 @@ const SCREENS = {
         REPORT_EXPORT: 'Report_Export',
         MISSING_PERSONAL_DETAILS: 'MissingPersonalDetails',
         DEBUG: 'Debug',
+        ADD_UNREPORTED_EXPENSE: 'AddUnreportedExpense',
         SCHEDULE_CALL: 'ScheduleCall',
     },
     PUBLIC_CONSOLE_DEBUG: 'Console_Debug',
@@ -708,6 +709,7 @@ const SCREENS = {
     FEATURE_TRAINING_ROOT: 'FeatureTraining_Root',
     RESTRICTED_ACTION_ROOT: 'RestrictedAction_Root',
     MISSING_PERSONAL_DETAILS_ROOT: 'MissingPersonalDetails_Root',
+    ADD_UNREPORTED_EXPENSES_ROOT: 'AddUnreportedExpenses_Root',
     DEBUG: {
         REPORT: 'Debug_Report',
         REPORT_ACTION: 'Debug_Report_Action',
diff --git a/src/components/EmptyStateComponent/index.tsx b/src/components/EmptyStateComponent/index.tsx
index 8af68e3cd440..609f36b26e95 100644
--- a/src/components/EmptyStateComponent/index.tsx
+++ b/src/components/EmptyStateComponent/index.tsx
@@ -102,8 +102,8 @@ function EmptyStateComponent({
                         <Text style={[styles.textAlignCenter, styles.textSupporting, styles.textNormal]}>{subtitle}</Text>
                         {children}
                         {!isEmpty(buttons) && (
-                            <View style={[styles.gap2, styles.mt5, !shouldUseNarrowLayout ? styles.flexRow : undefined]}>
-                                {buttons?.map(({buttonText, buttonAction, success, icon, isDisabled}) => (
+                            <View style={[styles.gap2, styles.mt5, !shouldUseNarrowLayout ? styles.flexRow : styles.mhAuto]}>
+                                {buttons?.map(({buttonText, buttonAction, success, icon, isDisabled, style}) => (
                                     <Button
                                         success={success}
                                         onPress={buttonAction}
@@ -111,7 +111,7 @@ function EmptyStateComponent({
                                         icon={icon}
                                         large
                                         isDisabled={isDisabled}
-                                        style={styles.flex1}
+                                        style={[styles.flex1, style]}
                                     />
                                 ))}
                             </View>
diff --git a/src/components/EmptyStateComponent/types.ts b/src/components/EmptyStateComponent/types.ts
index a07277566376..a238201c34f6 100644
--- a/src/components/EmptyStateComponent/types.ts
+++ b/src/components/EmptyStateComponent/types.ts
@@ -9,7 +9,7 @@ import type IconAsset from '@src/types/utils/IconAsset';
 
 type ValidSkeletons = typeof SearchRowSkeleton | typeof TableRowSkeleton;
 type MediaTypes = ValueOf<typeof CONST.EMPTY_STATE_MEDIA>;
-type Button = {buttonText?: string; buttonAction?: () => void; success?: boolean; icon?: IconAsset; isDisabled?: boolean};
+type Button = {buttonText?: string; buttonAction?: () => void; success?: boolean; icon?: IconAsset; isDisabled?: boolean; style?: StyleProp<ViewStyle>};
 
 type SharedProps<T> = {
     SkeletonComponent?: ValidSkeletons;
diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts
index 957d5350feb3..aded0deb1d69 100644
--- a/src/components/SelectionList/types.ts
+++ b/src/components/SelectionList/types.ts
@@ -17,6 +17,7 @@ import type {AnimatedStyle} from 'react-native-reanimated';
 import type {SearchRouterItem} from '@components/Search/SearchAutocompleteList';
 import type {SearchColumnType} from '@components/Search/types';
 import type {BrickRoad} from '@libs/WorkspacesSettingsUtils';
+import type UnreportedExpenseListItem from '@pages/UnreportedExpenseListItem';
 import type SpendCategorySelectorListItem from '@pages/workspace/categories/SpendCategorySelectorListItem';
 // eslint-disable-next-line no-restricted-imports
 import type CursorStyles from '@styles/utils/cursor/types';
@@ -26,6 +27,7 @@ import type {Attendee} from '@src/types/onyx/IOU';
 import type {Errors, Icon, PendingAction} from '@src/types/onyx/OnyxCommon';
 import type {SearchPersonalDetails, SearchReport, SearchReportAction, SearchTask, SearchTransaction} from '@src/types/onyx/SearchResults';
 import type {ReceiptErrors} from '@src/types/onyx/Transaction';
+import type Transaction from '@src/types/onyx/Transaction';
 import type ChildrenProps from '@src/types/utils/ChildrenProps';
 import type IconAsset from '@src/types/utils/IconAsset';
 import type ChatListItem from './ChatListItem';
@@ -383,6 +385,8 @@ type UserListItemProps<TItem extends ListItem> = ListItemProps<TItem> & {
     FooterComponent?: ReactElement;
 };
 
+type TransactionSelectionListItem<TItem extends ListItem> = ListItemProps<TItem> & Transaction;
+
 type InviteMemberListItemProps<TItem extends ListItem> = UserListItemProps<TItem>;
 
 type RadioListItemProps<TItem extends ListItem> = ListItemProps<TItem>;
@@ -422,6 +426,7 @@ type ValidListItem =
     | typeof SearchQueryListItem
     | typeof SearchRouterItem
     | typeof TravelDomainListItem
+    | typeof UnreportedExpenseListItem
     | typeof SpendCategorySelectorListItem;
 
 type Section<TItem extends ListItem> = {
@@ -776,6 +781,7 @@ export type {
     FlattenedSectionsReturn,
     InviteMemberListItemProps,
     ListItem,
+    ListItemProps,
     ListItemFocusEventHandler,
     RadioListItemProps,
     ReportListItemProps,
@@ -789,6 +795,7 @@ export type {
     TaskListItemProps,
     TransactionListItemProps,
     TransactionListItemType,
+    TransactionSelectionListItem,
     UserListItemProps,
     ReportActionListItemType,
     ChatListItemProps,
diff --git a/src/components/TransactionItemRow/index.tsx b/src/components/TransactionItemRow/index.tsx
index af2a28f995a3..c2371212769c 100644
--- a/src/components/TransactionItemRow/index.tsx
+++ b/src/components/TransactionItemRow/index.tsx
@@ -11,7 +11,7 @@ import useHover from '@hooks/useHover';
 import useStyleUtils from '@hooks/useStyleUtils';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
-import {getCreated as getTransactionCreated} from '@libs/TransactionUtils';
+import {getMerchant, getCreated as getTransactionCreated, isPartialMerchant} from '@libs/TransactionUtils';
 import variables from '@styles/variables';
 import CONST from '@src/CONST';
 import CategoryCell from './DataCells/CategoryCell';
@@ -26,21 +26,21 @@ import TransactionItemRowRBR from './TransactionItemRowRBR';
 function TransactionItemRow({
     transactionItem,
     shouldUseNarrowLayout,
-    shouldShowCheckbox,
     isSelected,
     shouldShowTooltip,
     dateColumnSize,
     shouldShowChatBubbleComponent = false,
     onCheckboxPress,
+    shouldShowCheckbox = false,
 }: {
     transactionItem: TransactionWithOptionalHighlight;
     shouldUseNarrowLayout: boolean;
-    shouldShowCheckbox: boolean;
     isSelected: boolean;
     shouldShowTooltip: boolean;
     dateColumnSize: TableColumnSize;
     shouldShowChatBubbleComponent?: boolean;
     onCheckboxPress: (transactionID: string) => void;
+    shouldShowCheckbox: boolean;
 }) {
     const styles = useThemeStyles();
     const StyleUtils = useStyleUtils();
@@ -69,6 +69,9 @@ function TransactionItemRow({
         }
     }, [hovered, isSelected, styles.activeComponentBG, styles.hoveredComponentBG]);
 
+    const merchantName = getMerchant(transactionItem);
+    const isMerchantEmpty = isPartialMerchant(merchantName);
+
     return (
         <View
             style={[styles.flex1]}
@@ -80,7 +83,7 @@ function TransactionItemRow({
                     <View style={[styles.expenseWidgetRadius, styles.justifyContentEvenly, styles.gap3, bgActiveStyles]}>
                         <View style={[styles.flexRow, styles.mt3, styles.mr3, styles.ml3]}>
                             {shouldShowCheckbox && (
-                                <View style={[styles.mr2, styles.justifyContentCenter]}>
+                                <View style={[styles.mr3, styles.justifyContentCenter]}>
                                     <Checkbox
                                         onPress={() => {
                                             onCheckboxPress(transactionItem.transactionID);
@@ -109,19 +112,30 @@ function TransactionItemRow({
                                         shouldShowTooltip={shouldShowTooltip}
                                         shouldUseNarrowLayout={shouldUseNarrowLayout}
                                     />
+                                    {isMerchantEmpty && (
+                                        <View style={[styles.mlAuto]}>
+                                            <TotalCell
+                                                transactionItem={transactionItem}
+                                                shouldShowTooltip={shouldShowTooltip}
+                                                shouldUseNarrowLayout={shouldUseNarrowLayout}
+                                            />
+                                        </View>
+                                    )}
                                 </View>
-                                <View style={[styles.flexRow, styles.alignItemsCenter, styles.justifyContentBetween, styles.gap2]}>
-                                    <MerchantCell
-                                        transactionItem={transactionItem}
-                                        shouldShowTooltip={shouldShowTooltip}
-                                        shouldUseNarrowLayout={shouldUseNarrowLayout}
-                                    />
-                                    <TotalCell
-                                        transactionItem={transactionItem}
-                                        shouldShowTooltip={shouldShowTooltip}
-                                        shouldUseNarrowLayout={shouldUseNarrowLayout}
-                                    />
-                                </View>
+                                {!isMerchantEmpty && (
+                                    <View style={[styles.flexRow, styles.alignItemsCenter, styles.justifyContentBetween, styles.gap2]}>
+                                        <MerchantCell
+                                            transactionItem={transactionItem}
+                                            shouldShowTooltip={shouldShowTooltip}
+                                            shouldUseNarrowLayout={shouldUseNarrowLayout}
+                                        />
+                                        <TotalCell
+                                            transactionItem={transactionItem}
+                                            shouldShowTooltip={shouldShowTooltip}
+                                            shouldUseNarrowLayout={shouldUseNarrowLayout}
+                                        />
+                                    </View>
+                                )}
                             </View>
                         </View>
                         <View style={[styles.flexRow, styles.justifyContentBetween, styles.mh3, styles.mb3]}>
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 76578a27d305..017546fd8192 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -1117,6 +1117,12 @@ const translations = {
         unholdExpense: 'Unhold expense',
         heldExpense: 'held this expense',
         unheldExpense: 'unheld this expense',
+        moveUnreportedExpense: 'Move unreported expense',
+        addUnreportedExpense: 'Add unreported expense',
+        selectUnreportedExpense: 'Select at least one expense to add to the report.',
+        emptyStateUnreportedExpenseTitle: 'No unreported expenses',
+        emptyStateUnreportedExpenseSubtitle: 'Looks like you don’t have any unreported expenses. Try creating one below.',
+        addUnreportedExpenseConfirm: 'Add to report',
         explainHold: "Explain why you're holding this expense.",
         reason: 'Reason',
         holdReasonRequired: 'A reason is required when holding.',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 5f36bd39562e..ba3baabce599 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1111,6 +1111,12 @@ const translations = {
         enableWallet: 'Habilitar billetera',
         holdExpense: 'Retener gasto',
         unholdExpense: 'Desbloquear gasto',
+        moveUnreportedExpense: 'Mover gasto no reportado',
+        addUnreportedExpense: 'Añadir gasto no reportado',
+        selectUnreportedExpense: 'Selecciona al menos un gasto para agregar al informe.',
+        emptyStateUnreportedExpenseTitle: 'No hay gastos no reportados',
+        emptyStateUnreportedExpenseSubtitle: 'Parece que no tienes gastos no reportados. Puedes crear uno a continuación.',
+        addUnreportedExpenseConfirm: 'Añadir al informe',
         heldExpense: 'retuvo este gasto',
         unheldExpense: 'desbloqueó este gasto',
         explainHold: 'Explica la razón para retener esta solicitud.',
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index 1dbed4da5e13..bd13b29b1dd4 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -4,6 +4,7 @@ import createPlatformStackNavigator from '@libs/Navigation/PlatformStackNavigati
 import Animations from '@libs/Navigation/PlatformStackNavigation/navigationOptions/animation';
 import type {
     AddPersonalBankAccountNavigatorParamList,
+    AddUnreportedExpensesParamList,
     ConsoleNavigatorParamList,
     DebugParamList,
     EditRequestNavigatorParamList,
@@ -743,6 +744,10 @@ const MissingPersonalDetailsModalStackNavigator = createModalStackNavigator<Miss
     [SCREENS.MISSING_PERSONAL_DETAILS_ROOT]: () => require<ReactComponentModule>('../../../../pages/MissingPersonalDetails').default,
 });
 
+const AddUnreportedExpenseModalStackNavigator = createModalStackNavigator<AddUnreportedExpensesParamList>({
+    [SCREENS.ADD_UNREPORTED_EXPENSES_ROOT]: () => require<ReactComponentModule>('../../../../pages/AddUnreportedExpense').default,
+});
+
 const DebugModalStackNavigator = createModalStackNavigator<DebugParamList>({
     [SCREENS.DEBUG.REPORT]: () => require<ReactComponentModule>('../../../../pages/Debug/Report/DebugReportPage').default,
     [SCREENS.DEBUG.REPORT_ACTION]: () => require<ReactComponentModule>('../../../../pages/Debug/ReportAction/DebugReportActionPage').default,
@@ -799,5 +804,6 @@ export {
     DebugModalStackNavigator,
     WorkspaceConfirmationModalStackNavigator,
     ConsoleModalStackNavigator,
+    AddUnreportedExpenseModalStackNavigator,
     ScheduleCallModalStackNavigator,
 };
diff --git a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx
index dcc95d0b534b..cd90a58bfed5 100644
--- a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx
+++ b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx
@@ -219,6 +219,10 @@ function RightModalNavigator({navigation, route}: RightModalNavigatorProps) {
                         name={SCREENS.RIGHT_MODAL.MISSING_PERSONAL_DETAILS}
                         component={ModalStackNavigators.MissingPersonalDetailsModalStackNavigator}
                     />
+                    <Stack.Screen
+                        name={SCREENS.RIGHT_MODAL.ADD_UNREPORTED_EXPENSE}
+                        component={ModalStackNavigators.AddUnreportedExpenseModalStackNavigator}
+                    />
                     <Stack.Screen
                         name={SCREENS.RIGHT_MODAL.SCHEDULE_CALL}
                         component={ModalStackNavigators.ScheduleCallModalStackNavigator}
diff --git a/src/libs/Navigation/helpers/getAdaptedStateFromPath.ts b/src/libs/Navigation/helpers/getAdaptedStateFromPath.ts
index 777690653683..c97f04e1113f 100644
--- a/src/libs/Navigation/helpers/getAdaptedStateFromPath.ts
+++ b/src/libs/Navigation/helpers/getAdaptedStateFromPath.ts
@@ -6,7 +6,7 @@ import type {OnyxCollection} from 'react-native-onyx';
 import {isAnonymousUser} from '@libs/actions/Session';
 import getInitialSplitNavigatorState from '@libs/Navigation/AppNavigator/createSplitNavigator/getInitialSplitNavigatorState';
 import {config} from '@libs/Navigation/linkingConfig/config';
-import {RHP_TO_SETTINGS, RHP_TO_SIDEBAR, RHP_TO_WORKSPACE, SEARCH_TO_RHP} from '@libs/Navigation/linkingConfig/RELATIONS';
+import {RHP_TO_SEARCH, RHP_TO_SETTINGS, RHP_TO_SIDEBAR, RHP_TO_WORKSPACE} from '@libs/Navigation/linkingConfig/RELATIONS';
 import type {NavigationPartialRoute, RootNavigatorParamList} from '@libs/Navigation/types';
 import {extractPolicyIDFromPath, getPathWithoutPolicyID} from '@libs/PolicyUtils';
 import NAVIGATORS from '@src/NAVIGATORS';
@@ -69,12 +69,15 @@ function getMatchingFullScreenRoute(route: NavigationPartialRoute, policyID?: st
         return getMatchingFullScreenRoute(focusedStateForBackToRoute, policyID);
     }
 
-    if (SEARCH_TO_RHP.includes(route.name)) {
-        const paramsFromRoute = getParamsFromRoute(SCREENS.SEARCH.ROOT);
-
+    if (RHP_TO_SEARCH[route.name]) {
+        const paramsFromRoute = getParamsFromRoute(RHP_TO_SEARCH[route.name]);
+        const searchRoute = {
+            name: RHP_TO_SEARCH[route.name],
+            params: paramsFromRoute.length > 0 ? pick(route.params, paramsFromRoute) : undefined,
+        };
         return {
             name: NAVIGATORS.SEARCH_FULLSCREEN_NAVIGATOR,
-            params: paramsFromRoute.length > 0 ? pick(route.params, paramsFromRoute) : undefined,
+            state: getRoutesWithIndex([searchRoute]),
         };
     }
 
diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/SEARCH_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/SEARCH_TO_RHP.ts
index e24abcb8a7e6..047c7f01cc9b 100644
--- a/src/libs/Navigation/linkingConfig/RELATIONS/SEARCH_TO_RHP.ts
+++ b/src/libs/Navigation/linkingConfig/RELATIONS/SEARCH_TO_RHP.ts
@@ -1,37 +1,41 @@
+import type {SearchFullscreenNavigatorParamList} from '@navigation/types';
 import SCREENS from '@src/SCREENS';
 
 // This file is used to define RHP screens that are in relation to the search screen.
-const SEARCH_TO_RHP: string[] = [
-    SCREENS.SEARCH.REPORT_RHP,
-    SCREENS.SEARCH.TRANSACTION_HOLD_REASON_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_CURRENCY_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_DATE_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_SUBMITTED_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_APPROVED_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_PAID_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_EXPORTED_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_POSTED_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_DESCRIPTION_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_MERCHANT_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_REPORT_ID_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_AMOUNT_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_CATEGORY_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_KEYWORD_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_TAX_RATE_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_EXPENSE_TYPE_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_TAG_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_FROM_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_TO_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_IN_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_WORKSPACE_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_CARD_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_TITLE_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_ASSIGNEE_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_CREATED_BY_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_REIMBURSABLE_RHP,
-    SCREENS.SEARCH.ADVANCED_FILTERS_BILLABLE_RHP,
-    SCREENS.SEARCH.SAVED_SEARCH_RENAME_RHP,
-];
+const SEARCH_TO_RHP: Partial<Record<keyof SearchFullscreenNavigatorParamList, string[]>> = {
+    [SCREENS.SEARCH.ROOT]: [
+        SCREENS.SEARCH.REPORT_RHP,
+        SCREENS.SEARCH.TRANSACTION_HOLD_REASON_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_CURRENCY_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_DATE_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_SUBMITTED_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_APPROVED_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_PAID_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_EXPORTED_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_POSTED_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_DESCRIPTION_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_MERCHANT_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_REPORT_ID_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_AMOUNT_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_CATEGORY_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_KEYWORD_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_TAX_RATE_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_EXPENSE_TYPE_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_TAG_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_FROM_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_TO_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_IN_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_WORKSPACE_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_CARD_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_TITLE_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_ASSIGNEE_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_CREATED_BY_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_REIMBURSABLE_RHP,
+        SCREENS.SEARCH.ADVANCED_FILTERS_BILLABLE_RHP,
+        SCREENS.SEARCH.SAVED_SEARCH_RENAME_RHP,
+    ],
+    [SCREENS.SEARCH.MONEY_REQUEST_REPORT]: [SCREENS.ADD_UNREPORTED_EXPENSES_ROOT],
+};
 
 export default SEARCH_TO_RHP;
diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/SETTINGS_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/SETTINGS_TO_RHP.ts
index 1fa5705ab3bc..f2945bf375c5 100755
--- a/src/libs/Navigation/linkingConfig/RELATIONS/SETTINGS_TO_RHP.ts
+++ b/src/libs/Navigation/linkingConfig/RELATIONS/SETTINGS_TO_RHP.ts
@@ -2,7 +2,7 @@ import type {SettingsSplitNavigatorParamList} from '@libs/Navigation/types';
 import SCREENS from '@src/SCREENS';
 
 // This file is used to define relation between settings split navigator's central screens and RHP screens.
-const CENTRAL_PANE_TO_RHP_MAPPING: Partial<Record<keyof SettingsSplitNavigatorParamList, string[]>> = {
+const SETTINGS_TO_RHP: Partial<Record<keyof SettingsSplitNavigatorParamList, string[]>> = {
     [SCREENS.SETTINGS.PROFILE.ROOT]: [
         SCREENS.SETTINGS.PROFILE.DISPLAY_NAME,
         SCREENS.SETTINGS.PROFILE.CONTACT_METHODS,
@@ -70,4 +70,4 @@ const CENTRAL_PANE_TO_RHP_MAPPING: Partial<Record<keyof SettingsSplitNavigatorPa
     ],
 };
 
-export default CENTRAL_PANE_TO_RHP_MAPPING;
+export default SETTINGS_TO_RHP;
diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/index.ts b/src/libs/Navigation/linkingConfig/RELATIONS/index.ts
index 3f779ba351a1..aa726661daf9 100644
--- a/src/libs/Navigation/linkingConfig/RELATIONS/index.ts
+++ b/src/libs/Navigation/linkingConfig/RELATIONS/index.ts
@@ -21,5 +21,18 @@ const RHP_TO_SETTINGS = createInverseRelation(SETTINGS_TO_RHP);
 const RHP_TO_WORKSPACE = createInverseRelation(WORKSPACE_TO_RHP);
 const RHP_TO_SIDEBAR = createInverseRelation(SIDEBAR_TO_RHP);
 const SPLIT_TO_SIDEBAR = createInverseRelation(SIDEBAR_TO_SPLIT);
+const RHP_TO_SEARCH = createInverseRelation(SEARCH_TO_RHP);
 
-export {SETTINGS_TO_RHP, RHP_TO_SETTINGS, RHP_TO_WORKSPACE, RHP_TO_SIDEBAR, SEARCH_TO_RHP, SIDEBAR_TO_RHP, WORKSPACE_TO_RHP, SIDEBAR_TO_SPLIT, SPLIT_TO_SIDEBAR, FULLSCREEN_TO_TAB};
+export {
+    SETTINGS_TO_RHP,
+    RHP_TO_SETTINGS,
+    RHP_TO_WORKSPACE,
+    RHP_TO_SIDEBAR,
+    RHP_TO_SEARCH,
+    SEARCH_TO_RHP,
+    SIDEBAR_TO_RHP,
+    WORKSPACE_TO_RHP,
+    SIDEBAR_TO_SPLIT,
+    SPLIT_TO_SIDEBAR,
+    FULLSCREEN_TO_TAB,
+};
diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts
index 9f24045bb6f4..0cac176d7737 100644
--- a/src/libs/Navigation/linkingConfig/config.ts
+++ b/src/libs/Navigation/linkingConfig/config.ts
@@ -1502,6 +1502,11 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
                         [SCREENS.MISSING_PERSONAL_DETAILS_ROOT]: ROUTES.MISSING_PERSONAL_DETAILS,
                     },
                 },
+                [SCREENS.RIGHT_MODAL.ADD_UNREPORTED_EXPENSE]: {
+                    screens: {
+                        [SCREENS.ADD_UNREPORTED_EXPENSES_ROOT]: ROUTES.ADD_UNREPORTED_EXPENSE.route,
+                    },
+                },
                 [SCREENS.RIGHT_MODAL.DEBUG]: {
                     screens: {
                         [SCREENS.DEBUG.REPORT]: {
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index 8e0415879be3..4f6a23a93f94 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -1594,6 +1594,7 @@ type RightModalNavigatorParamList = {
     [SCREENS.RIGHT_MODAL.SEARCH_SAVED_SEARCH]: NavigatorScreenParams<SearchSavedSearchParamList>;
     [SCREENS.RIGHT_MODAL.MISSING_PERSONAL_DETAILS]: NavigatorScreenParams<MissingPersonalDetailsParamList>;
     [SCREENS.RIGHT_MODAL.DEBUG]: NavigatorScreenParams<DebugParamList>;
+    [SCREENS.RIGHT_MODAL.ADD_UNREPORTED_EXPENSE]: NavigatorScreenParams<{reportId: string | undefined}>;
     [SCREENS.RIGHT_MODAL.SCHEDULE_CALL]: NavigatorScreenParams<ScheduleCallParamList>;
 };
 
@@ -1961,6 +1962,12 @@ type MissingPersonalDetailsParamList = {
     [SCREENS.MISSING_PERSONAL_DETAILS_ROOT]: undefined;
 };
 
+type AddUnreportedExpensesParamList = {
+    [SCREENS.ADD_UNREPORTED_EXPENSES_ROOT]: {
+        reportID: string;
+    };
+};
+
 type DebugParamList = {
     [SCREENS.DEBUG.REPORT]: {
         reportID: string;
@@ -2029,6 +2036,7 @@ declare global {
 
 export type {
     AddPersonalBankAccountNavigatorParamList,
+    AddUnreportedExpensesParamList,
     AuthScreensParamList,
     BackToParams,
     DebugParamList,
diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts
index 14ee250ca5f4..59c29ab6b803 100644
--- a/src/libs/actions/Report.ts
+++ b/src/libs/actions/Report.ts
@@ -466,6 +466,13 @@ function getReportChannelName(reportID: string): string {
     return `${CONST.PUSHER.PRIVATE_REPORT_CHANNEL_PREFIX}${reportID}${CONFIG.PUSHER.SUFFIX}`;
 }
 
+function openUnreportedExpense(reportID: string | undefined) {
+    if (!reportID) {
+        return;
+    }
+    Navigation.navigate(ROUTES.ADD_UNREPORTED_EXPENSE.getRoute(reportID));
+}
+
 /**
  * There are 2 possibilities that we can receive via pusher for a user's typing/leaving status:
  * 1. The "new" way from New Expensify is passed as {[login]: Boolean} (e.g. {yuwen@expensify.com: true}), where the value
@@ -5316,4 +5323,5 @@ export {
     dismissChangePolicyModal,
     changeReportPolicy,
     removeFailedReport,
+    openUnreportedExpense,
 };
diff --git a/src/libs/actions/Transaction.ts b/src/libs/actions/Transaction.ts
index df3c2561e1c8..ee5d0b118f9f 100644
--- a/src/libs/actions/Transaction.ts
+++ b/src/libs/actions/Transaction.ts
@@ -593,7 +593,7 @@ function changeTransactionsReport(transactionIDs: string[], reportID: string) {
 
     transactions.forEach((transaction) => {
         const oldIOUAction = getIOUActionForReportID(transaction.reportID, transaction.transactionID);
-        if (!oldIOUAction?.reportActionID || !transaction.reportID) {
+        if (!transaction.reportID) {
             return;
         }
 
@@ -628,16 +628,25 @@ function changeTransactionsReport(transactionIDs: string[], reportID: string) {
 
         // 3. Optimistically update the IOU action reportID
         const optimisticMoneyRequestReportActionID = rand64();
-        const newIOUAction = {...oldIOUAction, reportActionID: optimisticMoneyRequestReportActionID, pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD};
-        optimisticData.push(
-            {
+
+        const newIOUAction = {
+            ...oldIOUAction,
+            reportActionID: optimisticMoneyRequestReportActionID,
+            pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
+            actionName: oldIOUAction?.actionName ?? CONST.REPORT.ACTIONS.TYPE.MOVED_TRANSACTION,
+            created: oldIOUAction?.created ?? DateUtils.getDBTime(),
+        };
+
+        if (oldIOUAction) {
+            optimisticData.push({
                 onyxMethod: Onyx.METHOD.MERGE,
                 key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`,
                 value: {
                     [newIOUAction.reportActionID]: newIOUAction,
                 },
-            },
-            {
+            });
+
+            optimisticData.push({
                 onyxMethod: Onyx.METHOD.MERGE,
                 key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${oldReportID}`,
                 value: {
@@ -655,8 +664,8 @@ function changeTransactionsReport(transactionIDs: string[], reportID: string) {
                         ],
                     },
                 },
-            },
-        );
+            });
+        }
 
         successData.push({
             onyxMethod: Onyx.METHOD.MERGE,
@@ -665,21 +674,22 @@ function changeTransactionsReport(transactionIDs: string[], reportID: string) {
                 [newIOUAction.reportActionID]: {pendingAction: null},
             },
         });
-
-        failureData.push(
-            {
-                onyxMethod: Onyx.METHOD.MERGE,
-                key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`,
-                value: {
-                    [newIOUAction.reportActionID]: null,
+        if (oldIOUAction) {
+            failureData.push(
+                {
+                    onyxMethod: Onyx.METHOD.MERGE,
+                    key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`,
+                    value: {
+                        [newIOUAction.reportActionID]: null,
+                    },
                 },
-            },
-            {
-                onyxMethod: Onyx.METHOD.MERGE,
-                key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${oldReportID}`,
-                value: {[oldIOUAction.reportActionID]: oldIOUAction},
-            },
-        );
+                {
+                    onyxMethod: Onyx.METHOD.MERGE,
+                    key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${oldReportID}`,
+                    value: {[oldIOUAction.reportActionID]: oldIOUAction},
+                },
+            );
+        }
 
         // 4. Optimistically update the transaction thread and all threads in the transaction thread
         optimisticData.push({
@@ -692,15 +702,17 @@ function changeTransactionsReport(transactionIDs: string[], reportID: string) {
             },
         });
 
-        failureData.push({
-            onyxMethod: Onyx.METHOD.MERGE,
-            key: `${ONYXKEYS.COLLECTION.REPORT}${oldIOUAction.childReportID}`,
-            value: {
-                parentReportID: oldReportID,
-                optimisticMoneyRequestReportActionID: oldIOUAction.reportActionID,
-                policyID: allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${oldReportID}`]?.policyID,
-            },
-        });
+        if (oldIOUAction) {
+            failureData.push({
+                onyxMethod: Onyx.METHOD.MERGE,
+                key: `${ONYXKEYS.COLLECTION.REPORT}${oldIOUAction.childReportID}`,
+                value: {
+                    parentReportID: oldReportID,
+                    optimisticMoneyRequestReportActionID: oldIOUAction.reportActionID,
+                    policyID: allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${oldReportID}`]?.policyID,
+                },
+            });
+        }
 
         // 5. (Optional) Create transactionThread if it doesn't exist
         let transactionThreadReportID = newIOUAction.childReportID;
@@ -789,12 +801,12 @@ function changeTransactionsReport(transactionIDs: string[], reportID: string) {
         transactionIDToReportActionAndThreadData[transaction.transactionID] = {
             movedReportActionID: movedAction.reportActionID,
             moneyRequestPreviewReportActionID: newIOUAction.reportActionID,
-            ...(oldIOUAction.childReportID
-                ? {}
-                : {
+            ...(oldIOUAction && !oldIOUAction.childReportID
+                ? {
                       transactionThreadReportID,
                       transactionThreadCreatedReportActionID,
-                  }),
+                  }
+                : {}),
         };
     });
 
diff --git a/src/pages/AddUnreportedExpense.tsx b/src/pages/AddUnreportedExpense.tsx
new file mode 100644
index 000000000000..ab31dee0b35b
--- /dev/null
+++ b/src/pages/AddUnreportedExpense.tsx
@@ -0,0 +1,145 @@
+import React, {useRef, useState} from 'react';
+import {useOnyx} from 'react-native-onyx';
+import type {OnyxCollection} from 'react-native-onyx';
+import EmptyStateComponent from '@components/EmptyStateComponent';
+import FormHelpMessage from '@components/FormHelpMessage';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import LottieAnimations from '@components/LottieAnimations';
+import ScreenWrapper from '@components/ScreenWrapper';
+import SelectionList from '@components/SelectionList';
+import type {ListItem, SectionListDataType, SelectionListHandle} from '@components/SelectionList/types';
+import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
+import interceptAnonymousUser from '@libs/interceptAnonymousUser';
+import Navigation from '@navigation/Navigation';
+import type {PlatformStackScreenProps} from '@navigation/PlatformStackNavigation/types';
+import {startMoneyRequest} from '@userActions/IOU';
+import {changeTransactionsReport} from '@userActions/Transaction';
+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/Transaction';
+import NewChatSelectorPage from './NewChatSelectorPage';
+import UnreportedExpenseListItem from './UnreportedExpenseListItem';
+
+type AddUnreportedExpensePageType = PlatformStackScreenProps<AddUnreportedExpensesParamList, typeof SCREENS.ADD_UNREPORTED_EXPENSES_ROOT>;
+
+type AddUnreportedExpensesParamList = {
+    [SCREENS.ADD_UNREPORTED_EXPENSES_ROOT]: {
+        reportID: string;
+    };
+};
+
+function AddUnreportedExpense({route}: AddUnreportedExpensePageType) {
+    const {translate} = useLocalize();
+    const [errorMessage, setErrorMessage] = useState<string>('');
+
+    function getUnreportedTransactions(transactions: OnyxCollection<Transaction>) {
+        if (!transactions) {
+            return [];
+        }
+        return Object.values(transactions || {}).filter((item) => item?.reportID === '0');
+    }
+
+    const [transactions = []] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {
+        selector: (_transactions) => getUnreportedTransactions(_transactions),
+        initialValue: [],
+        canBeMissing: true,
+    });
+
+    const styles = useThemeStyles();
+    const selectionListRef = useRef<SelectionListHandle>(null);
+    const sections: Array<SectionListDataType<Transaction & ListItem>> = [
+        {
+            shouldShow: true,
+            data: transactions.filter((t): t is Transaction & ListItem => t !== undefined),
+        },
+    ];
+
+    const thereIsNoUnreportedTransaction = !((sections.at(0)?.data.length ?? 0) > 0);
+
+    const reportID = route.params.reportID;
+    const selectedIds = new Set<string>();
+    const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {canBeMissing: true});
+    return (
+        <ScreenWrapper
+            shouldEnableKeyboardAvoidingView={false}
+            includeSafeAreaPaddingBottom
+            shouldShowOfflineIndicator={false}
+            shouldEnablePickerAvoiding={false}
+            testID={NewChatSelectorPage.displayName}
+            focusTrapSettings={{active: false}}
+        >
+            <HeaderWithBackButton
+                title={translate('iou.addUnreportedExpense')}
+                onBackButtonPress={Navigation.goBack}
+            />
+
+            {thereIsNoUnreportedTransaction ? (
+                <EmptyStateComponent
+                    cardStyles={[styles.appBG]}
+                    cardContentStyles={[styles.pt5, styles.pb0]}
+                    headerMediaType={CONST.EMPTY_STATE_MEDIA.ANIMATION}
+                    headerMedia={LottieAnimations.GenericEmptyState}
+                    title={translate('iou.emptyStateUnreportedExpenseTitle')}
+                    subtitle={translate('iou.emptyStateUnreportedExpenseSubtitle')}
+                    headerStyles={[styles.emptyStateMoneyRequestReport]}
+                    lottieWebViewStyles={styles.emptyStateFolderWebStyles}
+                    headerContentStyles={styles.emptyStateFolderWebStyles}
+                    buttons={[
+                        {
+                            buttonText: translate('iou.createExpense'),
+                            buttonAction: () => {
+                                interceptAnonymousUser(() => {
+                                    startMoneyRequest(CONST.IOU.TYPE.SUBMIT, reportID);
+                                });
+                            },
+                            success: true,
+                            style: styles.unreportedExpenseCreateExpenseButton,
+                        },
+                    ]}
+                />
+            ) : (
+                <SelectionList<Transaction & ListItem>
+                    ref={selectionListRef}
+                    onSelectRow={(item) => {
+                        if (selectedIds.has(item.transactionID)) {
+                            selectedIds.delete(item.transactionID);
+                        } else {
+                            selectedIds.add(item.transactionID);
+                        }
+                    }}
+                    shouldShowTextInput={false}
+                    canSelectMultiple
+                    sections={sections}
+                    ListItem={UnreportedExpenseListItem}
+                    confirmButtonStyles={[styles.justifyContentCenter]}
+                    showConfirmButton
+                    confirmButtonText={translate('iou.addUnreportedExpenseConfirm')}
+                    onConfirm={() => {
+                        if (selectedIds.size === 0) {
+                            setErrorMessage(translate('iou.selectUnreportedExpense'));
+                            return;
+                        }
+                        Navigation.goBack(ROUTES.SEARCH_MONEY_REQUEST_REPORT.getRoute({reportID, backTo: Navigation.getActiveRoute()}));
+                        changeTransactionsReport([...selectedIds], report?.reportID ?? CONST.REPORT.UNREPORTED_REPORT_ID);
+                        setErrorMessage('');
+                    }}
+                >
+                    {!!errorMessage && (
+                        <FormHelpMessage
+                            style={[styles.mb2, styles.ph4]}
+                            isError
+                            message={errorMessage}
+                        />
+                    )}
+                </SelectionList>
+            )}
+        </ScreenWrapper>
+    );
+}
+
+AddUnreportedExpense.displayName = 'AddUnreportedExpense';
+
+export default AddUnreportedExpense;
diff --git a/src/pages/UnreportedExpenseListItem.tsx b/src/pages/UnreportedExpenseListItem.tsx
new file mode 100644
index 000000000000..d4e0c0a77ceb
--- /dev/null
+++ b/src/pages/UnreportedExpenseListItem.tsx
@@ -0,0 +1,64 @@
+import React, {useState} from 'react';
+import {View} from 'react-native';
+import BaseListItem from '@components/SelectionList/BaseListItem';
+import type {ListItem, ListItemProps, TransactionListItemType} from '@components/SelectionList/types';
+import TransactionItemRow from '@components/TransactionItemRow';
+import useAnimatedHighlightStyle from '@hooks/useAnimatedHighlightStyle';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import variables from '@styles/variables';
+
+function UnreportedExpenseListItem<TItem extends ListItem>({item, isFocused, showTooltip, isDisabled, canSelectMultiple, onFocus, shouldSyncFocus, onSelectRow}: ListItemProps<TItem>) {
+    const styles = useThemeStyles();
+    const transactionItem = item as unknown as TransactionListItemType;
+    const [isSelected, setIsSelected] = useState<boolean>(false);
+    const theme = useTheme();
+    const backgroundColor = isSelected ? styles.buttonDefaultBG : styles.highlightBG;
+
+    const hoveredTransactionStyles = useAnimatedHighlightStyle({
+        borderRadius: variables.componentBorderRadius,
+        shouldHighlight: item?.shouldAnimateInHighlight ?? false,
+        highlightColor: theme.messageHighlightBG,
+        backgroundColor: theme.highlightBG,
+    });
+
+    return (
+        <BaseListItem
+            item={item}
+            isFocused={isFocused}
+            isDisabled={isDisabled}
+            showTooltip={showTooltip}
+            canSelectMultiple={canSelectMultiple}
+            pendingAction={item.pendingAction}
+            keyForList={item.keyForList}
+            onFocus={onFocus}
+            shouldSyncFocus={shouldSyncFocus}
+            pressableWrapperStyle={[hoveredTransactionStyles, backgroundColor]}
+            onSelectRow={() => {
+                onSelectRow(item);
+                setIsSelected((val) => !val);
+            }}
+            containerStyle={[styles.p3, styles.mbn4, styles.expenseWidgetRadius]}
+            hoverStyle={[styles.borderRadiusComponentNormal]}
+        >
+            <View style={[styles.flexRow, styles.alignItemsCenter, styles.justifyContentBetween]}>
+                <TransactionItemRow
+                    transactionItem={transactionItem}
+                    shouldUseNarrowLayout
+                    isSelected={isSelected}
+                    shouldShowTooltip={false}
+                    dateColumnSize="normal"
+                    onCheckboxPress={() => {
+                        onSelectRow(item);
+                        setIsSelected((val) => !val);
+                    }}
+                    shouldShowCheckbox
+                />
+            </View>
+        </BaseListItem>
+    );
+}
+
+UnreportedExpenseListItem.displayName = 'UnreportedExpenseListItem';
+
+export default UnreportedExpenseListItem;
diff --git a/src/pages/home/report/PureReportActionItem.tsx b/src/pages/home/report/PureReportActionItem.tsx
index e4b2ee3f9967..b9df0269d1d1 100644
--- a/src/pages/home/report/PureReportActionItem.tsx
+++ b/src/pages/home/report/PureReportActionItem.tsx
@@ -1272,7 +1272,6 @@ function PureReportActionItem({
 
         return <ReportActionItemGrouped wrapperStyle={isWhisper ? styles.pt1 : {}}>{content}</ReportActionItemGrouped>;
     };
-
     if (action.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED) {
         const transactionID = isMoneyRequestAction(parentReportActionForTransactionThread) ? getOriginalMessage(parentReportActionForTransactionThread)?.IOUTransactionID : undefined;
 
diff --git a/src/pages/home/report/ReportActionItemContentCreated.tsx b/src/pages/home/report/ReportActionItemContentCreated.tsx
index 3a04b18b6d89..a5229be89a4b 100644
--- a/src/pages/home/report/ReportActionItemContentCreated.tsx
+++ b/src/pages/home/report/ReportActionItemContentCreated.tsx
@@ -48,7 +48,6 @@ function ReportActionItemContentCreated({contextValue, parentReportAction, trans
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const {report, action, transactionThreadReport} = contextValue;
-
     const policy = usePolicy(report?.policyID === CONST.POLICY.OWNER_EMAIL_FAKE ? undefined : report?.policyID);
     const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {canBeMissing: true});
 
diff --git a/src/pages/home/report/ReportActionsList.tsx b/src/pages/home/report/ReportActionsList.tsx
index 232475018355..5eb0306a3b7c 100644
--- a/src/pages/home/report/ReportActionsList.tsx
+++ b/src/pages/home/report/ReportActionsList.tsx
@@ -584,28 +584,30 @@ function ReportActionsList({
     }, [isFocused, isVisible]);
 
     const renderItem = useCallback(
-        ({item: reportAction, index}: ListRenderItemInfo<OnyxTypes.ReportAction>) => (
-            <ReportActionsListItemRenderer
-                reportAction={reportAction}
-                reportActions={sortedReportActions}
-                parentReportAction={parentReportAction}
-                parentReportActionForTransactionThread={parentReportActionForTransactionThread}
-                index={index}
-                report={report}
-                transactionThreadReport={transactionThreadReport}
-                linkedReportActionID={linkedReportActionID}
-                displayAsGroup={
-                    !isConsecutiveChronosAutomaticTimerAction(sortedVisibleReportActions, index, chatIncludesChronosWithID(reportAction?.reportID)) &&
-                    isConsecutiveActionMadeByPreviousActor(sortedVisibleReportActions, index)
-                }
-                mostRecentIOUReportActionID={mostRecentIOUReportActionID}
-                shouldHideThreadDividerLine={shouldHideThreadDividerLine}
-                shouldDisplayNewMarker={reportAction.reportActionID === unreadMarkerReportActionID}
-                shouldDisplayReplyDivider={sortedVisibleReportActions.length > 1}
-                isFirstVisibleReportAction={firstVisibleReportActionID === reportAction.reportActionID}
-                shouldUseThreadDividerLine={shouldUseThreadDividerLine}
-            />
-        ),
+        ({item: reportAction, index}: ListRenderItemInfo<OnyxTypes.ReportAction>) => {
+            return (
+                <ReportActionsListItemRenderer
+                    reportAction={reportAction}
+                    reportActions={sortedReportActions}
+                    parentReportAction={parentReportAction}
+                    parentReportActionForTransactionThread={parentReportActionForTransactionThread}
+                    index={index}
+                    report={report}
+                    transactionThreadReport={transactionThreadReport}
+                    linkedReportActionID={linkedReportActionID}
+                    displayAsGroup={
+                        !isConsecutiveChronosAutomaticTimerAction(sortedVisibleReportActions, index, chatIncludesChronosWithID(reportAction?.reportID)) &&
+                        isConsecutiveActionMadeByPreviousActor(sortedVisibleReportActions, index)
+                    }
+                    mostRecentIOUReportActionID={mostRecentIOUReportActionID}
+                    shouldHideThreadDividerLine={shouldHideThreadDividerLine}
+                    shouldDisplayNewMarker={reportAction.reportActionID === unreadMarkerReportActionID}
+                    shouldDisplayReplyDivider={sortedVisibleReportActions.length > 1}
+                    isFirstVisibleReportAction={firstVisibleReportActionID === reportAction.reportActionID}
+                    shouldUseThreadDividerLine={shouldUseThreadDividerLine}
+                />
+            );
+        },
         [
             report,
             linkedReportActionID,
diff --git a/src/stories/TransactionItemRow.stories.tsx b/src/stories/TransactionItemRow.stories.tsx
index 98bf6d767847..195d353d79d6 100644
--- a/src/stories/TransactionItemRow.stories.tsx
+++ b/src/stories/TransactionItemRow.stories.tsx
@@ -26,6 +26,7 @@ const story: Meta<typeof TransactionItemRow> = {
         shouldUseNarrowLayout: false,
         isSelected: false,
         shouldShowTooltip: true,
+        shouldShowCheckbox: true,
     },
     argTypes: {
         transactionItem: {
@@ -62,12 +63,12 @@ function Template(
                     <TransactionItemRow
                         transactionItem={transactionItem}
                         shouldUseNarrowLayout={shouldUseNarrowLayout}
-                        shouldShowCheckbox={shouldShowCheckbox}
                         isSelected={isSelected}
                         shouldShowTooltip={shouldShowTooltip}
                         shouldShowChatBubbleComponent
                         dateColumnSize={CONST.SEARCH.TABLE_COLUMN_SIZES.NORMAL}
                         onCheckboxPress={() => {}}
+                        shouldShowCheckbox={shouldShowCheckbox}
                     />
                 </ThemeStylesProvider>
             </ScreenWrapper>
diff --git a/src/styles/index.ts b/src/styles/index.ts
index 0f443b6a4916..f33299465ff8 100644
--- a/src/styles/index.ts
+++ b/src/styles/index.ts
@@ -860,6 +860,10 @@ const styles = (theme: ThemeColors) =>
             backgroundColor: theme.hoverComponentBG,
         },
 
+        hoveredComponentBG2: {
+            backgroundColor: 'black',
+        },
+
         activeComponentBG: {
             backgroundColor: theme.activeComponentBG,
         },
@@ -5720,6 +5724,10 @@ const styles = (theme: ThemeColors) =>
             borderTopRightRadius: variables.componentBorderRadiusLarge,
         },
 
+        unreportedExpenseCreateExpenseButton: {
+            ...flex.alignSelfStart,
+        },
+
         testDriveBannerGap: {
             height: CONST.DESKTOP_HEADER_PADDING * 2,
         },
diff --git a/src/styles/utils/spacing.ts b/src/styles/utils/spacing.ts
index ff0d1c8f4d4a..47c4f733a472 100644
--- a/src/styles/utils/spacing.ts
+++ b/src/styles/utils/spacing.ts
@@ -31,6 +31,10 @@ export default {
         margin: 20,
     },
 
+    mhAuto: {
+        marginHorizontal: 'auto',
+    },
+
     mh0: {
         marginHorizontal: 0,
     },
@@ -175,6 +179,10 @@ export default {
         marginLeft: 8,
     },
 
+    mln2: {
+        marginLeft: -12,
+    },
+
     ml3: {
         marginLeft: 12,
     },
@@ -755,6 +763,10 @@ export default {
         minHeight: 20,
     },
 
+    minHeight22: {
+        minHeight: 88,
+    },
+
     minHeight65: {
         minHeight: 260,
     },


Reviews:
user: login: SzymczakJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T11:00:49Z
user: login: sumo-slonik
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T14:51:41Z
user: login: allgandalf
body: Partial review below, will complete the remaining part tomorrow 
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T14:31:34Z
user: login: sumo-slonik
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-30T09:23:26Z
user: login: sumo-slonik
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-30T09:27:55Z
user: login: sumo-slonik
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-30T09:29:33Z
user: login: sumo-slonik
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-30T09:31:10Z
user: login: sumo-slonik
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-30T09:31:21Z
user: login: sumo-slonik
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-30T09:33:39Z
user: login: sumo-slonik
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-30T09:35:21Z
user: login: sumo-slonik
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-30T09:36:02Z
user: login: sumo-slonik
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-30T09:38:52Z
user: login: sumo-slonik
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-30T12:03:47Z
user: login: luacmartins
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-01T20:23:36Z
user: login: sumo-slonik
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-05T12:20:03Z
user: login: sumo-slonik
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-05T12:20:10Z
user: login: sumo-slonik
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-05T12:20:50Z
user: login: sumo-slonik
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-05T12:20:59Z
user: login: luacmartins
body: Nice! Tests well. Just missing conflicts resolution
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-05-05T18:21:37Z
user: login: luacmartins
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T08:47:19Z
user: login: allgandalf
body: Code wise LGTM, tests well, so if we fix the ^ bugs, this is good to merge !
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T16:37:08Z
user: login: mountiny
body: Couple small comments to address @sumo-slonik 
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T16:38:13Z
user: login: allgandalf
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-08T18:09:32Z
user: login: luacmartins
body: LGTM
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-08T18:25:50Z
user: login: mountiny
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-08T18:28:03Z
user: login: ikevin127
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-06-21T01:02:03Z
user: login: ikevin127
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-07-02T23:46:43Z
user: login: parasharrajat
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-08-27T10:23:14Z
user: login: rojiphil
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2026-02-20T05:33:40Z

Review comments:
diff_hunk: @@ -0,0 +1,78 @@
+import React, {useState} from 'react';
+import {View} from 'react-native';
+import type {ViewStyle} from 'react-native';
+import SelectCircle from '@components/SelectCircle';
+import BaseListItem from '@components/SelectionList/BaseListItem';
+import type {ListItem, ListItemProps} from '@components/SelectionList/types';
+import TransactionItemRow from '@components/TransactionItemRow';
+import useAnimatedHighlightStyle from '@hooks/useAnimatedHighlightStyle';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import variables from '@styles/variables';
+import type Transaction from '@src/types/onyx/Transaction';
+
+const emptyStylesArray: ViewStyle[] = [];
+
+function UnreportedExpenseListItem<TItem extends ListItem & Transaction>({
+    item,
+    isFocused,
+    showTooltip,
+    isDisabled,
+    canSelectMultiple,
+    onFocus,
+    shouldSyncFocus,
+    onSelectRow,
+}: ListItemProps<TItem>) {
+    const styles = useThemeStyles();
+    const [isSelected, setIsSelected] = useState<boolean>(false);
+    const theme = useTheme();
+
+    const backgroundColor = isSelected ? styles.buttonDefaultBG : styles.highlightBG;
+
+    const animatedHighlightStyle = useAnimatedHighlightStyle({
+        borderRadius: variables.componentBorderRadius,
+        shouldHighlight: item?.shouldAnimateInHighlight ?? false,
+        highlightColor: theme.messageHighlightBG,
+        backgroundColor: theme.highlightBG,
+    });
path: src/pages/UnreportedExpenseListItem.tsx
user: login: SzymczakJ
body: This hook is used for highlighting items that pop up on Search page, while the user is focused on it. Since we don't suppport highlighting new items on AddUnreportedExpense page(i hope :D), I think we can just remove this hook from here.
```suggestion
```
created_at: 2025-04-18T09:28:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,78 @@
+import React, {useState} from 'react';
+import {View} from 'react-native';
+import type {ViewStyle} from 'react-native';
+import SelectCircle from '@components/SelectCircle';
+import BaseListItem from '@components/SelectionList/BaseListItem';
+import type {ListItem, ListItemProps} from '@components/SelectionList/types';
+import TransactionItemRow from '@components/TransactionItemRow';
+import useAnimatedHighlightStyle from '@hooks/useAnimatedHighlightStyle';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import variables from '@styles/variables';
+import type Transaction from '@src/types/onyx/Transaction';
+
+const emptyStylesArray: ViewStyle[] = [];
+
+function UnreportedExpenseListItem<TItem extends ListItem & Transaction>({
+    item,
+    isFocused,
+    showTooltip,
+    isDisabled,
+    canSelectMultiple,
+    onFocus,
+    shouldSyncFocus,
+    onSelectRow,
+}: ListItemProps<TItem>) {
+    const styles = useThemeStyles();
+    const [isSelected, setIsSelected] = useState<boolean>(false);
+    const theme = useTheme();
+
+    const backgroundColor = isSelected ? styles.buttonDefaultBG : styles.highlightBG;
+
+    const animatedHighlightStyle = useAnimatedHighlightStyle({
+        borderRadius: variables.componentBorderRadius,
+        shouldHighlight: item?.shouldAnimateInHighlight ?? false,
+        highlightColor: theme.messageHighlightBG,
+        backgroundColor: theme.highlightBG,
+    });
path: src/pages/UnreportedExpenseListItem.tsx
user: login: sumo-slonik
body: This is used as the style of the currently selected components by an external checkbox.

created_at: 2025-04-18T14:51:40Z
author_association: CONTRIBUTOR
diff_hunk: @@ -102,16 +102,16 @@ function EmptyStateComponent({
                         <Text style={[styles.textAlignCenter, styles.textSupporting, styles.textNormal]}>{subtitle}</Text>
                         {children}
                         {!isEmpty(buttons) && (
-                            <View style={[styles.gap2, styles.mt5, !shouldUseNarrowLayout ? styles.flexRow : undefined]}>
-                                {buttons?.map(({buttonText, buttonAction, success, icon, isDisabled}) => (
+                            <View style={[styles.gap2, styles.mt5, !shouldUseNarrowLayout ? styles.flexRow : styles.mhAuto]}>
+                                {buttons?.map(({buttonText, buttonAction, success, icon, isDisabled, style}) => (
                                     <Button
                                         success={success}
                                         onPress={buttonAction}
                                         text={buttonText}
                                         icon={icon}
                                         large
                                         isDisabled={isDisabled}
-                                        style={styles.flex1}
+                                        style={[styles.flex1, style]}
path: src/components/EmptyStateComponent/index.tsx
user: login: allgandalf
body: what is this `style` used for here? where does it come from, can we name it in a better way?
created_at: 2025-04-29T14:21:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -229,6 +229,7 @@ function MoneyRequestReportTransactionList({report, transactions, reportActions,
                                 shouldUseNarrowLayout={displayNarrowVersion}
                                 shouldShowChatBubbleComponent
                                 onCheckboxPress={toggleTransaction}
+                                shouldShowCheckBox
path: src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx
user: login: allgandalf
body: did you check the effect of this being always true on small screens?
created_at: 2025-04-29T14:22:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -27,6 +29,8 @@ function TransactionItemRow({
     dateColumnSize,
     shouldShowChatBubbleComponent = false,
     onCheckboxPress,
+    containerStyles,
+    shouldShowCheckBox = true,
path: src/components/TransactionItemRow/index.tsx
user: login: allgandalf
body: how about this being default false? NAB
created_at: 2025-04-29T14:22:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -46,24 +52,29 @@ function TransactionItemRow({
 
     const {selectionMode} = useMobileSelectionMode();
 
+    const merchantName = getMerchant(transactionItem);
+    const isMernchantEmpty = merchantName === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT;
path: src/components/TransactionItemRow/index.tsx
user: login: allgandalf
body: ```suggestion
    const isMerchantEmpty = merchantName === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT;
```
created_at: 2025-04-29T14:27:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -83,19 +94,30 @@ function TransactionItemRow({
                                             shouldShowTooltip={shouldShowTooltip}
                                             shouldUseNarrowLayout={shouldUseNarrowLayout}
                                         />
+                                        {isMernchantEmpty && (
path: src/components/TransactionItemRow/index.tsx
user: login: allgandalf
body: ```suggestion
                                        {isMerchantEmpty && (
```
created_at: 2025-04-29T14:27:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -83,19 +94,30 @@ function TransactionItemRow({
                                             shouldShowTooltip={shouldShowTooltip}
                                             shouldUseNarrowLayout={shouldUseNarrowLayout}
                                         />
+                                        {isMernchantEmpty && (
+                                            <View style={[styles.mlAuto]}>
+                                                <TotalCell
+                                                    transactionItem={transactionItem}
+                                                    shouldShowTooltip={shouldShowTooltip}
+                                                    shouldUseNarrowLayout={shouldUseNarrowLayout}
+                                                />
+                                            </View>
+                                        )}
                                     </View>
-                                    <View style={[styles.flexRow, styles.alignItemsCenter, styles.justifyContentBetween, styles.gap2]}>
-                                        <MerchantCell
-                                            transactionItem={transactionItem}
-                                            shouldShowTooltip={shouldShowTooltip}
-                                            shouldUseNarrowLayout={shouldUseNarrowLayout}
-                                        />
-                                        <TotalCell
-                                            transactionItem={transactionItem}
-                                            shouldShowTooltip={shouldShowTooltip}
-                                            shouldUseNarrowLayout={shouldUseNarrowLayout}
-                                        />
-                                    </View>
+                                    {!isMernchantEmpty && (
path: src/components/TransactionItemRow/index.tsx
user: login: allgandalf
body: ```suggestion
                                    {!isMerchantEmpty && (
```
created_at: 2025-04-29T14:27:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1110,6 +1110,11 @@ const translations = {
         enableWallet: 'Habilitar billetera',
         holdExpense: 'Retener gasto',
         unholdExpense: 'Desbloquear gasto',
+        moveUnreportedExpense: 'Mover gasto no reportado',
+        addUnreportedExpense: 'Añadir gasto no reportado',
+        emptyStateUnreportedExpenseTitle: 'No hay gastos no reportados',
+        emptyStateUnreportedExpenseSubtitle: 'Parece que no tienes gastos no reportados. Puedes crear uno a continuación.',
+        addUnreportedExpenseConfirm: 'Añadir al informe',
path: src/languages/es.ts
user: login: allgandalf
body: are these translations verified ?
created_at: 2025-04-29T14:28:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -741,6 +742,10 @@ const MissingPersonalDetailsModalStackNavigator = createModalStackNavigator<Miss
     [SCREENS.MISSING_PERSONAL_DETAILS_ROOT]: () => require<ReactComponentModule>('../../../../pages/MissingPersonalDetails').default,
 });
 
+const AddingUnreportedExpenseModalStackNavigator = createModalStackNavigator<AddUnreportedExpensesParamList>({
path: src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
user: login: allgandalf
body: ```suggestion
const AddUnreportedExpenseModalStackNavigator = createModalStackNavigator<AddUnreportedExpensesParamList>({
```

This is better and consistent with how we name the ParamList
created_at: 2025-04-29T14:28:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,37 +1,41 @@
+import type {SearchFullscreenNavigatorParamList} from '@navigation/types';
 import SCREENS from '@src/SCREENS';
 
 // This file is used to define RHP screens that are in relation to the search screen.
-const SEARCH_TO_RHP: string[] = [
path: src/libs/Navigation/linkingConfig/RELATIONS/SEARCH_TO_RHP.ts
user: login: allgandalf
body: why is this a massive diff, we don't change order of things i think that should solve this diff
created_at: 2025-04-29T14:29:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2,7 +2,7 @@ import type {SettingsSplitNavigatorParamList} from '@libs/Navigation/types';
 import SCREENS from '@src/SCREENS';
 
 // This file is used to define relation between settings split navigator's central screens and RHP screens.
-const CENTRAL_PANE_TO_RHP_MAPPING: Partial<Record<keyof SettingsSplitNavigatorParamList, string[]>> = {
+const SETTINGS_TO_RHP: Partial<Record<keyof SettingsSplitNavigatorParamList, string[]>> = {
path: src/libs/Navigation/linkingConfig/RELATIONS/SETTINGS_TO_RHP.ts
user: login: allgandalf
body: why are we changing this name?
created_at: 2025-04-29T14:30:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -466,6 +466,14 @@ function getReportChannelName(reportID: string): string {
     return `${CONST.PUSHER.PRIVATE_REPORT_CHANNEL_PREFIX}${reportID}${CONFIG.PUSHER.SUFFIX}`;
 }
 
+function openUnreportedExpense(reportID: string | undefined) {
+    if (!reportID) {
+        return;
+    }
+    clearGroupChat();
path: src/libs/actions/Report.ts
user: login: allgandalf
body: why do we need to call this function before navigation ?
created_at: 2025-04-29T14:30:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2,7 +2,7 @@ import type {SettingsSplitNavigatorParamList} from '@libs/Navigation/types';
 import SCREENS from '@src/SCREENS';
 
 // This file is used to define relation between settings split navigator's central screens and RHP screens.
-const CENTRAL_PANE_TO_RHP_MAPPING: Partial<Record<keyof SettingsSplitNavigatorParamList, string[]>> = {
+const SETTINGS_TO_RHP: Partial<Record<keyof SettingsSplitNavigatorParamList, string[]>> = {
path: src/libs/Navigation/linkingConfig/RELATIONS/SETTINGS_TO_RHP.ts
user: login: sumo-slonik
body: I was making changes to the RHP configuration and consulted them with @WojtekBoman . He also asked me to change this name while I was at it.
created_at: 2025-04-30T09:23:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,37 +1,41 @@
+import type {SearchFullscreenNavigatorParamList} from '@navigation/types';
 import SCREENS from '@src/SCREENS';
 
 // This file is used to define RHP screens that are in relation to the search screen.
-const SEARCH_TO_RHP: string[] = [
path: src/libs/Navigation/linkingConfig/RELATIONS/SEARCH_TO_RHP.ts
user: login: sumo-slonik
body: To ensure that the correct report always appears under "RHP move unreported expense," I had to change the configuration of the array from 1D to 2D. That’s why the diff is so massive.
created_at: 2025-04-30T09:27:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -741,6 +742,10 @@ const MissingPersonalDetailsModalStackNavigator = createModalStackNavigator<Miss
     [SCREENS.MISSING_PERSONAL_DETAILS_ROOT]: () => require<ReactComponentModule>('../../../../pages/MissingPersonalDetails').default,
 });
 
+const AddingUnreportedExpenseModalStackNavigator = createModalStackNavigator<AddUnreportedExpensesParamList>({
path: src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
user: login: sumo-slonik
body: fixed
created_at: 2025-04-30T09:29:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -83,19 +94,30 @@ function TransactionItemRow({
                                             shouldShowTooltip={shouldShowTooltip}
                                             shouldUseNarrowLayout={shouldUseNarrowLayout}
                                         />
+                                        {isMernchantEmpty && (
path: src/components/TransactionItemRow/index.tsx
user: login: sumo-slonik
body: fixed
created_at: 2025-04-30T09:31:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -83,19 +94,30 @@ function TransactionItemRow({
                                             shouldShowTooltip={shouldShowTooltip}
                                             shouldUseNarrowLayout={shouldUseNarrowLayout}
                                         />
+                                        {isMernchantEmpty && (
+                                            <View style={[styles.mlAuto]}>
+                                                <TotalCell
+                                                    transactionItem={transactionItem}
+                                                    shouldShowTooltip={shouldShowTooltip}
+                                                    shouldUseNarrowLayout={shouldUseNarrowLayout}
+                                                />
+                                            </View>
+                                        )}
                                     </View>
-                                    <View style={[styles.flexRow, styles.alignItemsCenter, styles.justifyContentBetween, styles.gap2]}>
-                                        <MerchantCell
-                                            transactionItem={transactionItem}
-                                            shouldShowTooltip={shouldShowTooltip}
-                                            shouldUseNarrowLayout={shouldUseNarrowLayout}
-                                        />
-                                        <TotalCell
-                                            transactionItem={transactionItem}
-                                            shouldShowTooltip={shouldShowTooltip}
-                                            shouldUseNarrowLayout={shouldUseNarrowLayout}
-                                        />
-                                    </View>
+                                    {!isMernchantEmpty && (
path: src/components/TransactionItemRow/index.tsx
user: login: sumo-slonik
body: fixed
created_at: 2025-04-30T09:31:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -229,6 +229,7 @@ function MoneyRequestReportTransactionList({report, transactions, reportActions,
                                 shouldUseNarrowLayout={displayNarrowVersion}
                                 shouldShowChatBubbleComponent
                                 onCheckboxPress={toggleTransaction}
+                                shouldShowCheckBox
path: src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx
user: login: sumo-slonik
body: Following your suggestion, I changed the default value to false.
created_at: 2025-04-30T09:33:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -466,6 +466,14 @@ function getReportChannelName(reportID: string): string {
     return `${CONST.PUSHER.PRIVATE_REPORT_CHANNEL_PREFIX}${reportID}${CONFIG.PUSHER.SUFFIX}`;
 }
 
+function openUnreportedExpense(reportID: string | undefined) {
+    if (!reportID) {
+        return;
+    }
+    clearGroupChat();
path: src/libs/actions/Report.ts
user: login: sumo-slonik
body: it was unnecessary
created_at: 2025-04-30T09:35:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1110,6 +1110,11 @@ const translations = {
         enableWallet: 'Habilitar billetera',
         holdExpense: 'Retener gasto',
         unholdExpense: 'Desbloquear gasto',
+        moveUnreportedExpense: 'Mover gasto no reportado',
+        addUnreportedExpense: 'Añadir gasto no reportado',
+        emptyStateUnreportedExpenseTitle: 'No hay gastos no reportados',
+        emptyStateUnreportedExpenseSubtitle: 'Parece que no tienes gastos no reportados. Puedes crear uno a continuación.',
+        addUnreportedExpenseConfirm: 'Añadir al informe',
path: src/languages/es.ts
user: login: sumo-slonik
body: I’m confirming them now.


created_at: 2025-04-30T09:36:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -102,16 +102,16 @@ function EmptyStateComponent({
                         <Text style={[styles.textAlignCenter, styles.textSupporting, styles.textNormal]}>{subtitle}</Text>
                         {children}
                         {!isEmpty(buttons) && (
-                            <View style={[styles.gap2, styles.mt5, !shouldUseNarrowLayout ? styles.flexRow : undefined]}>
-                                {buttons?.map(({buttonText, buttonAction, success, icon, isDisabled}) => (
+                            <View style={[styles.gap2, styles.mt5, !shouldUseNarrowLayout ? styles.flexRow : styles.mhAuto]}>
+                                {buttons?.map(({buttonText, buttonAction, success, icon, isDisabled, style}) => (
                                     <Button
                                         success={success}
                                         onPress={buttonAction}
                                         text={buttonText}
                                         icon={icon}
                                         large
                                         isDisabled={isDisabled}
-                                        style={styles.flex1}
+                                        style={[styles.flex1, style]}
path: src/components/EmptyStateComponent/index.tsx
user: login: sumo-slonik
body: This is to support the style of the button that we are passing from the outside, in this case, to change the max width. I think the name "style" in the array containing the button properties is quite good, as naming it "button style" would be redundant.
created_at: 2025-04-30T09:38:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1110,6 +1110,11 @@ const translations = {
         enableWallet: 'Habilitar billetera',
         holdExpense: 'Retener gasto',
         unholdExpense: 'Desbloquear gasto',
+        moveUnreportedExpense: 'Mover gasto no reportado',
+        addUnreportedExpense: 'Añadir gasto no reportado',
+        emptyStateUnreportedExpenseTitle: 'No hay gastos no reportados',
+        emptyStateUnreportedExpenseSubtitle: 'Parece que no tienes gastos no reportados. Puedes crear uno a continuación.',
+        addUnreportedExpenseConfirm: 'Añadir al informe',
path: src/languages/es.ts
user: login: sumo-slonik
body: Confirmed.
created_at: 2025-04-30T12:03:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2390,6 +2390,10 @@ const ROUTES = {
         route: 'settings/workspaces/:policyID/accounting/sage-intacct/advanced/payment-account',
         getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/sage-intacct/advanced/payment-account` as const,
     },
+    ADD_UNREPORTED_EXPENSE: {
+        route: 'search/r/:reportID/AddUnreportedExpense',
+        getRoute: (reportID: string | undefined) => `search/r/${reportID}/AddUnreportedExpense` as const,
path: src/ROUTES.ts
user: login: luacmartins
body: Let's follow our convention for route names here
```suggestion
        getRoute: (reportID: string | undefined) => `search/r/${reportID}/add-unreported-expense` as const,
```
created_at: 2025-05-01T20:20:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -27,6 +29,8 @@ function TransactionItemRow({
     dateColumnSize,
     shouldShowChatBubbleComponent = false,
     onCheckboxPress,
+    containerStyles,
path: src/components/TransactionItemRow/index.tsx
user: login: luacmartins
body: Why do we need this? It seems like the only time we pass `containerStyles` it's an empty array
created_at: 2025-05-01T20:21:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -46,24 +52,29 @@ function TransactionItemRow({
 
     const {selectionMode} = useMobileSelectionMode();
 
+    const merchantName = getMerchant(transactionItem);
+    const isMerchantEmpty = merchantName === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT;
+
     return (
         <View style={styles.flex1}>
             {shouldUseNarrowLayout ? (
                 <Hoverable>
                     {(hovered) => (
-                        <View style={[hovered ? styles.hoveredComponentBG : backgroundColor, styles.expenseWidgetRadius, styles.justifyContentEvenly, styles.gap3]}>
+                        <View style={containerStyles ?? [hovered ? styles.hoveredComponentBG : backgroundColor, styles.p2, styles.expenseWidgetRadius]}>
+                            {' '}
path: src/components/TransactionItemRow/index.tsx
user: login: luacmartins
body: Why do we need this?
created_at: 2025-05-01T20:22:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,68 @@
+import React, {useState} from 'react';
+import {View} from 'react-native';
+import type {ViewStyle} from 'react-native';
+import BaseListItem from '@components/SelectionList/BaseListItem';
+import type {ListItem, ListItemProps, TransactionListItemType} from '@components/SelectionList/types';
+import TransactionItemRow from '@components/TransactionItemRow';
+import useAnimatedHighlightStyle from '@hooks/useAnimatedHighlightStyle';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import variables from '@styles/variables';
+
+const emptyStylesArray: ViewStyle[] = [];
path: src/pages/UnreportedExpenseListItem.tsx
user: login: luacmartins
body: Why do we need this empty style?
created_at: 2025-05-01T20:23:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,68 @@
+import React, {useState} from 'react';
+import {View} from 'react-native';
+import type {ViewStyle} from 'react-native';
+import BaseListItem from '@components/SelectionList/BaseListItem';
+import type {ListItem, ListItemProps, TransactionListItemType} from '@components/SelectionList/types';
+import TransactionItemRow from '@components/TransactionItemRow';
+import useAnimatedHighlightStyle from '@hooks/useAnimatedHighlightStyle';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import variables from '@styles/variables';
+
+const emptyStylesArray: ViewStyle[] = [];
+
+function UnreportedExpenseListItem<TItem extends ListItem>({item, isFocused, showTooltip, isDisabled, canSelectMultiple, onFocus, shouldSyncFocus, onSelectRow}: ListItemProps<TItem>) {
+    const styles = useThemeStyles();
+    const transactionItem = item as unknown as TransactionListItemType;
+    const [isSelected, setIsSelected] = useState<boolean>(false);
+    const theme = useTheme();
+    const backgroundColor = isSelected ? styles.buttonDefaultBG : styles.highlightBG;
+
+    const animatedHighlightStyle = useAnimatedHighlightStyle({
+        borderRadius: variables.componentBorderRadius,
+        shouldHighlight: item?.shouldAnimateInHighlight ?? false,
+        highlightColor: theme.messageHighlightBG,
+        backgroundColor: theme.highlightBG,
+    });
+
+    return (
+        <BaseListItem
+            item={item}
+            isFocused={isFocused}
+            isDisabled={isDisabled}
+            showTooltip={showTooltip}
+            canSelectMultiple={canSelectMultiple}
+            pendingAction={item.pendingAction}
+            keyForList={item.keyForList}
+            onFocus={onFocus}
+            shouldSyncFocus={shouldSyncFocus}
+            pressableWrapperStyle={[animatedHighlightStyle, backgroundColor]}
+            onSelectRow={() => {
+                onSelectRow(item);
+                setIsSelected((val) => !val);
+            }}
+            containerStyle={[styles.p3, styles.mbn4, styles.expenseWidgetRadius]}
+            hoverStyle={[styles.borderRadiusComponentNormal]}
+        >
+            <View style={[styles.flexRow, styles.alignItemsCenter, styles.justifyContentBetween]}>
+                <TransactionItemRow
+                    transactionItem={transactionItem}
+                    shouldUseNarrowLayout
+                    isSelected={isSelected}
+                    shouldShowTooltip={false}
+                    dateColumnSize="normal"
+                    onCheckboxPress={() => {
+                        onSelectRow(item);
+                        setIsSelected((val) => !val);
+                    }}
+                    containerStyles={emptyStylesArray}
+                    shouldShowCheckBox
+                />
+            </View>
+        </BaseListItem>
+    );
+}
+
+UnreportedExpenseListItem.displayName = 'unreportedExpenseListItem';
path: src/pages/UnreportedExpenseListItem.tsx
user: login: luacmartins
body: ```suggestion
UnreportedExpenseListItem.displayName = 'UnreportedExpenseListItem';
```
created_at: 2025-05-01T20:23:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,68 @@
+import React, {useState} from 'react';
+import {View} from 'react-native';
+import type {ViewStyle} from 'react-native';
+import BaseListItem from '@components/SelectionList/BaseListItem';
+import type {ListItem, ListItemProps, TransactionListItemType} from '@components/SelectionList/types';
+import TransactionItemRow from '@components/TransactionItemRow';
+import useAnimatedHighlightStyle from '@hooks/useAnimatedHighlightStyle';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import variables from '@styles/variables';
+
+const emptyStylesArray: ViewStyle[] = [];
path: src/pages/UnreportedExpenseListItem.tsx
user: login: sumo-slonik
body: These are remnants of the now-removed and no longer needed circle used for selecting a row on its right side.
created_at: 2025-05-05T12:20:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -46,24 +52,29 @@ function TransactionItemRow({
 
     const {selectionMode} = useMobileSelectionMode();
 
+    const merchantName = getMerchant(transactionItem);
+    const isMerchantEmpty = merchantName === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT;
+
     return (
         <View style={styles.flex1}>
             {shouldUseNarrowLayout ? (
                 <Hoverable>
                     {(hovered) => (
-                        <View style={[hovered ? styles.hoveredComponentBG : backgroundColor, styles.expenseWidgetRadius, styles.justifyContentEvenly, styles.gap3]}>
+                        <View style={containerStyles ?? [hovered ? styles.hoveredComponentBG : backgroundColor, styles.p2, styles.expenseWidgetRadius]}>
+                            {' '}
path: src/components/TransactionItemRow/index.tsx
user: login: sumo-slonik
body: These are remnants of the now-removed and no longer needed circle used for selecting a row on its right side.
created_at: 2025-05-05T12:20:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -27,6 +29,8 @@ function TransactionItemRow({
     dateColumnSize,
     shouldShowChatBubbleComponent = false,
     onCheckboxPress,
+    containerStyles,
path: src/components/TransactionItemRow/index.tsx
user: login: sumo-slonik
body: These are remnants of the now-removed and no longer needed circle used for selecting a row on its right side.
created_at: 2025-05-05T12:20:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2390,6 +2390,10 @@ const ROUTES = {
         route: 'settings/workspaces/:policyID/accounting/sage-intacct/advanced/payment-account',
         getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/sage-intacct/advanced/payment-account` as const,
     },
+    ADD_UNREPORTED_EXPENSE: {
+        route: 'search/r/:reportID/AddUnreportedExpense',
+        getRoute: (reportID: string | undefined) => `search/r/${reportID}/AddUnreportedExpense` as const,
path: src/ROUTES.ts
user: login: sumo-slonik
body: fixed
created_at: 2025-05-05T12:20:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -69,6 +71,9 @@ function TransactionItemRow({
         }
     }, [hovered, isSelected, styles.activeComponentBG, styles.hoveredComponentBG]);
 
+    const merchantName = getMerchant(transactionItem);
+    const isMerchantEmpty = merchantName === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT;
path: src/components/TransactionItemRow/index.tsx
user: login: mountiny
body: Lets use the isPartialMerchant from TransactionUtils
```suggestion
    const isMerchantEmpty = isPartialMerchant(merchantName);
```
created_at: 2025-05-06T16:34:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,128 @@
+import React, {useRef} from 'react';
+import {useOnyx} from 'react-native-onyx';
+import type {OnyxCollection} from 'react-native-onyx';
+import EmptyStateComponent from '@components/EmptyStateComponent';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import LottieAnimations from '@components/LottieAnimations';
+import ScreenWrapper from '@components/ScreenWrapper';
+import SelectionList from '@components/SelectionList';
+import type {ListItem, SectionListDataType, SelectionListHandle} from '@components/SelectionList/types';
+import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
+import interceptAnonymousUser from '@libs/interceptAnonymousUser';
+import Navigation from '@navigation/Navigation';
+import type {PlatformStackScreenProps} from '@navigation/PlatformStackNavigation/types';
+import {startMoneyRequest} from '@userActions/IOU';
+import {changeTransactionsReport} from '@userActions/Transaction';
+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/Transaction';
+import NewChatSelectorPage from './NewChatSelectorPage';
+import UnreportedExpenseListItem from './UnreportedExpenseListItem';
+
+type AddUnreportedExpensePageType = PlatformStackScreenProps<AddUnreportedExpensesParamList, typeof SCREENS.ADD_UNREPORTED_EXPENSES_ROOT>;
+
+type AddUnreportedExpensesParamList = {
+    [SCREENS.ADD_UNREPORTED_EXPENSES_ROOT]: {
+        reportID: string;
+    };
+};
+
+function AddUnreportedExpense({route}: AddUnreportedExpensePageType) {
+    const {translate} = useLocalize();
+
+    function getUnreportedTransactions(transactions: OnyxCollection<Transaction>) {
+        if (!transactions) {
+            return [];
+        }
+        return Object.values(transactions || {}).filter((item) => item?.reportID === '0');
+    }
+
+    const [transactions = []] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {
+        selector: (_transactions) => getUnreportedTransactions(_transactions),
+        initialValue: [],
+        canBeMissing: true,
+    });
+
+    const styles = useThemeStyles();
+    const selectionListRef = useRef<SelectionListHandle>(null);
+    const sections: Array<SectionListDataType<Transaction & ListItem>> = [
+        {
+            shouldShow: true,
+            data: transactions.filter((t): t is Transaction & ListItem => t !== undefined),
+        },
+    ];
+
+    const thereIsNoUnreportedTransactions = !((sections.at(0)?.data.length ?? 0) > 0);
+
+    const reportID = route.params.reportID;
+    const selectedIds = new Set<string>();
+    const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {canBeMissing: true});
+    return (
+        <ScreenWrapper
+            shouldEnableKeyboardAvoidingView={false}
+            includeSafeAreaPaddingBottom
+            shouldShowOfflineIndicator={false}
+            shouldEnablePickerAvoiding={false}
+            testID={NewChatSelectorPage.displayName}
+            focusTrapSettings={{active: false}}
+        >
+            <HeaderWithBackButton
+                title={translate('iou.addUnreportedExpense')}
+                onBackButtonPress={Navigation.goBack}
+            />
+
+            {thereIsNoUnreportedTransactions ? (
+                <EmptyStateComponent
+                    cardStyles={[styles.appBG]}
+                    cardContentStyles={[styles.pt5, styles.pb0]}
+                    headerMediaType={CONST.EMPTY_STATE_MEDIA.ANIMATION}
+                    headerMedia={LottieAnimations.GenericEmptyState}
+                    title={translate('iou.emptyStateUnreportedExpenseTitle')}
+                    subtitle={translate('iou.emptyStateUnreportedExpenseSubtitle')}
+                    headerStyles={[styles.emptyStateMoneyRequestReport]}
+                    lottieWebViewStyles={styles.emptyStateFolderWebStyles}
+                    headerContentStyles={styles.emptyStateFolderWebStyles}
+                    buttons={[
+                        {
+                            buttonText: translate('iou.createExpense'),
+                            buttonAction: () => {
+                                interceptAnonymousUser(() => {
+                                    startMoneyRequest(CONST.IOU.TYPE.SUBMIT, reportID);
+                                });
+                            },
+                            success: true,
+                            style: styles.unreportedExpenseCreateExpenseButton,
+                        },
+                    ]}
+                />
+            ) : (
+                <SelectionList<Transaction & ListItem>
+                    ref={selectionListRef}
+                    onSelectRow={(item) => {
+                        if (selectedIds.has(item.transactionID)) {
+                            selectedIds.delete(item.transactionID);
+                        } else {
+                            selectedIds.add(item.transactionID);
+                        }
+                    }}
+                    shouldShowTextInput={false}
+                    canSelectMultiple
+                    sections={sections}
+                    ListItem={UnreportedExpenseListItem}
+                    confirmButtonStyles={[styles.justifyContentCenter]}
+                    showConfirmButton
+                    confirmButtonText={translate('iou.addUnreportedExpenseConfirm')}
+                    onConfirm={() => {
+                        changeTransactionsReport([...selectedIds], report?.reportID ?? CONST.REPORT.UNREPORTED_REPORT_ID);
+                        Navigation.goBack(ROUTES.SEARCH_MONEY_REQUEST_REPORT.getRoute({reportID, backTo: Navigation.getActiveRoute()}));
+                    }}
+                />
+            )}
+        </ScreenWrapper>
+    );
+}
+
+export default AddUnreportedExpense;
path: src/pages/AddUnreportedExpense.tsx
user: login: mountiny
body: display name missing
created_at: 2025-05-06T16:36:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,128 @@
+import React, {useRef} from 'react';
+import {useOnyx} from 'react-native-onyx';
+import type {OnyxCollection} from 'react-native-onyx';
+import EmptyStateComponent from '@components/EmptyStateComponent';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import LottieAnimations from '@components/LottieAnimations';
+import ScreenWrapper from '@components/ScreenWrapper';
+import SelectionList from '@components/SelectionList';
+import type {ListItem, SectionListDataType, SelectionListHandle} from '@components/SelectionList/types';
+import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
+import interceptAnonymousUser from '@libs/interceptAnonymousUser';
+import Navigation from '@navigation/Navigation';
+import type {PlatformStackScreenProps} from '@navigation/PlatformStackNavigation/types';
+import {startMoneyRequest} from '@userActions/IOU';
+import {changeTransactionsReport} from '@userActions/Transaction';
+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/Transaction';
+import NewChatSelectorPage from './NewChatSelectorPage';
+import UnreportedExpenseListItem from './UnreportedExpenseListItem';
+
+type AddUnreportedExpensePageType = PlatformStackScreenProps<AddUnreportedExpensesParamList, typeof SCREENS.ADD_UNREPORTED_EXPENSES_ROOT>;
+
+type AddUnreportedExpensesParamList = {
+    [SCREENS.ADD_UNREPORTED_EXPENSES_ROOT]: {
+        reportID: string;
+    };
+};
+
+function AddUnreportedExpense({route}: AddUnreportedExpensePageType) {
+    const {translate} = useLocalize();
+
+    function getUnreportedTransactions(transactions: OnyxCollection<Transaction>) {
+        if (!transactions) {
+            return [];
+        }
+        return Object.values(transactions || {}).filter((item) => item?.reportID === '0');
+    }
+
+    const [transactions = []] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {
+        selector: (_transactions) => getUnreportedTransactions(_transactions),
+        initialValue: [],
+        canBeMissing: true,
+    });
+
+    const styles = useThemeStyles();
+    const selectionListRef = useRef<SelectionListHandle>(null);
+    const sections: Array<SectionListDataType<Transaction & ListItem>> = [
+        {
+            shouldShow: true,
+            data: transactions.filter((t): t is Transaction & ListItem => t !== undefined),
+        },
+    ];
+
+    const thereIsNoUnreportedTransactions = !((sections.at(0)?.data.length ?? 0) > 0);
path: src/pages/AddUnreportedExpense.tsx
user: login: mountiny
body: ```suggestion
    const thereIsNoUnreportedTransaction = !((sections.at(0)?.data.length ?? 0) > 0);
```
created_at: 2025-05-06T16:37:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,128 @@
+import React, {useRef} from 'react';
+import {useOnyx} from 'react-native-onyx';
+import type {OnyxCollection} from 'react-native-onyx';
+import EmptyStateComponent from '@components/EmptyStateComponent';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import LottieAnimations from '@components/LottieAnimations';
+import ScreenWrapper from '@components/ScreenWrapper';
+import SelectionList from '@components/SelectionList';
+import type {ListItem, SectionListDataType, SelectionListHandle} from '@components/SelectionList/types';
+import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
+import interceptAnonymousUser from '@libs/interceptAnonymousUser';
+import Navigation from '@navigation/Navigation';
+import type {PlatformStackScreenProps} from '@navigation/PlatformStackNavigation/types';
+import {startMoneyRequest} from '@userActions/IOU';
+import {changeTransactionsReport} from '@userActions/Transaction';
+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/Transaction';
+import NewChatSelectorPage from './NewChatSelectorPage';
+import UnreportedExpenseListItem from './UnreportedExpenseListItem';
+
+type AddUnreportedExpensePageType = PlatformStackScreenProps<AddUnreportedExpensesParamList, typeof SCREENS.ADD_UNREPORTED_EXPENSES_ROOT>;
+
+type AddUnreportedExpensesParamList = {
+    [SCREENS.ADD_UNREPORTED_EXPENSES_ROOT]: {
+        reportID: string;
+    };
+};
+
+function AddUnreportedExpense({route}: AddUnreportedExpensePageType) {
+    const {translate} = useLocalize();
+
+    function getUnreportedTransactions(transactions: OnyxCollection<Transaction>) {
+        if (!transactions) {
+            return [];
+        }
+        return Object.values(transactions || {}).filter((item) => item?.reportID === '0');
+    }
+
+    const [transactions = []] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {
+        selector: (_transactions) => getUnreportedTransactions(_transactions),
+        initialValue: [],
+        canBeMissing: true,
+    });
+
+    const styles = useThemeStyles();
+    const selectionListRef = useRef<SelectionListHandle>(null);
+    const sections: Array<SectionListDataType<Transaction & ListItem>> = [
+        {
+            shouldShow: true,
+            data: transactions.filter((t): t is Transaction & ListItem => t !== undefined),
+        },
+    ];
+
+    const thereIsNoUnreportedTransactions = !((sections.at(0)?.data.length ?? 0) > 0);
+
+    const reportID = route.params.reportID;
+    const selectedIds = new Set<string>();
+    const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {canBeMissing: true});
+    return (
+        <ScreenWrapper
+            shouldEnableKeyboardAvoidingView={false}
+            includeSafeAreaPaddingBottom
+            shouldShowOfflineIndicator={false}
+            shouldEnablePickerAvoiding={false}
+            testID={NewChatSelectorPage.displayName}
+            focusTrapSettings={{active: false}}
+        >
+            <HeaderWithBackButton
+                title={translate('iou.addUnreportedExpense')}
+                onBackButtonPress={Navigation.goBack}
+            />
+
+            {thereIsNoUnreportedTransactions ? (
path: src/pages/AddUnreportedExpense.tsx
user: login: mountiny
body: ```suggestion
            {thereIsNoUnreportedTransaction ? (
```
created_at: 2025-05-06T16:37:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,145 @@
+import React, {useRef, useState} from 'react';
+import {useOnyx} from 'react-native-onyx';
+import type {OnyxCollection} from 'react-native-onyx';
+import EmptyStateComponent from '@components/EmptyStateComponent';
+import FormHelpMessage from '@components/FormHelpMessage';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import LottieAnimations from '@components/LottieAnimations';
+import ScreenWrapper from '@components/ScreenWrapper';
+import SelectionList from '@components/SelectionList';
+import type {ListItem, SectionListDataType, SelectionListHandle} from '@components/SelectionList/types';
+import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
+import interceptAnonymousUser from '@libs/interceptAnonymousUser';
+import Navigation from '@navigation/Navigation';
+import type {PlatformStackScreenProps} from '@navigation/PlatformStackNavigation/types';
+import {startMoneyRequest} from '@userActions/IOU';
+import {changeTransactionsReport} from '@userActions/Transaction';
+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/Transaction';
+import NewChatSelectorPage from './NewChatSelectorPage';
+import UnreportedExpenseListItem from './UnreportedExpenseListItem';
+
+type AddUnreportedExpensePageType = PlatformStackScreenProps<AddUnreportedExpensesParamList, typeof SCREENS.ADD_UNREPORTED_EXPENSES_ROOT>;
+
+type AddUnreportedExpensesParamList = {
+    [SCREENS.ADD_UNREPORTED_EXPENSES_ROOT]: {
+        reportID: string;
+    };
+};
+
+function AddUnreportedExpense({route}: AddUnreportedExpensePageType) {
+    const {translate} = useLocalize();
+    const [errorMessage, setErrorMessage] = useState<string>('');
+
+    function getUnreportedTransactions(transactions: OnyxCollection<Transaction>) {
+        if (!transactions) {
+            return [];
+        }
+        return Object.values(transactions || {}).filter((item) => item?.reportID === '0');
+    }
+
+    const [transactions = []] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {
+        selector: (_transactions) => getUnreportedTransactions(_transactions),
+        initialValue: [],
+        canBeMissing: true,
+    });
+
+    const styles = useThemeStyles();
+    const selectionListRef = useRef<SelectionListHandle>(null);
+    const sections: Array<SectionListDataType<Transaction & ListItem>> = [
+        {
+            shouldShow: true,
+            data: transactions.filter((t): t is Transaction & ListItem => t !== undefined),
path: src/pages/AddUnreportedExpense.tsx
user: login: ikevin127
body: We had an issue recently originating from this implementation:
- https://github.com/Expensify/App/issues/63858

we addressed it by mapping `transactions` and passing `isDisabled: isTransactionPendingDelete(transaction)` to prevent offline deleted unreported expenses from being added to a report.


created_at: 2025-06-21T01:02:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,145 @@
+import React, {useRef, useState} from 'react';
+import {useOnyx} from 'react-native-onyx';
+import type {OnyxCollection} from 'react-native-onyx';
+import EmptyStateComponent from '@components/EmptyStateComponent';
+import FormHelpMessage from '@components/FormHelpMessage';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import LottieAnimations from '@components/LottieAnimations';
+import ScreenWrapper from '@components/ScreenWrapper';
+import SelectionList from '@components/SelectionList';
+import type {ListItem, SectionListDataType, SelectionListHandle} from '@components/SelectionList/types';
+import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
+import interceptAnonymousUser from '@libs/interceptAnonymousUser';
+import Navigation from '@navigation/Navigation';
+import type {PlatformStackScreenProps} from '@navigation/PlatformStackNavigation/types';
+import {startMoneyRequest} from '@userActions/IOU';
+import {changeTransactionsReport} from '@userActions/Transaction';
+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/Transaction';
+import NewChatSelectorPage from './NewChatSelectorPage';
+import UnreportedExpenseListItem from './UnreportedExpenseListItem';
+
+type AddUnreportedExpensePageType = PlatformStackScreenProps<AddUnreportedExpensesParamList, typeof SCREENS.ADD_UNREPORTED_EXPENSES_ROOT>;
+
+type AddUnreportedExpensesParamList = {
+    [SCREENS.ADD_UNREPORTED_EXPENSES_ROOT]: {
+        reportID: string;
+    };
+};
+
+function AddUnreportedExpense({route}: AddUnreportedExpensePageType) {
+    const {translate} = useLocalize();
+    const [errorMessage, setErrorMessage] = useState<string>('');
+
+    function getUnreportedTransactions(transactions: OnyxCollection<Transaction>) {
+        if (!transactions) {
+            return [];
+        }
+        return Object.values(transactions || {}).filter((item) => item?.reportID === '0');
+    }
+
+    const [transactions = []] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {
+        selector: (_transactions) => getUnreportedTransactions(_transactions),
+        initialValue: [],
+        canBeMissing: true,
+    });
+
+    const styles = useThemeStyles();
+    const selectionListRef = useRef<SelectionListHandle>(null);
+    const sections: Array<SectionListDataType<Transaction & ListItem>> = [
+        {
+            shouldShow: true,
+            data: transactions.filter((t): t is Transaction & ListItem => t !== undefined),
+        },
+    ];
+
+    const thereIsNoUnreportedTransaction = !((sections.at(0)?.data.length ?? 0) > 0);
+
+    const reportID = route.params.reportID;
+    const selectedIds = new Set<string>();
+    const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {canBeMissing: true});
+    return (
+        <ScreenWrapper
+            shouldEnableKeyboardAvoidingView={false}
+            includeSafeAreaPaddingBottom
+            shouldShowOfflineIndicator={false}
+            shouldEnablePickerAvoiding={false}
+            testID={NewChatSelectorPage.displayName}
+            focusTrapSettings={{active: false}}
+        >
+            <HeaderWithBackButton
+                title={translate('iou.addUnreportedExpense')}
+                onBackButtonPress={Navigation.goBack}
+            />
+
+            {thereIsNoUnreportedTransaction ? (
+                <EmptyStateComponent
+                    cardStyles={[styles.appBG]}
+                    cardContentStyles={[styles.pt5, styles.pb0]}
+                    headerMediaType={CONST.EMPTY_STATE_MEDIA.ANIMATION}
+                    headerMedia={LottieAnimations.GenericEmptyState}
+                    title={translate('iou.emptyStateUnreportedExpenseTitle')}
+                    subtitle={translate('iou.emptyStateUnreportedExpenseSubtitle')}
+                    headerStyles={[styles.emptyStateMoneyRequestReport]}
+                    lottieWebViewStyles={styles.emptyStateFolderWebStyles}
+                    headerContentStyles={styles.emptyStateFolderWebStyles}
+                    buttons={[
+                        {
+                            buttonText: translate('iou.createExpense'),
+                            buttonAction: () => {
+                                interceptAnonymousUser(() => {
+                                    startMoneyRequest(CONST.IOU.TYPE.SUBMIT, reportID);
+                                });
+                            },
+                            success: true,
+                            style: styles.unreportedExpenseCreateExpenseButton,
+                        },
+                    ]}
+                />
+            ) : (
+                <SelectionList<Transaction & ListItem>
+                    ref={selectionListRef}
+                    onSelectRow={(item) => {
+                        if (selectedIds.has(item.transactionID)) {
+                            selectedIds.delete(item.transactionID);
+                        } else {
+                            selectedIds.add(item.transactionID);
+                        }
+                    }}
path: src/pages/AddUnreportedExpense.tsx
user: login: ikevin127
body: The `onSelectRow` block was missing logic to clear existing `errorMessage` once an option was actually selected, leading to this issue:
- https://github.com/Expensify/App/issues/64099

which we addressed by clearing the error and moving the `Set` implementation to state (see [comment](https://github.com/Expensify/App/pull/64379#issuecomment-2983295082) for details).
created_at: 2025-07-02T23:46:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,145 @@
+import React, {useRef, useState} from 'react';
+import {useOnyx} from 'react-native-onyx';
+import type {OnyxCollection} from 'react-native-onyx';
+import EmptyStateComponent from '@components/EmptyStateComponent';
+import FormHelpMessage from '@components/FormHelpMessage';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import LottieAnimations from '@components/LottieAnimations';
+import ScreenWrapper from '@components/ScreenWrapper';
+import SelectionList from '@components/SelectionList';
+import type {ListItem, SectionListDataType, SelectionListHandle} from '@components/SelectionList/types';
+import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
+import interceptAnonymousUser from '@libs/interceptAnonymousUser';
+import Navigation from '@navigation/Navigation';
+import type {PlatformStackScreenProps} from '@navigation/PlatformStackNavigation/types';
+import {startMoneyRequest} from '@userActions/IOU';
+import {changeTransactionsReport} from '@userActions/Transaction';
+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/Transaction';
+import NewChatSelectorPage from './NewChatSelectorPage';
+import UnreportedExpenseListItem from './UnreportedExpenseListItem';
+
+type AddUnreportedExpensePageType = PlatformStackScreenProps<AddUnreportedExpensesParamList, typeof SCREENS.ADD_UNREPORTED_EXPENSES_ROOT>;
+
+type AddUnreportedExpensesParamList = {
+    [SCREENS.ADD_UNREPORTED_EXPENSES_ROOT]: {
+        reportID: string;
+    };
+};
+
+function AddUnreportedExpense({route}: AddUnreportedExpensePageType) {
+    const {translate} = useLocalize();
+    const [errorMessage, setErrorMessage] = useState<string>('');
+
+    function getUnreportedTransactions(transactions: OnyxCollection<Transaction>) {
path: src/pages/AddUnreportedExpense.tsx
user: login: parasharrajat
body: Per diem transactions can be moved to any workspace, they can only be readded to same workspace and we do not filter per diem transactions if workspace per diem settings is disabled. It caused https://github.com/Expensify/App/issues/65402
created_at: 2025-08-27T10:23:13Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,145 @@
+import React, {useRef, useState} from 'react';
+import {useOnyx} from 'react-native-onyx';
+import type {OnyxCollection} from 'react-native-onyx';
+import EmptyStateComponent from '@components/EmptyStateComponent';
+import FormHelpMessage from '@components/FormHelpMessage';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import LottieAnimations from '@components/LottieAnimations';
+import ScreenWrapper from '@components/ScreenWrapper';
+import SelectionList from '@components/SelectionList';
+import type {ListItem, SectionListDataType, SelectionListHandle} from '@components/SelectionList/types';
+import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
+import interceptAnonymousUser from '@libs/interceptAnonymousUser';
+import Navigation from '@navigation/Navigation';
+import type {PlatformStackScreenProps} from '@navigation/PlatformStackNavigation/types';
+import {startMoneyRequest} from '@userActions/IOU';
+import {changeTransactionsReport} from '@userActions/Transaction';
+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/Transaction';
+import NewChatSelectorPage from './NewChatSelectorPage';
+import UnreportedExpenseListItem from './UnreportedExpenseListItem';
+
+type AddUnreportedExpensePageType = PlatformStackScreenProps<AddUnreportedExpensesParamList, typeof SCREENS.ADD_UNREPORTED_EXPENSES_ROOT>;
+
+type AddUnreportedExpensesParamList = {
+    [SCREENS.ADD_UNREPORTED_EXPENSES_ROOT]: {
+        reportID: string;
+    };
+};
+
+function AddUnreportedExpense({route}: AddUnreportedExpensePageType) {
+    const {translate} = useLocalize();
+    const [errorMessage, setErrorMessage] = useState<string>('');
+
+    function getUnreportedTransactions(transactions: OnyxCollection<Transaction>) {
+        if (!transactions) {
+            return [];
+        }
+        return Object.values(transactions || {}).filter((item) => item?.reportID === '0');
path: src/pages/AddUnreportedExpense.tsx
user: login: rojiphil
body: We needed an additional check if unreported transactions are owned by the current user. We implemented this in #70639 
created_at: 2026-02-20T05:33:40Z
author_association: CONTRIBUTOR

PR comments:
user: login: sumo-slonik
created_at: 2025-04-23T12:03:00Z
body: I'm still wrestling 🤼  with TypeScript here, but the code is probably ready for review. 
On the backend side @mountiny , I think we could consider removing concierge messages from self-DMs after expenses are moved to reports.
Also, I’d like to suggest that when we move an expense, we could return the next steps for the report header as well.
author_association: CONTRIBUTOR
user: login: melvin-bot[bot]
created_at: 2025-04-23T12:03:07Z
body: @ Please copy/paste the Reviewer Checklist from [here](https://raw.githubusercontent.com/Expensify/App/main/contributingGuides/REVIEWER_CHECKLIST.md) into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]
author_association: NONE
user: login: mountiny
created_at: 2025-04-23T12:27:56Z
body: >  I think we could consider removing concierge messages from self-DMs after expenses are moved to reports.

Can you post about this in a new thread in migrate please? I am not sure I exactly follow what you mean
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-04-23T12:57:45Z
body: > > I think we could consider removing concierge messages from self-DMs after expenses are moved to reports.
> 
> Can you post about this in a new thread in migrate please? I am not sure I exactly follow what you mean

I'll record a video then, to provide better context.
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-04-24T10:25:33Z
body: All check errors seem to be fixed, I think we can start the review.
author_association: CONTRIBUTOR
user: login: trjExpensify
created_at: 2025-04-24T10:41:12Z
body: When there's no merchant or description, I think everything should be on the same line in the preview.

<img width="1073" alt="image" src="https://github.com/user-attachments/assets/d4506c1c-2439-4021-8e7a-3521a78b5ab0" />

E.g 

`Apr 26 * Cash              $10.00`

I've asked @shawnborton to confirm, just noting it here for now. 

author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-04-24T10:50:15Z
body: > When there's no merchant or description, I think everything should be on the same line in the preview.
> I've asked @shawnborton to confirm, just noting it here for now.

Alright, once we have that confirmed, I'll take care of the changes.
author_association: CONTRIBUTOR
user: login: dannymcclain
created_at: 2025-04-24T13:06:30Z
body: >When there's no merchant or description, I think everything should be on the same line in the preview.

I agree, that's what we do for the new previews and I think it makes sense to do that here too (98% confident Shawn will agree).

![CleanShot 2025-04-24 at 08 05 31@2x](https://github.com/user-attachments/assets/b749165c-a619-42d2-96ca-3a38ccb60a92)
author_association: CONTRIBUTOR
user: login: trjExpensify
created_at: 2025-04-24T13:20:15Z
body: Alrighty, let's do it. 
author_association: CONTRIBUTOR
user: login: shawnborton
created_at: 2025-04-24T23:57:24Z
body: 98% of the time Danny is right 100% of the time. I agree, that's what I would expect. 

Can we also try vertically centering the check circle? Perhaps it could use an extra 4px of margin between check circle and amount too? 
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-04-28T13:21:00Z
body: <img width="373" alt="image" src="https://github.com/user-attachments/assets/a73c96af-7cfa-4889-bc62-6faf32f9e845" />

Does it look fine now?
I centered the "Select Circle" and, in case there is no merchant, I moved the total amount to the same line as the rest of the content.
author_association: CONTRIBUTOR
user: login: shawnborton
created_at: 2025-04-28T16:38:27Z
body: I think that is looking better. This makes me wonder though... should we move the check circle over to the left side, and try to match the exact styles we have for mobile multi-select? I don't see a great reason to make things look too much different here. And I'm thinking it might feel a little nicer too...
![CleanShot 2025-04-28 at 12 38 16@2x](https://github.com/user-attachments/assets/0bf0b7e2-02da-49d0-b226-cb0cd6a511a4)



Thoughts @Expensify/design ?
author_association: CONTRIBUTOR
user: login: dannymcclain
created_at: 2025-04-28T16:43:05Z
body: Oh my gosh yes! Didn't even think of that 🤦‍♂️ but 100% agree. 
author_association: CONTRIBUTOR
user: login: trjExpensify
created_at: 2025-04-28T18:22:16Z
body: Beauty! 
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-04-28T21:15:48Z
body: In that case, I’m changing the select circle to a checkbox on the left side.
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-04-29T09:00:59Z
body: <img width="213" alt="image" src="https://github.com/user-attachments/assets/811daf96-1506-4f0a-86c1-265872ef2811" />

It's much clearer, I 100% agree with the suggestion of placing the checkbox on the left side.
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-04-29T09:18:46Z
body: I think it's ready for the next review.
author_association: CONTRIBUTOR
user: login: trjExpensify
created_at: 2025-04-29T10:00:21Z
body: Assigned @allgandalf for the review. 
author_association: CONTRIBUTOR
user: login: shawnborton
created_at: 2025-04-29T12:29:35Z
body: What gap are you using between the checkbox and the receipt icon? I think we might need to increase it slightly, so that we basically have the same padding on the left of the checkbox as we do on the right side. 

But otherwise I agree, this feels much better! 
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-04-29T13:26:29Z
body: ![image](https://github.com/user-attachments/assets/c332fbe8-18da-4357-97f4-6d71cfa43b76)

There's an 8px margin on the right side of the checkbox  — if you think I should align it with the spacing from the left edge (12px) , I’d be happy to adjust it.
author_association: CONTRIBUTOR
user: login: shawnborton
created_at: 2025-04-29T14:46:06Z
body: > There's an 8px margin on the right side of the checkbox — if you think I should align it with the spacing from the left edge (12px) , I’d be happy to adjust it.

Yes, I think we should! 
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-04-30T10:02:48Z
body: I think I've already fixed everything. If there are no further comments, the PR is ready. In the follow-up, I'll add the integration with the Simplified Actions button.
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-04-30T13:09:35Z
body: @allgandalf 
If you could take another look at it, because tomorrow we start our time off in Poland and I’d like to fix any potential mistakes before then
author_association: CONTRIBUTOR
user: login: allgandalf
created_at: 2025-05-01T12:17:01Z
body: @sumo-slonik can you please resolve conflicts here :)
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-05-05T12:24:02Z
body: @luacmartins I think I've already fixed everything you asked for.
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-05-05T15:07:09Z
body: @allgandalf Do you want to add anything, or is it all good?
author_association: CONTRIBUTOR
user: login: luacmartins
created_at: 2025-05-05T18:13:19Z
body: @sumo-slonik we have conflicts again. Could you please address them?
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-05-06T07:17:45Z
body: @luacmartins  I think I've resolved the conflicts, so if you don't have any comments, you can restore the ticket.
author_association: CONTRIBUTOR
user: login: allgandalf
created_at: 2025-05-06T12:10:01Z
body: @sumo-slonik please resolve conflicts 
author_association: CONTRIBUTOR
user: login: allgandalf
created_at: 2025-05-06T12:10:28Z
body: > @allgandalf Do you want to add anything, or is it all good?

Seems good to me!, will take a quick check though
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-05-06T13:39:24Z
body: @allgandalf I think it's ready, but it impacts a lot of files we're working on in other branches, so conflicts are appearing often. The sooner we merge it, the better.
author_association: CONTRIBUTOR
user: login: allgandalf
created_at: 2025-05-06T16:23:44Z
body: ## Reviewer Checklist

- [x] I have verified the author checklist is complete (all boxes are checked off).
- [x] I verified the correct issue is linked in the `### Fixed Issues` section above
- [x] I verified testing steps are clear and they cover the changes made in this PR
    - [x] I verified the steps for local testing are in the `Tests` section
    - [x] I verified the steps for Staging and/or Production testing are in the `QA steps` section
    - [x] I verified the steps cover any possible failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    - [x] I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
- [x] I checked that screenshots or videos are included for tests on [all platforms](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#make-sure-you-can-test-on-all-platforms)
- [x] I included screenshots or videos for tests on [all platforms](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#make-sure-you-can-test-on-all-platforms)
- [x] I verified that the composer does not automatically focus or open the keyboard on mobile unless explicitly intended. This includes checking that returning the app from the background does not unexpectedly open the keyboard.
- [x] I verified tests pass on **all platforms** & I tested again on:
    - [x] Android: HybridApp
    - [x] Android: mWeb Chrome
    - [x] iOS: HybridApp
    - [x] iOS: mWeb Safari
    - [x] MacOS: Chrome / Safari
    - [x] MacOS: Desktop
- [x] If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
- [x] I verified there are no new alerts related to the `canBeMissing` param for `useOnyx`
- [x] I verified proper code patterns were followed (see [Reviewing the code](https://github.com/Expensify/App/blob/main/contributingGuides/PR_REVIEW_GUIDELINES.md#reviewing-the-code))
    - [x] I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. `toggleReport` and not `onIconClick`).
    - [x] I verified that comments were added to code that is not self explanatory
    - [x] I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    - [x] I verified any copy / text shown in the product is localized by adding it to `src/languages/*` files and using the [translation method](https://github.com/Expensify/App/blob/4bd99402cebdf4d7394e0d1f260879ea238197eb/src/components/withLocalize.js#L60)
    - [x] I verified all numbers, amounts, dates and phone numbers shown in the product are using the [localization methods](https://github.com/Expensify/App/blob/4bd99402cebdf4d7394e0d1f260879ea238197eb/src/components/withLocalize.js#L60-L68)
    - [x] I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
    - [x] I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    - [x] I verified the JSDocs style guidelines (in [`STYLE.md`](https://github.com/Expensify/App/blob/main/contributingGuides/STYLE.md#jsdocs)) were followed
- [x] If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
- [x] I verified that this PR follows the guidelines as stated in the [Review Guidelines](https://github.com/Expensify/App/blob/main/contributingGuides/PR_REVIEW_GUIDELINES.md)
- [x] I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like `Avatar`, I verified the components using `Avatar` have been tested & I retested again)
- [x] I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
- [x] I verified any variables that can be defined as constants (ie. in CONST.ts or at the top of the file that uses the constant) are defined as such
- [x] If a new component is created I verified that:
    - [x] A similar component doesn't exist in the codebase
    - [x] All props are defined accurately and each prop has a `/** comment above it */`
    - [x] The file is named correctly
    - [x] The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    - [x] The only data being stored in the state is data necessary for rendering and nothing else
    - [x] For Class Components, any internal methods passed to components event handlers are bound to `this` properly so there are no scoping issues (i.e. for `onClick={this.submit}` the method `this.submit` should be bound to `this` in the constructor)
    - [x] Any internal methods bound to `this` are necessary to be bound (i.e. avoid `this.submit = this.submit.bind(this);` if `this.submit` is never passed to a component event handler like `onClick`)
    - [x] All JSX used for rendering exists in the render method
    - [x] The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
- [x] If any new file was added I verified that:
    - [x] The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
- [x] If a new CSS style is added I verified that:
    - [x] A similar style doesn't already exist
    - [x] The style can't be created with an existing [StyleUtils](https://github.com/Expensify/App/blob/main/src/utils/index.ts) function (i.e. `StyleUtils.getBackgroundAndBorderStyle(theme.componentBG`)
- [x] If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
- [x] If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like `Avatar` is modified, I verified that `Avatar` is working as expected in all cases)
- [x] If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
- [x] If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
- [x] If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    - [x] I verified that all the inputs inside a form are aligned with each other.
    - [x] I added `Design` label and/or tagged `@Expensify/design` so the design team can review the changes.
- [x] If a new page is added, I verified it's using the `ScrollView` component to make it scrollable when more elements are added to the page.
- [x] For any bug fix or new feature in this PR, I verified that sufficient [unit tests](https://github.com/Expensify/App/blob/main/tests/README.md) are included to prevent regressions in this flow.
- [x] If the `main` branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the `Test` steps.
- [x] I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

### Screenshots/Videos
<details>
<summary>Android: HybridApp</summary>

https://github.com/user-attachments/assets/a8147e23-e0c5-41ef-a40e-bc2810a7ff50


<!-- add screenshots or videos here -->

</details>

<details>
<summary>Android: mWeb Chrome</summary>

https://github.com/user-attachments/assets/5d6c56b2-4c7a-4b82-9dd1-8ef9365f3a66


<!-- add screenshots or videos here -->

</details>

<details>
<summary>iOS: HybridApp</summary>

https://github.com/user-attachments/assets/16c16fd4-7e7e-471a-b520-e237c3fc841c


<!-- add screenshots or videos here -->

</details>

<details>
<summary>iOS: mWeb Safari</summary>

https://github.com/user-attachments/assets/cae0c4a8-c1aa-40f4-9742-2007bb6e7dc2


<!-- add screenshots or videos here -->

</details>

<details>
<summary>MacOS: Chrome / Safari</summary>


https://github.com/user-attachments/assets/0c258d2a-6c46-443f-8d43-e2f9906c3cb0



<!-- add screenshots or videos here -->

</details>

<details>
<summary>MacOS: Desktop</summary>

https://github.com/user-attachments/assets/93848671-21c2-4b77-9a91-6a911e268528


<!-- add screenshots or videos here -->

</details>

author_association: CONTRIBUTOR
user: login: allgandalf
created_at: 2025-05-06T16:32:55Z
body: `Bug:` No error when the user clicks on `Add to report` with no selection 

 https://github.com/user-attachments/assets/bc025ab8-88de-421f-bbf8-a029e2d50d9b


author_association: CONTRIBUTOR
user: login: allgandalf
created_at: 2025-05-06T16:34:39Z
body: `Bug`: We cannot add distance request to a report BE throws error, so lets not show those expenses, @trjExpensify @mountiny @luacmartins can you confirm this 

![Screenshot 2025-05-06 at 10 03 42 PM](https://github.com/user-attachments/assets/ec69decc-1a32-4bbf-a89c-eb3e546a5c0d)

author_association: CONTRIBUTOR
user: login: allgandalf
created_at: 2025-05-06T16:36:20Z
body: `Bug`: If we select all the expenses at once and then click `add to report` there is a empty view briefly shown before the RHP closes, i think we should first close the RHP then optimistically clear the transactions from that RHP:

https://github.com/user-attachments/assets/05a1e363-4418-42ae-a909-8a33260fa7e4


author_association: CONTRIBUTOR
user: login: trjExpensify
created_at: 2025-05-06T21:45:20Z
body: >Bug: We cannot add distance request to a report BE throws error, so lets not show those expenses, @trjExpensify @mountiny @luacmartins can you confirm this

I think that's a myth. See [here](https://github.com/Expensify/App/issues/58435#issuecomment-2741865035). @luacmartins I believe was addressing this then. 
author_association: CONTRIBUTOR
user: login: allgandalf
created_at: 2025-05-07T08:02:26Z
body: What should we do for this PR then ? since the BE throws error if we try to add the expense 
author_association: CONTRIBUTOR
user: login: trjExpensify
created_at: 2025-05-07T09:26:07Z
body: I think we don't add hiding distance expenses in this PR @allgandalf, and fix the bug with distance expenses separately. 
author_association: CONTRIBUTOR
user: login: luacmartins
created_at: 2025-05-07T10:41:57Z
body: Hmm the error shown above for distance requests seems different than what I addressed in my PR. We have [specific code](https://github.com/Expensify/Web-Expensify/blob/ef11302311ff0f1bdaaeebbf4b30a1a21ad9dda8/lib/ReportAPI.php#L2840-L2850) that prevents moving a transaction if the customUnit is not present in the new policy. I think we can address this in a follow up though
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-05-07T14:18:47Z
body: >Bug: No error when the user clicks on Add to report with no selection

@Expensify/design Could you please let me know what error should appear in this situation? I can’t find any mockup for it in Figma, so I’m not sure what it’s supposed to look like.

Should it look similar to this?
![image](https://github.com/user-attachments/assets/552db310-4ecb-4b85-8a67-de9d42e7d94f)

author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-05-07T15:20:10Z
body: If this is okay, I'll confirm the translations and we’ll have all the bugs fixed:
![image](https://github.com/user-attachments/assets/5caee2bb-9b8e-4b9a-ac5e-54dae58b0d84)

author_association: CONTRIBUTOR
user: login: shawnborton
created_at: 2025-05-07T15:37:21Z
body: > Should it look similar to this?

Yup, that looks good to me! Can we see what it looks like when the list of unreported expenses is quite long too? 
author_association: CONTRIBUTOR
user: login: trjExpensify
created_at: 2025-05-07T15:55:37Z
body: Yeah, standard form error pattern sounds good! "Submitting" is a bit technical in reference to the form, and potentially confusing with actually submitting the report. I'd vote to go with:

>Select at least one expense to add to the report
author_association: CONTRIBUTOR
user: login: allgandalf
created_at: 2025-05-07T18:48:58Z
body: @sumo-slonik , lets fix the conflicts, I will post the checklist tomorrow morning 
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-05-08T08:49:12Z
body: @shawnborton This is what it looks like when we have a lot of transactions:
<img width="961" alt="image" src="https://github.com/user-attachments/assets/cb38f900-b26e-435d-a43d-34d726a44233" />
author_association: CONTRIBUTOR
user: login: shawnborton
created_at: 2025-05-08T11:57:49Z
body: Okay cool, and can you show that same screenshot but with no error? Just want to make sure we don't use any kind of padding or gap on top of the button when it's fixed to the bottom like that and we have a scrolling list behind it. 
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-05-08T15:02:41Z
body: <img width="1512" alt="image" src="https://github.com/user-attachments/assets/e6baee92-0e8b-4a22-bed6-7e59f6bebc59" />

<img width="1512" alt="image" src="https://github.com/user-attachments/assets/0d8c2837-574b-42bd-a7b7-ecffa26bb489" />

author_association: CONTRIBUTOR
user: login: shawnborton
created_at: 2025-05-08T15:24:23Z
body: Nice, looks good to me 👍 
author_association: CONTRIBUTOR
user: login: dannymcclain
created_at: 2025-05-08T15:25:16Z
body: Why is there more padding on the bottom of these than on the top?

![CleanShot 2025-05-08 at 10 24 52@2x](https://github.com/user-attachments/assets/f29feb6d-f885-42fb-be25-457bbdcefc61)

author_association: CONTRIBUTOR
user: login: shawnborton
created_at: 2025-05-08T15:36:46Z
body: > Why is there more padding on the bottom of these than on the top?

Good shout! I think @Kicu is fixing that in a different PR, right? 
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-05-08T15:40:33Z
body: It seems to me that it's done here:
https://github.com/Expensify/App/pull/61677
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-05-08T15:43:29Z
body: There are some issues after adding the main, I'm already working on the fixes.
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-05-08T16:44:24Z
body: If there’s nothing else here, I think this can be merged.
author_association: CONTRIBUTOR
user: login: sumo-slonik
created_at: 2025-05-08T16:56:28Z
body: > @sumo-slonik , lets fix the conflicts, I will post the checklist tomorrow morning

@allgandalf Would you have a chance to take a look at it today?

author_association: CONTRIBUTOR
user: login: allgandalf
created_at: 2025-05-08T17:41:28Z
body: Working on it right now
author_association: CONTRIBUTOR
user: login: OSBotify
created_at: 2025-05-08T18:37:12Z
body: :hand: This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.
author_association: CONTRIBUTOR
user: login: vincdargento
created_at: 2025-05-14T21:27:31Z
body: @sumo-slonik This PR is failing because of issue https://github.com/Expensify/App/issues/62057
The issue is reproducible in: Web, mWeb

https://github.com/user-attachments/assets/7d583139-aca2-472c-9284-b2d94fd61a6f
author_association: NONE
user: login: brunovjk
created_at: 2025-07-21T14:43:37Z
body: This PR introduced a [bug](https://github.com/Expensify/App/issues/64563) where the LHN preview total only included one track expense after adding multiple unreported expenses to a workspace report. This happened because the aggregation logic didn’t account for the possibility of multiple track expenses in this context
author_association: CONTRIBUTOR