From 8769b23b2e3b57ef02f8aea1038477d2439a066b Mon Sep 17 00:00:00 2001
From: Mykhailo Kravchenko <rezkiy37@gmail.com>
Date: Thu, 10 Apr 2025 17:40:32 +0300
Subject: [PATCH 1/2] Enhance Search and Report Components with Policy
 Integration

- Added `useOnyx` hook to fetch policies in `SearchList` and passed it to relevant components.
- Updated `ChatListItem`, `PureReportActionItem`, and `ReportActionItemSingle` to accept and utilize policies prop.
- Modified type definitions to include policies for better type safety and clarity.
---
 src/components/Search/SearchList.tsx          | 19 ++++++++++++++++++-
 src/components/SelectionList/ChatListItem.tsx |  2 ++
 src/components/SelectionList/types.ts         |  5 +++++
 .../home/report/PureReportActionItem.tsx      |  7 ++++++-
 .../home/report/ReportActionItemSingle.tsx    | 15 ++++++++++-----
 5 files changed, 41 insertions(+), 7 deletions(-)

diff --git a/src/components/Search/SearchList.tsx b/src/components/Search/SearchList.tsx
index 3808c13253f7..cdafe5dd3e8c 100644
--- a/src/components/Search/SearchList.tsx
+++ b/src/components/Search/SearchList.tsx
@@ -3,6 +3,7 @@ import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useRef,
 import type {ForwardedRef} from 'react';
 import {View} from 'react-native';
 import type {FlatList, ListRenderItemInfo, NativeSyntheticEvent, StyleProp, ViewStyle, ViewToken} from 'react-native';
+import {useOnyx} from 'react-native-onyx';
 import Animated from 'react-native-reanimated';
 import type {FlatListPropsWithLayout} from 'react-native-reanimated';
 import Checkbox from '@components/Checkbox';
@@ -28,6 +29,7 @@ import {isMobileChrome} from '@libs/Browser';
 import {addKeyDownPressListener, removeKeyDownPressListener} from '@libs/KeyboardShortcut/KeyDownPressListener';
 import variables from '@styles/variables';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 
 type SearchListItem = TransactionListItemType | ReportListItemType | ReportActionListItemType;
 type SearchListItemComponentType = typeof TransactionListItem | typeof ChatListItem | typeof ReportListItem;
@@ -120,6 +122,8 @@ function SearchList(
     // Keep track of the number of selected items to determine if we should turn off selection mode
     const selectionRef = useRef(0);
 
+    const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);
+
     useEffect(() => {
         selectionRef.current = selectedItemsLength;
 
@@ -299,10 +303,23 @@ function SearchList(
                     }}
                     shouldPreventDefaultFocusOnSelectRow={shouldPreventDefaultFocusOnSelectRow}
                     queryJSONHash={queryJSONHash}
+                    policies={policies}
                 />
             );
         },
-        [ListItem, canSelectMultiple, focusedIndex, handleLongPressRow, itemsToHighlight, onCheckboxPress, onSelectRow, queryJSONHash, setFocusedIndex, shouldPreventDefaultFocusOnSelectRow],
+        [
+            ListItem,
+            canSelectMultiple,
+            focusedIndex,
+            handleLongPressRow,
+            itemsToHighlight,
+            onCheckboxPress,
+            onSelectRow,
+            policies,
+            queryJSONHash,
+            setFocusedIndex,
+            shouldPreventDefaultFocusOnSelectRow,
+        ],
     );
 
     return (
diff --git a/src/components/SelectionList/ChatListItem.tsx b/src/components/SelectionList/ChatListItem.tsx
index 634b34897311..2bec4ab0f2a5 100644
--- a/src/components/SelectionList/ChatListItem.tsx
+++ b/src/components/SelectionList/ChatListItem.tsx
@@ -22,6 +22,7 @@ function ChatListItem<TItem extends ListItem>({
     onFocus,
     onLongPressRow,
     shouldSyncFocus,
+    policies,
 }: ChatListItemProps<TItem>) {
     const reportActionItem = item as unknown as ReportActionListItemType;
     const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportActionItem?.reportID ?? CONST.DEFAULT_NUMBER_ID}`);
@@ -87,6 +88,7 @@ function ChatListItem<TItem extends ListItem>({
                         CONST.REPORT.ACTIONS.TYPE.FORWARDED,
                     ].some((type) => type === reportActionItem.actionName)
                 }
+                policies={policies}
             />
         </BaseListItem>
     );
diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts
index 7e80c5ebebe5..e9272453c23a 100644
--- a/src/components/SelectionList/types.ts
+++ b/src/components/SelectionList/types.ts
@@ -12,6 +12,7 @@ import type {
     TextStyle,
     ViewStyle,
 } from 'react-native';
+import type {OnyxCollection} from 'react-native-onyx';
 import type {AnimatedStyle} from 'react-native-reanimated';
 import type {SearchRouterItem} from '@components/Search/SearchAutocompleteList';
 import type {SearchColumnType} from '@components/Search/types';
@@ -19,6 +20,7 @@ import type {BrickRoad} from '@libs/WorkspacesSettingsUtils';
 // eslint-disable-next-line no-restricted-imports
 import type CursorStyles from '@styles/utils/cursor/types';
 import type CONST from '@src/CONST';
+import type {Policy} from '@src/types/onyx';
 import type {Attendee} from '@src/types/onyx/IOU';
 import type {Errors, Icon, PendingAction} from '@src/types/onyx/OnyxCommon';
 import type {SearchPersonalDetails, SearchReport, SearchReportAction, SearchTransaction} from '@src/types/onyx/SearchResults';
@@ -362,6 +364,9 @@ type ReportListItemProps<TItem extends ListItem> = ListItemProps<TItem> & {
 
 type ChatListItemProps<TItem extends ListItem> = ListItemProps<TItem> & {
     queryJSONHash?: number;
+
+    /** The policies which the user has access to */
+    policies: OnyxCollection<Policy>;
 };
 
 type ValidListItem =
diff --git a/src/pages/home/report/PureReportActionItem.tsx b/src/pages/home/report/PureReportActionItem.tsx
index b9e74bfc4ac8..9d63e67f03c6 100644
--- a/src/pages/home/report/PureReportActionItem.tsx
+++ b/src/pages/home/report/PureReportActionItem.tsx
@@ -3,7 +3,7 @@ import mapValues from 'lodash/mapValues';
 import React, {memo, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
 import type {GestureResponderEvent, TextInput} from 'react-native';
 import {InteractionManager, Keyboard, View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
+import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
 import type {ValueOf} from 'type-fest';
 import type {Emoji} from '@assets/emojis/types';
 import {AttachmentContext} from '@components/AttachmentContext';
@@ -326,6 +326,9 @@ type PureReportActionItemProps = {
 
     /** A message related to a report action that has been automatically forwarded */
     reportAutomaticallyForwardedMessage?: string;
+
+    /** Policies */
+    policies?: OnyxCollection<OnyxTypes.Policy>;
 };
 
 // This is equivalent to returning a negative boolean in normal functions, but we can keep the element return type
@@ -397,6 +400,7 @@ function PureReportActionItem({
     dismissTrackExpenseActionableWhisper = () => {},
     userBillingFundID,
     reportAutomaticallyForwardedMessage,
+    policies,
 }: PureReportActionItemProps) {
     const {translate} = useLocalize();
     const {shouldUseNarrowLayout} = useResponsiveLayout();
@@ -1199,6 +1203,7 @@ function PureReportActionItem({
                     hasBeenFlagged={
                         ![CONST.MODERATION.MODERATOR_DECISION_APPROVED, CONST.MODERATION.MODERATOR_DECISION_PENDING].some((item) => item === moderationDecision) && !isPendingRemove(action)
                     }
+                    policies={policies}
                 >
                     {content}
                 </ReportActionItemSingle>
diff --git a/src/pages/home/report/ReportActionItemSingle.tsx b/src/pages/home/report/ReportActionItemSingle.tsx
index 8cac03f609e3..e889099a6313 100644
--- a/src/pages/home/report/ReportActionItemSingle.tsx
+++ b/src/pages/home/report/ReportActionItemSingle.tsx
@@ -1,7 +1,7 @@
 import React, {useCallback, useMemo} from 'react';
 import type {StyleProp, ViewStyle} from 'react-native';
 import {View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
+import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
 import Avatar from '@components/Avatar';
 import {FallbackAvatar} from '@components/Icon/Expensicons';
 import MultipleAvatars from '@components/MultipleAvatars';
@@ -39,7 +39,7 @@ import {
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
-import type {Report, ReportAction} from '@src/types/onyx';
+import type {Policy, Report, ReportAction} from '@src/types/onyx';
 import type {Icon} from '@src/types/onyx/OnyxCommon';
 import type ChildrenProps from '@src/types/utils/ChildrenProps';
 import ReportActionItemDate from './ReportActionItemDate';
@@ -72,6 +72,9 @@ type ReportActionItemSingleProps = Partial<ChildrenProps> & {
 
     /** If the action is being actived */
     isActive?: boolean;
+
+    /** Policies */
+    policies?: OnyxCollection<Policy>;
 };
 
 const showUserDetails = (accountID: number | undefined) => {
@@ -96,6 +99,7 @@ function ReportActionItemSingle({
     iouReport,
     isHovered = false,
     isActive = false,
+    policies,
 }: ReportActionItemSingleProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
@@ -107,9 +111,10 @@ function ReportActionItemSingle({
     const ownerAccountID = iouReport?.ownerAccountID ?? action?.childOwnerAccountID;
     const isReportPreviewAction = action?.actionName === CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW;
     const actorAccountID = getReportActionActorAccountID(action, iouReport, report, delegatePersonalDetails);
-    const [invoiceReceiverPolicy] = useOnyx(
-        `${ONYXKEYS.COLLECTION.POLICY}${report?.invoiceReceiver && 'policyID' in report.invoiceReceiver ? report.invoiceReceiver.policyID : CONST.DEFAULT_NUMBER_ID}`,
-    );
+    const invoiceReceiverPolicy =
+        report?.invoiceReceiver && 'policyID' in report.invoiceReceiver
+            ? policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report.invoiceReceiver.policyID}`]
+            : policies?.[`${ONYXKEYS.COLLECTION.POLICY}${CONST.DEFAULT_NUMBER_ID}`];
 
     let displayName = getDisplayNameForParticipant({accountID: actorAccountID, personalDetailsData: personalDetails});
     const {avatar, login, pendingFields, status, fallbackIcon} = personalDetails?.[actorAccountID ?? CONST.DEFAULT_NUMBER_ID] ?? {};

From cd79248833b80a3773a4cfe8982461091127ebcd Mon Sep 17 00:00:00 2001
From: Mykhailo Kravchenko <rezkiy37@gmail.com>
Date: Fri, 11 Apr 2025 12:01:32 +0300
Subject: [PATCH 2/2] Update ChatListItemProps to make policies optional

---
 src/components/SelectionList/types.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts
index e9272453c23a..f02e804c15cd 100644
--- a/src/components/SelectionList/types.ts
+++ b/src/components/SelectionList/types.ts
@@ -366,7 +366,7 @@ type ChatListItemProps<TItem extends ListItem> = ListItemProps<TItem> & {
     queryJSONHash?: number;
 
     /** The policies which the user has access to */
-    policies: OnyxCollection<Policy>;
+    policies?: OnyxCollection<Policy>;
 };
 
 type ValidListItem =
