From ccab1f77ce53ed62b2eb616b384f887dafea5000 Mon Sep 17 00:00:00 2001
From: Ishpaul Singh <ishpaul207@gmail.com>
Date: Sun, 23 Feb 2025 23:11:18 +0530
Subject: [PATCH 01/17] Add close button to product training tooltips and track
 dismissal method

---
 assets/images/x-letter.svg                    | 14 ++++
 src/components/Icon/Expensicons.ts            |  2 +
 .../ProductTrainingContext/TOOLTIPS.ts        | 20 ++---
 .../ProductTrainingContext/index.tsx          | 73 ++++++++++++-------
 src/hooks/useOnboardingFlow.ts                |  4 +-
 .../API/parameters/DismissProductTraining.ts  |  1 +
 src/libs/TooltipUtils.ts                      | 16 ++++
 src/libs/actions/Welcome/index.ts             | 10 ++-
 src/types/onyx/DismissedProductTraining.ts    | 37 ++++++----
 .../ProductTrainingContextProvider.tsx        | 36 ++++++---
 10 files changed, 150 insertions(+), 63 deletions(-)
 create mode 100644 assets/images/x-letter.svg
 create mode 100644 src/libs/TooltipUtils.ts

diff --git a/assets/images/x-letter.svg b/assets/images/x-letter.svg
new file mode 100644
index 000000000000..559b11671e41
--- /dev/null
+++ b/assets/images/x-letter.svg
@@ -0,0 +1,14 @@
+<svg
+  xmlns="http://www.w3.org/2000/svg"
+  width="24"
+  height="24"
+  viewBox="0 0 24 24"
+  fill="none"
+  stroke="currentColor"
+  stroke-width="2"
+  stroke-linecap="round"
+  stroke-linejoin="round"
+>
+  <line x1="18" y1="6" x2="6" y2="18" />
+  <line x1="6" y1="6" x2="18" y2="18" />
+</svg>
diff --git a/src/components/Icon/Expensicons.ts b/src/components/Icon/Expensicons.ts
index db5c81a0cfc3..0f42d1201be8 100644
--- a/src/components/Icon/Expensicons.ts
+++ b/src/components/Icon/Expensicons.ts
@@ -213,6 +213,7 @@ import Workflows from '@assets/images/workflows.svg';
 import Workspace from '@assets/images/workspace-default-avatar.svg';
 import Wrench from '@assets/images/wrench.svg';
 import Clear from '@assets/images/x-circle.svg';
+import CrossX from '@assets/images/x-letter.svg';
 import Zoom from '@assets/images/zoom.svg';
 
 export {
@@ -432,4 +433,5 @@ export {
     Train,
     boltSlash,
     MagnifyingGlassSpyMouthClosed,
+    CrossX,
 };
diff --git a/src/components/ProductTrainingContext/TOOLTIPS.ts b/src/components/ProductTrainingContext/TOOLTIPS.ts
index 90e91166fba7..c8191386eca2 100644
--- a/src/components/ProductTrainingContext/TOOLTIPS.ts
+++ b/src/components/ProductTrainingContext/TOOLTIPS.ts
@@ -25,7 +25,7 @@ type ShouldShowConditionProps = {
 
 type TooltipData = {
     content: Array<{text: TranslationPaths; isBold: boolean}>;
-    onHideTooltip: () => void;
+    onHideTooltip: (isDismissedUsingX?: boolean) => void;
     name: ProductTrainingTooltipName;
     priority: number;
     shouldShow: (props: ShouldShowConditionProps) => boolean;
@@ -38,17 +38,17 @@ const TOOLTIPS: Record<ProductTrainingTooltipName, TooltipData> = {
             {text: 'productTrainingTooltip.conciergeLHNGBR.part1', isBold: false},
             {text: 'productTrainingTooltip.conciergeLHNGBR.part2', isBold: true},
         ],
-        onHideTooltip: () => dismissProductTraining(CONCEIRGE_LHN_GBR),
+        onHideTooltip: (isDismissedUsingX = false) => dismissProductTraining(CONCEIRGE_LHN_GBR, isDismissedUsingX),
         name: CONCEIRGE_LHN_GBR,
         priority: 1300,
-        shouldShow: ({shouldUseNarrowLayout}) => !!shouldUseNarrowLayout,
+        shouldShow: () => true,
     },
     [RENAME_SAVED_SEARCH]: {
         content: [
             {text: 'productTrainingTooltip.saveSearchTooltip.part1', isBold: true},
             {text: 'productTrainingTooltip.saveSearchTooltip.part2', isBold: false},
         ],
-        onHideTooltip: () => dismissProductTraining(RENAME_SAVED_SEARCH),
+        onHideTooltip: (isDismissedUsingX = false) => dismissProductTraining(RENAME_SAVED_SEARCH, isDismissedUsingX),
         name: RENAME_SAVED_SEARCH,
         priority: 1250,
         shouldShow: ({shouldUseNarrowLayout}) => !shouldUseNarrowLayout,
@@ -59,7 +59,7 @@ const TOOLTIPS: Record<ProductTrainingTooltipName, TooltipData> = {
             {text: 'productTrainingTooltip.globalCreateTooltip.part2', isBold: false},
             {text: 'productTrainingTooltip.globalCreateTooltip.part3', isBold: false},
         ],
-        onHideTooltip: () => dismissProductTraining(GLOBAL_CREATE_TOOLTIP),
+        onHideTooltip: (isDismissedUsingX = false) => dismissProductTraining(GLOBAL_CREATE_TOOLTIP, isDismissedUsingX),
         name: GLOBAL_CREATE_TOOLTIP,
         priority: 1200,
         shouldShow: () => true,
@@ -69,7 +69,7 @@ const TOOLTIPS: Record<ProductTrainingTooltipName, TooltipData> = {
             {text: 'productTrainingTooltip.quickActionButton.part1', isBold: true},
             {text: 'productTrainingTooltip.quickActionButton.part2', isBold: false},
         ],
-        onHideTooltip: () => dismissProductTraining(QUICK_ACTION_BUTTON),
+        onHideTooltip: (isDismissedUsingX = false) => dismissProductTraining(QUICK_ACTION_BUTTON, isDismissedUsingX),
         name: QUICK_ACTION_BUTTON,
         priority: 1150,
         shouldShow: () => true,
@@ -80,7 +80,7 @@ const TOOLTIPS: Record<ProductTrainingTooltipName, TooltipData> = {
             {text: 'productTrainingTooltip.workspaceChatCreate.part2', isBold: true},
             {text: 'productTrainingTooltip.workspaceChatCreate.part3', isBold: false},
         ],
-        onHideTooltip: () => dismissProductTraining(WORKSAPCE_CHAT_CREATE),
+        onHideTooltip: (isDismissedUsingX = false) => dismissProductTraining(WORKSAPCE_CHAT_CREATE, isDismissedUsingX),
         name: WORKSAPCE_CHAT_CREATE,
         priority: 1100,
         shouldShow: () => true,
@@ -90,7 +90,7 @@ const TOOLTIPS: Record<ProductTrainingTooltipName, TooltipData> = {
             {text: 'productTrainingTooltip.searchFilterButtonTooltip.part1', isBold: true},
             {text: 'productTrainingTooltip.searchFilterButtonTooltip.part2', isBold: false},
         ],
-        onHideTooltip: () => dismissProductTraining(SEARCH_FILTER_BUTTON_TOOLTIP),
+        onHideTooltip: (isDismissedUsingX = false) => dismissProductTraining(SEARCH_FILTER_BUTTON_TOOLTIP, isDismissedUsingX),
         name: SEARCH_FILTER_BUTTON_TOOLTIP,
         priority: 1000,
         shouldShow: () => true,
@@ -101,7 +101,7 @@ const TOOLTIPS: Record<ProductTrainingTooltipName, TooltipData> = {
             {text: 'productTrainingTooltip.bottomNavInboxTooltip.part2', isBold: false},
             {text: 'productTrainingTooltip.bottomNavInboxTooltip.part3', isBold: false},
         ],
-        onHideTooltip: () => dismissProductTraining(BOTTOM_NAV_INBOX_TOOLTIP),
+        onHideTooltip: (isDismissedUsingX = false) => dismissProductTraining(BOTTOM_NAV_INBOX_TOOLTIP, isDismissedUsingX),
         name: BOTTOM_NAV_INBOX_TOOLTIP,
         priority: 900,
         shouldShow: () => true,
@@ -112,7 +112,7 @@ const TOOLTIPS: Record<ProductTrainingTooltipName, TooltipData> = {
             {text: 'productTrainingTooltip.workspaceChatTooltip.part2', isBold: false},
             {text: 'productTrainingTooltip.workspaceChatTooltip.part3', isBold: false},
         ],
-        onHideTooltip: () => dismissProductTraining(LHN_WORKSPACE_CHAT_TOOLTIP),
+        onHideTooltip: (isDismissedUsingX = false) => dismissProductTraining(LHN_WORKSPACE_CHAT_TOOLTIP, isDismissedUsingX),
         name: LHN_WORKSPACE_CHAT_TOOLTIP,
         priority: 800,
         shouldShow: () => true,
diff --git a/src/components/ProductTrainingContext/index.tsx b/src/components/ProductTrainingContext/index.tsx
index 474741cbda42..6cec81377993 100644
--- a/src/components/ProductTrainingContext/index.tsx
+++ b/src/components/ProductTrainingContext/index.tsx
@@ -4,6 +4,7 @@ import {useOnyx} from 'react-native-onyx';
 import Button from '@components/Button';
 import Icon from '@components/Icon';
 import * as Expensicons from '@components/Icon/Expensicons';
+import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
 import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
@@ -12,6 +13,7 @@ import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {parseFSAttributes} from '@libs/Fullstory';
 import {hasCompletedGuidedSetupFlowSelector} from '@libs/onboardingSelectors';
+import {isProductTrainingElementDismissed} from '@libs/TooltipUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type ChildrenProps from '@src/types/utils/ChildrenProps';
@@ -98,7 +100,7 @@ function ProductTrainingContextProvider({children}: ChildrenProps) {
                 return false;
             }
 
-            const isDismissed = !!dismissedProductTraining?.[tooltipName];
+            const isDismissed = isProductTrainingElementDismissed(tooltipName, dismissedProductTraining);
 
             if (isDismissed) {
                 return false;
@@ -203,6 +205,22 @@ const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shou
      */
     useLayoutEffect(parseFSAttributes, []);
 
+    const shouldShowProductTrainingTooltip = useMemo(() => {
+        return shouldShow && shouldRenderTooltip(tooltipName) && !shouldHideToolTip;
+    }, [shouldRenderTooltip, tooltipName, shouldShow, shouldHideToolTip]);
+
+    const hideProductTrainingTooltip = useCallback(
+        (isDismissedUsingX = false) => {
+            if (!shouldShowProductTrainingTooltip) {
+                return;
+            }
+            const tooltip = TOOLTIPS[tooltipName];
+            tooltip.onHideTooltip(isDismissedUsingX);
+            unregisterTooltip(tooltipName);
+        },
+        [tooltipName, shouldShowProductTrainingTooltip, unregisterTooltip],
+    );
+
     const renderProductTrainingTooltip = useCallback(() => {
         const tooltip = TOOLTIPS[tooltipName];
         return (
@@ -239,6 +257,20 @@ const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shou
                             );
                         })}
                     </Text>
+                    <PressableWithoutFeedback
+                        onPress={() => {
+                            hideProductTrainingTooltip(true);
+                        }}
+                        style={[styles.flexRow, styles.alignItemsCenter, styles.flex1]}
+                        accessibilityLabel={translate('productTrainingTooltip.scanTestTooltip.noThanks')}
+                        role={CONST.ROLE.BUTTON}
+                    >
+                        <Icon
+                            src={Expensicons.Clear}
+                            fill={theme.icon}
+                            medium
+                        />
+                    </PressableWithoutFeedback>
                 </View>
                 {!!tooltip?.shouldRenderActionButtons && (
                     <View style={[styles.alignItemsCenter, styles.justifyContentBetween, styles.flexRow, styles.ph2, styles.pv2, styles.gap2]}>
@@ -258,43 +290,32 @@ const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shou
             </View>
         );
     }, [
-        config.onConfirm,
-        config.onDismiss,
+        tooltipName,
         styles.alignItemsCenter,
-        styles.flex1,
         styles.flexRow,
+        styles.justifyContentStart,
+        styles.justifyContentCenter,
         styles.flexWrap,
+        styles.textAlignCenter,
         styles.gap3,
-        styles.justifyContentBetween,
-        styles.justifyContentCenter,
-        styles.mw100,
         styles.p2,
         styles.productTrainingTooltipText,
-        styles.pv2,
-        styles.textAlignCenter,
-        styles.textBold,
         styles.textWrap,
-        styles.gap2,
-        styles.justifyContentStart,
+        styles.mw100,
+        styles.flex1,
+        styles.justifyContentBetween,
         styles.ph2,
+        styles.pv2,
+        styles.gap2,
+        styles.textBold,
         theme.tooltipHighlightText,
-        tooltipName,
+        theme.icon,
         translate,
+        config.onConfirm,
+        config.onDismiss,
+        hideProductTrainingTooltip,
     ]);
 
-    const shouldShowProductTrainingTooltip = useMemo(() => {
-        return shouldShow && shouldRenderTooltip(tooltipName) && !shouldHideToolTip;
-    }, [shouldRenderTooltip, tooltipName, shouldShow, shouldHideToolTip]);
-
-    const hideProductTrainingTooltip = useCallback(() => {
-        if (!shouldShowProductTrainingTooltip) {
-            return;
-        }
-        const tooltip = TOOLTIPS[tooltipName];
-        tooltip.onHideTooltip();
-        unregisterTooltip(tooltipName);
-    }, [tooltipName, shouldShowProductTrainingTooltip, unregisterTooltip]);
-
     return {
         renderProductTrainingTooltip,
         hideProductTrainingTooltip,
diff --git a/src/hooks/useOnboardingFlow.ts b/src/hooks/useOnboardingFlow.ts
index 0aaa8ddad9d0..cf45cd9ae9d5 100644
--- a/src/hooks/useOnboardingFlow.ts
+++ b/src/hooks/useOnboardingFlow.ts
@@ -6,6 +6,7 @@ import {startOnboardingFlow} from '@libs/actions/Welcome/OnboardingFlow';
 import Navigation from '@libs/Navigation/Navigation';
 import {hasCompletedGuidedSetupFlowSelector, tryNewDotOnyxSelector} from '@libs/onboardingSelectors';
 import {buildCannedSearchQuery} from '@libs/SearchQueryUtils';
+import {isProductTrainingElementDismissed} from '@libs/TooltipUtils';
 import CONFIG from '@src/CONFIG';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
@@ -45,8 +46,7 @@ function useOnboardingFlowRouter() {
             if (CONFIG.IS_HYBRID_APP && isLoadingOnyxValue(isSingleNewDotEntryMetadata)) {
                 return;
             }
-
-            if (hasBeenAddedToNudgeMigration && !dismissedProductTraining?.migratedUserWelcomeModal) {
+            if (hasBeenAddedToNudgeMigration && !isProductTrainingElementDismissed('migratedUserWelcomeModal', dismissedProductTraining)) {
                 const defaultCannedQuery = buildCannedSearchQuery();
                 const query = defaultCannedQuery;
                 Navigation.navigate(ROUTES.SEARCH_ROOT.getRoute({query}));
diff --git a/src/libs/API/parameters/DismissProductTraining.ts b/src/libs/API/parameters/DismissProductTraining.ts
index 6a82ad995294..f3c066a5f948 100644
--- a/src/libs/API/parameters/DismissProductTraining.ts
+++ b/src/libs/API/parameters/DismissProductTraining.ts
@@ -1,5 +1,6 @@
 type DismissProductTrainingParams = {
     name: string;
+    dismissedMethod: 'x' | 'click';
 };
 
 export default DismissProductTrainingParams;
diff --git a/src/libs/TooltipUtils.ts b/src/libs/TooltipUtils.ts
new file mode 100644
index 000000000000..16607c434553
--- /dev/null
+++ b/src/libs/TooltipUtils.ts
@@ -0,0 +1,16 @@
+import Onyx from 'react-native-onyx';
+import type {OnyxEntry} from 'react-native-onyx';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {DismissedProductTraining} from '@src/types/onyx';
+
+let nvpDismissedProductTraining: OnyxEntry<DismissedProductTraining>;
+Onyx.connect({
+    key: ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING,
+    callback: (value) => (nvpDismissedProductTraining = value),
+});
+
+function isProductTrainingElementDismissed(elementName: keyof DismissedProductTraining, dismissedProductTraining: OnyxEntry<DismissedProductTraining> = nvpDismissedProductTraining) {
+    return typeof dismissedProductTraining?.[elementName] === 'string' ? !!dismissedProductTraining?.[elementName] : !!dismissedProductTraining?.[elementName]?.dismissedTime;
+}
+
+export {isProductTrainingElementDismissed};
diff --git a/src/libs/actions/Welcome/index.ts b/src/libs/actions/Welcome/index.ts
index a98b600e5baf..fe66940eea0a 100644
--- a/src/libs/actions/Welcome/index.ts
+++ b/src/libs/actions/Welcome/index.ts
@@ -207,18 +207,22 @@ function setSelfTourViewed(shouldUpdateOnyxDataOnlyLocally = false) {
     API.write(WRITE_COMMANDS.SELF_TOUR_VIEWED, null, {optimisticData});
 }
 
-function dismissProductTraining(elementName: string) {
+function dismissProductTraining(elementName: string, isDismissedUsingX = false) {
     const date = new Date();
+    const dismissedMethod = isDismissedUsingX ? 'x' : 'click';
     const optimisticData = [
         {
             onyxMethod: Onyx.METHOD.MERGE,
             key: ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING,
             value: {
-                [elementName]: DateUtils.getDBTime(date.valueOf()),
+                [elementName]: {
+                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
+                    dismissedMethod
+                },
             },
         },
     ];
-    API.write(WRITE_COMMANDS.DISMISS_PRODUCT_TRAINING, {name: elementName}, {optimisticData});
+    API.write(WRITE_COMMANDS.DISMISS_PRODUCT_TRAINING, {name: elementName, dismissedMethod}, {optimisticData});
 }
 
 export {
diff --git a/src/types/onyx/DismissedProductTraining.ts b/src/types/onyx/DismissedProductTraining.ts
index 283c660be2e1..be1f886a4320 100644
--- a/src/types/onyx/DismissedProductTraining.ts
+++ b/src/types/onyx/DismissedProductTraining.ts
@@ -13,6 +13,17 @@ const {
     SCAN_TEST_TOOLTIP_MANAGER,
     SCAN_TEST_CONFIRMATION,
 } = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES;
+
+/**
+ * This type is used to store the timestamp of when the user dismisses a product training ui elements.
+ */
+type DismissedProductTrainingElement = {
+    /** The timestamp of when the user dismissed the product training element. */
+    dismissedTime: string;
+
+    /** The method of how the user dismissed the product training element, click or x. */
+    dismissedMethod: 'click' | 'x';
+};
 /**
  * This type is used to store the timestamp of when the user dismisses a product training ui elements.
  */
@@ -20,67 +31,67 @@ type DismissedProductTraining = {
     /**
      * When user dismisses the nudgeMigration Welcome Modal, we store the timestamp here.
      */
-    [CONST.MIGRATED_USER_WELCOME_MODAL]: string;
+    [CONST.MIGRATED_USER_WELCOME_MODAL]: DismissedProductTrainingElement;
 
     /**
      * When user dismisses the conciergeLHNGBR product training tooltip, we store the timestamp here.
      */
-    [CONCEIRGE_LHN_GBR]: string;
+    [CONCEIRGE_LHN_GBR]: DismissedProductTrainingElement;
 
     /**
      * When user dismisses the renameSavedSearch product training tooltip, we store the timestamp here.
      */
-    [RENAME_SAVED_SEARCH]: string;
+    [RENAME_SAVED_SEARCH]: DismissedProductTrainingElement;
 
     /**
      * When user dismisses the workspaceChatCreate product training tooltip, we store the timestamp here.
      */
-    [WORKSAPCE_CHAT_CREATE]: string;
+    [WORKSAPCE_CHAT_CREATE]: DismissedProductTrainingElement;
 
     /**
      * When user dismisses the quickActionButton product training tooltip, we store the timestamp here.
      */
-    [QUICK_ACTION_BUTTON]: string;
+    [QUICK_ACTION_BUTTON]: DismissedProductTrainingElement;
 
     /**
      * When user dismisses the searchFilterButtonTooltip product training tooltip, we store the timestamp here.
      */
-    [SEARCH_FILTER_BUTTON_TOOLTIP]: string;
+    [SEARCH_FILTER_BUTTON_TOOLTIP]: DismissedProductTrainingElement;
 
     /**
      * When user dismisses the bottomNavInboxTooltip product training tooltip, we store the timestamp here.
      */
-    [BOTTOM_NAV_INBOX_TOOLTIP]: string;
+    [BOTTOM_NAV_INBOX_TOOLTIP]: DismissedProductTrainingElement;
 
     /**
      * When user dismisses the lhnWorkspaceChatTooltip product training tooltip, we store the timestamp here.
      */
-    [LHN_WORKSPACE_CHAT_TOOLTIP]: string;
+    [LHN_WORKSPACE_CHAT_TOOLTIP]: DismissedProductTrainingElement;
 
     /**
      * When user dismisses the globalCreateTooltip product training tooltip, we store the timestamp here.
      */
-    [GLOBAL_CREATE_TOOLTIP]: string;
+    [GLOBAL_CREATE_TOOLTIP]: DismissedProductTrainingElement;
 
     /**
      * When user dismisses the globalCreateTooltip product training tooltip, we store the timestamp here.
      */
-    [SCAN_TEST_TOOLTIP]: string;
+    [SCAN_TEST_TOOLTIP]: DismissedProductTrainingElement;
 
     /**
      * When user dismisses the test manager tooltip product training tooltip, we store the timestamp here.
      */
-    [SCAN_TEST_TOOLTIP_MANAGER]: string;
+    [SCAN_TEST_TOOLTIP_MANAGER]: DismissedProductTrainingElement;
 
     /**
      * When user dismisses the test manager on confirmantion page product training tooltip, we store the timestamp here.
      */
-    [SCAN_TEST_CONFIRMATION]: string;
+    [SCAN_TEST_CONFIRMATION]: DismissedProductTrainingElement;
 
     /**
      * When user dismisses the ChangeReportPolicy feature training modal, we store the timestamp here.
      */
-    [CONST.CHANGE_POLICY_TRAINING_MODAL]: string;
+    [CONST.CHANGE_POLICY_TRAINING_MODAL]: DismissedProductTrainingElement;
 };
 
 export default DismissedProductTraining;
diff --git a/tests/ui/components/ProductTrainingContextProvider.tsx b/tests/ui/components/ProductTrainingContextProvider.tsx
index 6bc131f80be2..0d25e70cf4bb 100644
--- a/tests/ui/components/ProductTrainingContextProvider.tsx
+++ b/tests/ui/components/ProductTrainingContextProvider.tsx
@@ -129,7 +129,9 @@ describe('ProductTrainingContextProvider', () => {
             Onyx.merge(ONYXKEYS.NVP_TRYNEWDOT, {nudgeMigration: {timestamp: new Date()}});
             const date = new Date();
             Onyx.set(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
-                migratedUserWelcomeModal: DateUtils.getDBTime(date.valueOf()),
+                migratedUserWelcomeModal: {
+                    dismissedTime: DateUtils.getDBTime(date.valueOf())
+                },
             });
             await waitForBatchedUpdatesWithAct();
 
@@ -148,8 +150,12 @@ describe('ProductTrainingContextProvider', () => {
             Onyx.merge(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: true});
             const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.GLOBAL_CREATE_TOOLTIP;
             Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
-                migratedUserWelcomeModal: DateUtils.getDBTime(date.valueOf()),
-                [testTooltip]: DateUtils.getDBTime(date.valueOf()),
+                migratedUserWelcomeModal: {
+                    dismissedTime: DateUtils.getDBTime(date.valueOf())
+                },
+                [testTooltip]: {
+                    dismissedTime: DateUtils.getDBTime(date.valueOf())
+                },
             });
             await waitForBatchedUpdatesWithAct();
 
@@ -164,7 +170,9 @@ describe('ProductTrainingContextProvider', () => {
             Onyx.merge(ONYXKEYS.NVP_TRYNEWDOT, {nudgeMigration: {timestamp: new Date()}});
             const date = new Date();
             Onyx.set(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
-                migratedUserWelcomeModal: DateUtils.getDBTime(date.valueOf()),
+                migratedUserWelcomeModal: {
+                    dismissedTime: DateUtils.getDBTime(date.valueOf())
+                },
             });
             await waitForBatchedUpdatesWithAct();
             const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.GLOBAL_CREATE_TOOLTIP;
@@ -238,7 +246,9 @@ describe('ProductTrainingContextProvider', () => {
             Onyx.merge(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: true});
             const date = new Date();
             Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
-                migratedUserWelcomeModal: DateUtils.getDBTime(date.valueOf()),
+                migratedUserWelcomeModal: {
+                    dismissedTime: DateUtils.getDBTime(date.valueOf())
+                },
             });
             await waitForBatchedUpdatesWithAct();
 
@@ -267,8 +277,12 @@ describe('ProductTrainingContextProvider', () => {
             const lowPriorityTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SEARCH_FILTER_BUTTON_TOOLTIP;
 
             Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
-                migratedUserWelcomeModal: DateUtils.getDBTime(date.valueOf()),
-                [highPriorityTooltip]: DateUtils.getDBTime(date.valueOf()),
+                migratedUserWelcomeModal: {
+                    dismissedTime: DateUtils.getDBTime(date.valueOf())
+                },
+                [highPriorityTooltip]: {
+                    dismissedTime: DateUtils.getDBTime(date.valueOf())
+                },
             });
             await waitForBatchedUpdatesWithAct();
 
@@ -291,7 +305,9 @@ describe('ProductTrainingContextProvider', () => {
             Onyx.merge(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: true});
             const date = new Date();
             Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
-                migratedUserWelcomeModal: DateUtils.getDBTime(date.valueOf()),
+                migratedUserWelcomeModal: {
+                    dismissedTime: DateUtils.getDBTime(date.valueOf())
+                },
             });
             await waitForBatchedUpdatesWithAct();
 
@@ -312,7 +328,9 @@ describe('ProductTrainingContextProvider', () => {
 
             // When dismissing higher priority tooltip
             Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
-                [highPriorityTooltip]: DateUtils.getDBTime(date.valueOf()),
+                [highPriorityTooltip]: {
+                    dismissedTime: DateUtils.getDBTime(date.valueOf())
+                },
             });
             await waitForBatchedUpdatesWithAct();
 

From 322e143e261d9569fadce12ede5cdef33eed51c9 Mon Sep 17 00:00:00 2001
From: Ishpaul Singh <ishpaul207@gmail.com>
Date: Wed, 19 Mar 2025 03:54:23 +0530
Subject: [PATCH 02/17] prettier

---
 src/libs/actions/Welcome/index.ts              |  2 +-
 .../ProductTrainingContextProvider.tsx         | 18 +++++++++---------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/libs/actions/Welcome/index.ts b/src/libs/actions/Welcome/index.ts
index fe66940eea0a..7a4552550149 100644
--- a/src/libs/actions/Welcome/index.ts
+++ b/src/libs/actions/Welcome/index.ts
@@ -217,7 +217,7 @@ function dismissProductTraining(elementName: string, isDismissedUsingX = false)
             value: {
                 [elementName]: {
                     dismissedTime: DateUtils.getDBTime(date.valueOf()),
-                    dismissedMethod
+                    dismissedMethod,
                 },
             },
         },
diff --git a/tests/ui/components/ProductTrainingContextProvider.tsx b/tests/ui/components/ProductTrainingContextProvider.tsx
index 0d25e70cf4bb..c8a6abeee3cc 100644
--- a/tests/ui/components/ProductTrainingContextProvider.tsx
+++ b/tests/ui/components/ProductTrainingContextProvider.tsx
@@ -130,7 +130,7 @@ describe('ProductTrainingContextProvider', () => {
             const date = new Date();
             Onyx.set(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
                 migratedUserWelcomeModal: {
-                    dismissedTime: DateUtils.getDBTime(date.valueOf())
+                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
                 },
             });
             await waitForBatchedUpdatesWithAct();
@@ -151,10 +151,10 @@ describe('ProductTrainingContextProvider', () => {
             const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.GLOBAL_CREATE_TOOLTIP;
             Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
                 migratedUserWelcomeModal: {
-                    dismissedTime: DateUtils.getDBTime(date.valueOf())
+                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
                 },
                 [testTooltip]: {
-                    dismissedTime: DateUtils.getDBTime(date.valueOf())
+                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
                 },
             });
             await waitForBatchedUpdatesWithAct();
@@ -171,7 +171,7 @@ describe('ProductTrainingContextProvider', () => {
             const date = new Date();
             Onyx.set(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
                 migratedUserWelcomeModal: {
-                    dismissedTime: DateUtils.getDBTime(date.valueOf())
+                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
                 },
             });
             await waitForBatchedUpdatesWithAct();
@@ -247,7 +247,7 @@ describe('ProductTrainingContextProvider', () => {
             const date = new Date();
             Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
                 migratedUserWelcomeModal: {
-                    dismissedTime: DateUtils.getDBTime(date.valueOf())
+                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
                 },
             });
             await waitForBatchedUpdatesWithAct();
@@ -278,10 +278,10 @@ describe('ProductTrainingContextProvider', () => {
 
             Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
                 migratedUserWelcomeModal: {
-                    dismissedTime: DateUtils.getDBTime(date.valueOf())
+                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
                 },
                 [highPriorityTooltip]: {
-                    dismissedTime: DateUtils.getDBTime(date.valueOf())
+                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
                 },
             });
             await waitForBatchedUpdatesWithAct();
@@ -306,7 +306,7 @@ describe('ProductTrainingContextProvider', () => {
             const date = new Date();
             Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
                 migratedUserWelcomeModal: {
-                    dismissedTime: DateUtils.getDBTime(date.valueOf())
+                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
                 },
             });
             await waitForBatchedUpdatesWithAct();
@@ -329,7 +329,7 @@ describe('ProductTrainingContextProvider', () => {
             // When dismissing higher priority tooltip
             Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
                 [highPriorityTooltip]: {
-                    dismissedTime: DateUtils.getDBTime(date.valueOf())
+                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
                 },
             });
             await waitForBatchedUpdatesWithAct();

From e0ad3575695eee5fb499e352a4b0138181247cea Mon Sep 17 00:00:00 2001
From: Ishpaul Singh <ishpaul207@gmail.com>
Date: Wed, 19 Mar 2025 03:58:45 +0530
Subject: [PATCH 03/17] fix tests

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

diff --git a/src/components/ProductTrainingContext/TOOLTIPS.ts b/src/components/ProductTrainingContext/TOOLTIPS.ts
index c8191386eca2..de511e2f6c8c 100644
--- a/src/components/ProductTrainingContext/TOOLTIPS.ts
+++ b/src/components/ProductTrainingContext/TOOLTIPS.ts
@@ -41,7 +41,7 @@ const TOOLTIPS: Record<ProductTrainingTooltipName, TooltipData> = {
         onHideTooltip: (isDismissedUsingX = false) => dismissProductTraining(CONCEIRGE_LHN_GBR, isDismissedUsingX),
         name: CONCEIRGE_LHN_GBR,
         priority: 1300,
-        shouldShow: () => true,
+        shouldShow: ({shouldUseNarrowLayout}) => !!shouldUseNarrowLayout,
     },
     [RENAME_SAVED_SEARCH]: {
         content: [

From 462a06923d45def74f7e9ae81e312ffaa6210549 Mon Sep 17 00:00:00 2001
From: Ishpaul Singh <ishpaul207@gmail.com>
Date: Wed, 19 Mar 2025 04:08:51 +0530
Subject: [PATCH 04/17] fix lint

---
 src/components/ProductTrainingContext/index.tsx | 2 +-
 src/hooks/useOnboardingFlow.ts                  | 2 +-
 src/libs/TooltipUtils.ts                        | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/components/ProductTrainingContext/index.tsx b/src/components/ProductTrainingContext/index.tsx
index 6cec81377993..cde84d94bbc8 100644
--- a/src/components/ProductTrainingContext/index.tsx
+++ b/src/components/ProductTrainingContext/index.tsx
@@ -13,7 +13,7 @@ import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {parseFSAttributes} from '@libs/Fullstory';
 import {hasCompletedGuidedSetupFlowSelector} from '@libs/onboardingSelectors';
-import {isProductTrainingElementDismissed} from '@libs/TooltipUtils';
+import isProductTrainingElementDismissed from '@libs/TooltipUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type ChildrenProps from '@src/types/utils/ChildrenProps';
diff --git a/src/hooks/useOnboardingFlow.ts b/src/hooks/useOnboardingFlow.ts
index cf45cd9ae9d5..811a1dae4d2e 100644
--- a/src/hooks/useOnboardingFlow.ts
+++ b/src/hooks/useOnboardingFlow.ts
@@ -6,7 +6,7 @@ import {startOnboardingFlow} from '@libs/actions/Welcome/OnboardingFlow';
 import Navigation from '@libs/Navigation/Navigation';
 import {hasCompletedGuidedSetupFlowSelector, tryNewDotOnyxSelector} from '@libs/onboardingSelectors';
 import {buildCannedSearchQuery} from '@libs/SearchQueryUtils';
-import {isProductTrainingElementDismissed} from '@libs/TooltipUtils';
+import isProductTrainingElementDismissed from '@libs/TooltipUtils';
 import CONFIG from '@src/CONFIG';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
diff --git a/src/libs/TooltipUtils.ts b/src/libs/TooltipUtils.ts
index 16607c434553..b262d21adb8f 100644
--- a/src/libs/TooltipUtils.ts
+++ b/src/libs/TooltipUtils.ts
@@ -13,4 +13,4 @@ function isProductTrainingElementDismissed(elementName: keyof DismissedProductTr
     return typeof dismissedProductTraining?.[elementName] === 'string' ? !!dismissedProductTraining?.[elementName] : !!dismissedProductTraining?.[elementName]?.dismissedTime;
 }
 
-export {isProductTrainingElementDismissed};
+export default isProductTrainingElementDismissed;

From c214dbbd94c486d647f55270674a489db1e425d5 Mon Sep 17 00:00:00 2001
From: Ishpaul Singh <ishpaul207@gmail.com>
Date: Wed, 19 Mar 2025 04:16:37 +0530
Subject: [PATCH 05/17] fix type error

---
 src/libs/actions/Report.ts         | 2 +-
 tests/unit/OptionsListUtilsTest.ts | 4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts
index 660926815b25..fa2284542f53 100644
--- a/src/libs/actions/Report.ts
+++ b/src/libs/actions/Report.ts
@@ -4861,7 +4861,7 @@ function dismissChangePolicyModal() {
             },
         },
     ];
-    API.write(WRITE_COMMANDS.DISMISS_PRODUCT_TRAINING, {name: CONST.CHANGE_POLICY_TRAINING_MODAL}, {optimisticData});
+    API.write(WRITE_COMMANDS.DISMISS_PRODUCT_TRAINING, {name: CONST.CHANGE_POLICY_TRAINING_MODAL, dismissedMethod: 'click'}, {optimisticData});
 }
 
 /**
diff --git a/tests/unit/OptionsListUtilsTest.ts b/tests/unit/OptionsListUtilsTest.ts
index 6da927490eeb..3713855a164c 100644
--- a/tests/unit/OptionsListUtilsTest.ts
+++ b/tests/unit/OptionsListUtilsTest.ts
@@ -684,7 +684,9 @@ describe('OptionsListUtils', () => {
         expect(options.personalDetails).not.toEqual(expect.arrayContaining([expect.objectContaining({login: CONST.EMAIL.MANAGER_MCTEST})]));
 
         return waitForBatchedUpdates()
-            .then(() => Onyx.set(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {[CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP]: new Date() as unknown as string}))
+            .then(() => Onyx.set(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {[CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP]: {
+                dismissedTime: DateUtils.getDBTime(new Date().valueOf()),
+            }}))
             .then(() => {
                 // Manager McTest shouldn't be included to recipients when the user has already submitted an expense
                 const optionsWhenUserAlreadySubmittedExpense = getValidOptions(

From fedbd1d4f2772b1ebbf00dd6c80389de5c236fcd Mon Sep 17 00:00:00 2001
From: Ishpaul Singh <ishpaul207@gmail.com>
Date: Wed, 19 Mar 2025 23:08:59 +0530
Subject: [PATCH 06/17] fix as per comments

---
 src/libs/TooltipUtils.ts                       |  2 +-
 src/libs/actions/Welcome/index.ts              |  2 +-
 src/types/onyx/DismissedProductTraining.ts     |  4 ++--
 .../ProductTrainingContextProvider.tsx         | 18 +++++++++---------
 tests/unit/OptionsListUtilsTest.ts             | 10 +++++++---
 5 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/src/libs/TooltipUtils.ts b/src/libs/TooltipUtils.ts
index b262d21adb8f..f77dbe95fb6c 100644
--- a/src/libs/TooltipUtils.ts
+++ b/src/libs/TooltipUtils.ts
@@ -10,7 +10,7 @@ Onyx.connect({
 });
 
 function isProductTrainingElementDismissed(elementName: keyof DismissedProductTraining, dismissedProductTraining: OnyxEntry<DismissedProductTraining> = nvpDismissedProductTraining) {
-    return typeof dismissedProductTraining?.[elementName] === 'string' ? !!dismissedProductTraining?.[elementName] : !!dismissedProductTraining?.[elementName]?.dismissedTime;
+    return typeof dismissedProductTraining?.[elementName] === 'string' ? !!dismissedProductTraining?.[elementName] : !!dismissedProductTraining?.[elementName]?.timestamp;
 }
 
 export default isProductTrainingElementDismissed;
diff --git a/src/libs/actions/Welcome/index.ts b/src/libs/actions/Welcome/index.ts
index 7a4552550149..3f31d58ce490 100644
--- a/src/libs/actions/Welcome/index.ts
+++ b/src/libs/actions/Welcome/index.ts
@@ -216,7 +216,7 @@ function dismissProductTraining(elementName: string, isDismissedUsingX = false)
             key: ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING,
             value: {
                 [elementName]: {
-                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
+                    timestamp: DateUtils.getDBTime(date.valueOf()),
                     dismissedMethod,
                 },
             },
diff --git a/src/types/onyx/DismissedProductTraining.ts b/src/types/onyx/DismissedProductTraining.ts
index be1f886a4320..d11672e70296 100644
--- a/src/types/onyx/DismissedProductTraining.ts
+++ b/src/types/onyx/DismissedProductTraining.ts
@@ -19,10 +19,10 @@ const {
  */
 type DismissedProductTrainingElement = {
     /** The timestamp of when the user dismissed the product training element. */
-    dismissedTime: string;
+    timestamp: string;
 
     /** The method of how the user dismissed the product training element, click or x. */
-    dismissedMethod: 'click' | 'x';
+    dismissedMethod: 'click' | 'x' | 'elsewhere';
 };
 /**
  * This type is used to store the timestamp of when the user dismisses a product training ui elements.
diff --git a/tests/ui/components/ProductTrainingContextProvider.tsx b/tests/ui/components/ProductTrainingContextProvider.tsx
index c8a6abeee3cc..d9e2a09023ca 100644
--- a/tests/ui/components/ProductTrainingContextProvider.tsx
+++ b/tests/ui/components/ProductTrainingContextProvider.tsx
@@ -130,7 +130,7 @@ describe('ProductTrainingContextProvider', () => {
             const date = new Date();
             Onyx.set(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
                 migratedUserWelcomeModal: {
-                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
+                    timestamp: DateUtils.getDBTime(date.valueOf()),
                 },
             });
             await waitForBatchedUpdatesWithAct();
@@ -151,10 +151,10 @@ describe('ProductTrainingContextProvider', () => {
             const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.GLOBAL_CREATE_TOOLTIP;
             Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
                 migratedUserWelcomeModal: {
-                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
+                    timestamp: DateUtils.getDBTime(date.valueOf()),
                 },
                 [testTooltip]: {
-                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
+                    timestamp: DateUtils.getDBTime(date.valueOf()),
                 },
             });
             await waitForBatchedUpdatesWithAct();
@@ -171,7 +171,7 @@ describe('ProductTrainingContextProvider', () => {
             const date = new Date();
             Onyx.set(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
                 migratedUserWelcomeModal: {
-                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
+                    timestamp: DateUtils.getDBTime(date.valueOf()),
                 },
             });
             await waitForBatchedUpdatesWithAct();
@@ -247,7 +247,7 @@ describe('ProductTrainingContextProvider', () => {
             const date = new Date();
             Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
                 migratedUserWelcomeModal: {
-                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
+                    timestamp: DateUtils.getDBTime(date.valueOf()),
                 },
             });
             await waitForBatchedUpdatesWithAct();
@@ -278,10 +278,10 @@ describe('ProductTrainingContextProvider', () => {
 
             Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
                 migratedUserWelcomeModal: {
-                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
+                    timestamp: DateUtils.getDBTime(date.valueOf()),
                 },
                 [highPriorityTooltip]: {
-                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
+                    timestamp: DateUtils.getDBTime(date.valueOf()),
                 },
             });
             await waitForBatchedUpdatesWithAct();
@@ -306,7 +306,7 @@ describe('ProductTrainingContextProvider', () => {
             const date = new Date();
             Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
                 migratedUserWelcomeModal: {
-                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
+                    timestamp: DateUtils.getDBTime(date.valueOf()),
                 },
             });
             await waitForBatchedUpdatesWithAct();
@@ -329,7 +329,7 @@ describe('ProductTrainingContextProvider', () => {
             // When dismissing higher priority tooltip
             Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
                 [highPriorityTooltip]: {
-                    dismissedTime: DateUtils.getDBTime(date.valueOf()),
+                    timestamp: DateUtils.getDBTime(date.valueOf()),
                 },
             });
             await waitForBatchedUpdatesWithAct();
diff --git a/tests/unit/OptionsListUtilsTest.ts b/tests/unit/OptionsListUtilsTest.ts
index 3713855a164c..009c8acfe3ad 100644
--- a/tests/unit/OptionsListUtilsTest.ts
+++ b/tests/unit/OptionsListUtilsTest.ts
@@ -684,9 +684,13 @@ describe('OptionsListUtils', () => {
         expect(options.personalDetails).not.toEqual(expect.arrayContaining([expect.objectContaining({login: CONST.EMAIL.MANAGER_MCTEST})]));
 
         return waitForBatchedUpdates()
-            .then(() => Onyx.set(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {[CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP]: {
-                dismissedTime: DateUtils.getDBTime(new Date().valueOf()),
-            }}))
+            .then(() =>
+                Onyx.set(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
+                    [CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP]: {
+                        timestamp: DateUtils.getDBTime(new Date().valueOf()),
+                    },
+                }),
+            )
             .then(() => {
                 // Manager McTest shouldn't be included to recipients when the user has already submitted an expense
                 const optionsWhenUserAlreadySubmittedExpense = getValidOptions(

From 14ecc886ec1c1721e2e328b36a65c35f2f1324dd Mon Sep 17 00:00:00 2001
From: Ishpaul Singh <ishpaul207@gmail.com>
Date: Thu, 20 Mar 2025 00:50:05 +0530
Subject: [PATCH 07/17] Remove unused x-letter icon

---
 assets/images/x-letter.svg                      | 14 --------------
 src/components/Icon/Expensicons.ts              |  2 --
 src/components/ProductTrainingContext/index.tsx |  6 ++++--
 3 files changed, 4 insertions(+), 18 deletions(-)
 delete mode 100644 assets/images/x-letter.svg

diff --git a/assets/images/x-letter.svg b/assets/images/x-letter.svg
deleted file mode 100644
index 559b11671e41..000000000000
--- a/assets/images/x-letter.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<svg
-  xmlns="http://www.w3.org/2000/svg"
-  width="24"
-  height="24"
-  viewBox="0 0 24 24"
-  fill="none"
-  stroke="currentColor"
-  stroke-width="2"
-  stroke-linecap="round"
-  stroke-linejoin="round"
->
-  <line x1="18" y1="6" x2="6" y2="18" />
-  <line x1="6" y1="6" x2="18" y2="18" />
-</svg>
diff --git a/src/components/Icon/Expensicons.ts b/src/components/Icon/Expensicons.ts
index c5ca05706e67..146a58f5940f 100644
--- a/src/components/Icon/Expensicons.ts
+++ b/src/components/Icon/Expensicons.ts
@@ -214,7 +214,6 @@ import Workflows from '@assets/images/workflows.svg';
 import Workspace from '@assets/images/workspace-default-avatar.svg';
 import Wrench from '@assets/images/wrench.svg';
 import Clear from '@assets/images/x-circle.svg';
-import CrossX from '@assets/images/x-letter.svg';
 import Zoom from '@assets/images/zoom.svg';
 
 export {
@@ -435,5 +434,4 @@ export {
     Train,
     boltSlash,
     MagnifyingGlassSpyMouthClosed,
-    CrossX,
 };
diff --git a/src/components/ProductTrainingContext/index.tsx b/src/components/ProductTrainingContext/index.tsx
index cde84d94bbc8..5af72dde0603 100644
--- a/src/components/ProductTrainingContext/index.tsx
+++ b/src/components/ProductTrainingContext/index.tsx
@@ -20,6 +20,7 @@ import type ChildrenProps from '@src/types/utils/ChildrenProps';
 import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
 import type {ProductTrainingTooltipName} from './TOOLTIPS';
 import TOOLTIPS from './TOOLTIPS';
+import variables from '@styles/variables';
 
 type ProductTrainingContextType = {
     shouldRenderTooltip: (tooltipName: ProductTrainingTooltipName) => boolean;
@@ -266,9 +267,10 @@ const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shou
                         role={CONST.ROLE.BUTTON}
                     >
                         <Icon
-                            src={Expensicons.Clear}
+                            src={Expensicons.Close}
                             fill={theme.icon}
-                            medium
+                            width={variables.iconSizeSemiSmall}
+                            height={variables.iconSizeSemiSmall}
                         />
                     </PressableWithoutFeedback>
                 </View>

From 66fcb94e6ed91add6940a0d9c686faa128e765a0 Mon Sep 17 00:00:00 2001
From: Ishpaul Singh <ishpaul207@gmail.com>
Date: Thu, 20 Mar 2025 00:53:55 +0530
Subject: [PATCH 08/17] prettier

---
 src/components/ProductTrainingContext/index.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/ProductTrainingContext/index.tsx b/src/components/ProductTrainingContext/index.tsx
index 5af72dde0603..f9d412c689a6 100644
--- a/src/components/ProductTrainingContext/index.tsx
+++ b/src/components/ProductTrainingContext/index.tsx
@@ -14,13 +14,13 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import {parseFSAttributes} from '@libs/Fullstory';
 import {hasCompletedGuidedSetupFlowSelector} from '@libs/onboardingSelectors';
 import isProductTrainingElementDismissed from '@libs/TooltipUtils';
+import variables from '@styles/variables';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type ChildrenProps from '@src/types/utils/ChildrenProps';
 import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
 import type {ProductTrainingTooltipName} from './TOOLTIPS';
 import TOOLTIPS from './TOOLTIPS';
-import variables from '@styles/variables';
 
 type ProductTrainingContextType = {
     shouldRenderTooltip: (tooltipName: ProductTrainingTooltipName) => boolean;

From e5c39ef72ac6ba861d70c3dd55d03877b7f6de0c Mon Sep 17 00:00:00 2001
From: Ishpaul Singh <ishpaul207@gmail.com>
Date: Fri, 21 Mar 2025 00:22:18 +0530
Subject: [PATCH 09/17] fix padding

---
 src/components/ProductTrainingContext/index.tsx | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/components/ProductTrainingContext/index.tsx b/src/components/ProductTrainingContext/index.tsx
index 107b744a097c..40b674f62b11 100644
--- a/src/components/ProductTrainingContext/index.tsx
+++ b/src/components/ProductTrainingContext/index.tsx
@@ -236,7 +236,8 @@ const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shou
                         styles.flexWrap,
                         styles.textAlignCenter,
                         styles.gap3,
-                        styles.p2,
+                        styles.pv2,
+                        styles.ph1,
                     ]}
                 >
                     <Icon
@@ -261,7 +262,6 @@ const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shou
                         onPress={() => {
                             hideProductTrainingTooltip(true);
                         }}
-                        style={[styles.flexRow, styles.alignItemsCenter, styles.flex1]}
                         accessibilityLabel={translate('productTrainingTooltip.scanTestTooltip.noThanks')}
                         role={CONST.ROLE.BUTTON}
                     >
@@ -299,14 +299,14 @@ const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shou
         styles.flexWrap,
         styles.textAlignCenter,
         styles.gap3,
-        styles.p2,
+        styles.pv2,
+        styles.ph1,
         styles.productTrainingTooltipText,
         styles.textWrap,
         styles.mw100,
         styles.flex1,
         styles.justifyContentBetween,
         styles.ph2,
-        styles.pv2,
         styles.gap2,
         styles.textBold,
         theme.tooltipHighlightText,

From da17ce0cb50419c111e1151571ec4ac7e4101dcd Mon Sep 17 00:00:00 2001
From: Ishpaul Singh <ishpaul207@gmail.com>
Date: Fri, 21 Mar 2025 00:42:34 +0530
Subject: [PATCH 10/17] remove x from tooltip with buttons

---
 .../ProductTrainingContext/index.tsx          | 30 ++++++++++---------
 .../step/IOURequestStepScan/index.native.tsx  |  2 +-
 .../request/step/IOURequestStepScan/index.tsx |  2 +-
 3 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/src/components/ProductTrainingContext/index.tsx b/src/components/ProductTrainingContext/index.tsx
index 40b674f62b11..cb337e4df318 100644
--- a/src/components/ProductTrainingContext/index.tsx
+++ b/src/components/ProductTrainingContext/index.tsx
@@ -258,20 +258,22 @@ const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shou
                             );
                         })}
                     </Text>
-                    <PressableWithoutFeedback
-                        onPress={() => {
-                            hideProductTrainingTooltip(true);
-                        }}
-                        accessibilityLabel={translate('productTrainingTooltip.scanTestTooltip.noThanks')}
-                        role={CONST.ROLE.BUTTON}
-                    >
-                        <Icon
-                            src={Expensicons.Close}
-                            fill={theme.icon}
-                            width={variables.iconSizeSemiSmall}
-                            height={variables.iconSizeSemiSmall}
-                        />
-                    </PressableWithoutFeedback>
+                    {!tooltip?.shouldRenderActionButtons && (
+                        <PressableWithoutFeedback
+                            onPress={() => {
+                                hideProductTrainingTooltip(true);
+                            }}
+                            accessibilityLabel={translate('productTrainingTooltip.scanTestTooltip.noThanks')}
+                            role={CONST.ROLE.BUTTON}
+                        >
+                            <Icon
+                                src={Expensicons.Close}
+                                fill={theme.icon}
+                                width={variables.iconSizeSemiSmall}
+                                height={variables.iconSizeSemiSmall}
+                            />
+                        </PressableWithoutFeedback>
+                    )}
                 </View>
                 {!!tooltip?.shouldRenderActionButtons && (
                     <View style={[styles.alignItemsCenter, styles.justifyContentBetween, styles.flexRow, styles.ph2, styles.pv2, styles.gap2]}>
diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx
index 6a00b329a2b6..ab6b1fe76500 100644
--- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx
+++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx
@@ -528,7 +528,7 @@ function IOURequestStepScan({
         {
             onConfirm: setTestReceiptAndNavigate,
             onDismiss: () => {
-                dismissProductTraining(CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP);
+                dismissProductTraining(CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP, true);
             },
         },
     );
diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx
index 2cef346c2125..544629580e23 100644
--- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx
+++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx
@@ -587,7 +587,7 @@ function IOURequestStepScan({
         {
             onConfirm: setTestReceiptAndNavigate,
             onDismiss: () => {
-                dismissProductTraining(CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP);
+                dismissProductTraining(CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP, true);
             },
         },
     );

From 9cc72887d275e4a053f279683b3cd697aa0c5aab Mon Sep 17 00:00:00 2001
From: Ishpaul Singh <ishpaul207@gmail.com>
Date: Fri, 21 Mar 2025 01:17:29 +0530
Subject: [PATCH 11/17] Update tooltip dismissal logic to accept parameter for
 dismissal method

---
 src/components/ProductTrainingContext/TOOLTIPS.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/components/ProductTrainingContext/TOOLTIPS.ts b/src/components/ProductTrainingContext/TOOLTIPS.ts
index 1da7293a2ed7..83bd4e6fe714 100644
--- a/src/components/ProductTrainingContext/TOOLTIPS.ts
+++ b/src/components/ProductTrainingContext/TOOLTIPS.ts
@@ -102,7 +102,7 @@ const TOOLTIPS: Record<ProductTrainingTooltipName, TooltipData> = {
             {text: 'productTrainingTooltip.scanTestTooltip.part4', isBold: true},
             {text: 'productTrainingTooltip.scanTestTooltip.part5', isBold: false},
         ],
-        onHideTooltip: () => dismissProductTraining(SCAN_TEST_TOOLTIP_MANAGER),
+        onHideTooltip: (isDismissedUsingX = false) => dismissProductTraining(SCAN_TEST_TOOLTIP_MANAGER, isDismissedUsingX),
         name: SCAN_TEST_TOOLTIP_MANAGER,
         priority: 1000,
         shouldShow: () => true,
@@ -113,7 +113,7 @@ const TOOLTIPS: Record<ProductTrainingTooltipName, TooltipData> = {
             {text: 'productTrainingTooltip.scanTestTooltip.part7', isBold: true},
             {text: 'productTrainingTooltip.scanTestTooltip.part8', isBold: false},
         ],
-        onHideTooltip: () => dismissProductTraining(SCAN_TEST_CONFIRMATION),
+        onHideTooltip: (isDismissedUsingX = false) => dismissProductTraining(SCAN_TEST_CONFIRMATION, isDismissedUsingX),
         name: SCAN_TEST_CONFIRMATION,
         priority: 1100,
         shouldShow: () => true,

From 0dda3fd9d4f77cfb84022f4032142203b7776667 Mon Sep 17 00:00:00 2001
From: Ishpaul Singh <ishpaul207@gmail.com>
Date: Fri, 21 Mar 2025 01:38:45 +0530
Subject: [PATCH 12/17] change variable name

---
 .../ProductTrainingContext/TOOLTIPS.ts           | 16 ++++++++--------
 src/components/ProductTrainingContext/index.tsx  |  4 ++--
 src/libs/Permissions.ts                          |  2 +-
 src/libs/actions/Welcome/index.ts                |  4 ++--
 4 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/src/components/ProductTrainingContext/TOOLTIPS.ts b/src/components/ProductTrainingContext/TOOLTIPS.ts
index 83bd4e6fe714..0256c7f67988 100644
--- a/src/components/ProductTrainingContext/TOOLTIPS.ts
+++ b/src/components/ProductTrainingContext/TOOLTIPS.ts
@@ -22,7 +22,7 @@ type ShouldShowConditionProps = {
 
 type TooltipData = {
     content: Array<{text: TranslationPaths; isBold: boolean}>;
-    onHideTooltip: (isDismissedUsingX?: boolean) => void;
+    onHideTooltip: (isDismissedUsingCloseButton?: boolean) => void;
     name: ProductTrainingTooltipName;
     priority: number;
     shouldShow: (props: ShouldShowConditionProps) => boolean;
@@ -35,7 +35,7 @@ const TOOLTIPS: Record<ProductTrainingTooltipName, TooltipData> = {
             {text: 'productTrainingTooltip.conciergeLHNGBR.part1', isBold: false},
             {text: 'productTrainingTooltip.conciergeLHNGBR.part2', isBold: true},
         ],
-        onHideTooltip: (isDismissedUsingX = false) => dismissProductTraining(CONCEIRGE_LHN_GBR, isDismissedUsingX),
+        onHideTooltip: (isDismissedUsingCloseButton = false) => dismissProductTraining(CONCEIRGE_LHN_GBR, isDismissedUsingCloseButton),
         name: CONCEIRGE_LHN_GBR,
         priority: 1300,
         // TODO: CONCEIRGE_LHN_GBR tooltip will be replaced by a tooltip in the #admins room
@@ -47,7 +47,7 @@ const TOOLTIPS: Record<ProductTrainingTooltipName, TooltipData> = {
             {text: 'productTrainingTooltip.saveSearchTooltip.part1', isBold: true},
             {text: 'productTrainingTooltip.saveSearchTooltip.part2', isBold: false},
         ],
-        onHideTooltip: (isDismissedUsingX = false) => dismissProductTraining(RENAME_SAVED_SEARCH, isDismissedUsingX),
+        onHideTooltip: (isDismissedUsingCloseButton = false) => dismissProductTraining(RENAME_SAVED_SEARCH, isDismissedUsingCloseButton),
         name: RENAME_SAVED_SEARCH,
         priority: 1250,
         shouldShow: ({shouldUseNarrowLayout}) => !shouldUseNarrowLayout,
@@ -58,7 +58,7 @@ const TOOLTIPS: Record<ProductTrainingTooltipName, TooltipData> = {
             {text: 'productTrainingTooltip.globalCreateTooltip.part2', isBold: false},
             {text: 'productTrainingTooltip.globalCreateTooltip.part3', isBold: false},
         ],
-        onHideTooltip: (isDismissedUsingX = false) => dismissProductTraining(GLOBAL_CREATE_TOOLTIP, isDismissedUsingX),
+        onHideTooltip: (isDismissedUsingCloseButton = false) => dismissProductTraining(GLOBAL_CREATE_TOOLTIP, isDismissedUsingCloseButton),
         name: GLOBAL_CREATE_TOOLTIP,
         priority: 1200,
         shouldShow: () => true,
@@ -69,7 +69,7 @@ const TOOLTIPS: Record<ProductTrainingTooltipName, TooltipData> = {
             {text: 'productTrainingTooltip.bottomNavInboxTooltip.part2', isBold: false},
             {text: 'productTrainingTooltip.bottomNavInboxTooltip.part3', isBold: false},
         ],
-        onHideTooltip: (isDismissedUsingX = false) => dismissProductTraining(BOTTOM_NAV_INBOX_TOOLTIP, isDismissedUsingX),
+        onHideTooltip: (isDismissedUsingCloseButton = false) => dismissProductTraining(BOTTOM_NAV_INBOX_TOOLTIP, isDismissedUsingCloseButton),
         name: BOTTOM_NAV_INBOX_TOOLTIP,
         priority: 900,
         shouldShow: () => true,
@@ -80,7 +80,7 @@ const TOOLTIPS: Record<ProductTrainingTooltipName, TooltipData> = {
             {text: 'productTrainingTooltip.workspaceChatTooltip.part2', isBold: false},
             {text: 'productTrainingTooltip.workspaceChatTooltip.part3', isBold: false},
         ],
-        onHideTooltip: (isDismissedUsingX = false) => dismissProductTraining(LHN_WORKSPACE_CHAT_TOOLTIP, isDismissedUsingX),
+        onHideTooltip: (isDismissedUsingCloseButton = false) => dismissProductTraining(LHN_WORKSPACE_CHAT_TOOLTIP, isDismissedUsingCloseButton),
         name: LHN_WORKSPACE_CHAT_TOOLTIP,
         priority: 800,
         shouldShow: () => true,
@@ -102,7 +102,7 @@ const TOOLTIPS: Record<ProductTrainingTooltipName, TooltipData> = {
             {text: 'productTrainingTooltip.scanTestTooltip.part4', isBold: true},
             {text: 'productTrainingTooltip.scanTestTooltip.part5', isBold: false},
         ],
-        onHideTooltip: (isDismissedUsingX = false) => dismissProductTraining(SCAN_TEST_TOOLTIP_MANAGER, isDismissedUsingX),
+        onHideTooltip: (isDismissedUsingCloseButton = false) => dismissProductTraining(SCAN_TEST_TOOLTIP_MANAGER, isDismissedUsingCloseButton),
         name: SCAN_TEST_TOOLTIP_MANAGER,
         priority: 1000,
         shouldShow: () => true,
@@ -113,7 +113,7 @@ const TOOLTIPS: Record<ProductTrainingTooltipName, TooltipData> = {
             {text: 'productTrainingTooltip.scanTestTooltip.part7', isBold: true},
             {text: 'productTrainingTooltip.scanTestTooltip.part8', isBold: false},
         ],
-        onHideTooltip: (isDismissedUsingX = false) => dismissProductTraining(SCAN_TEST_CONFIRMATION, isDismissedUsingX),
+        onHideTooltip: (isDismissedUsingCloseButton = false) => dismissProductTraining(SCAN_TEST_CONFIRMATION, isDismissedUsingCloseButton),
         name: SCAN_TEST_CONFIRMATION,
         priority: 1100,
         shouldShow: () => true,
diff --git a/src/components/ProductTrainingContext/index.tsx b/src/components/ProductTrainingContext/index.tsx
index cb337e4df318..35b4574e1e5b 100644
--- a/src/components/ProductTrainingContext/index.tsx
+++ b/src/components/ProductTrainingContext/index.tsx
@@ -210,12 +210,12 @@ const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shou
     }, [shouldRenderTooltip, tooltipName, shouldShow, shouldHideToolTip]);
 
     const hideProductTrainingTooltip = useCallback(
-        (isDismissedUsingX = false) => {
+        (isDismissedUsingCloseButton = false) => {
             if (!shouldShowProductTrainingTooltip) {
                 return;
             }
             const tooltip = TOOLTIPS[tooltipName];
-            tooltip.onHideTooltip(isDismissedUsingX);
+            tooltip.onHideTooltip(isDismissedUsingCloseButton);
             unregisterTooltip(tooltipName);
         },
         [tooltipName, shouldShowProductTrainingTooltip, unregisterTooltip],
diff --git a/src/libs/Permissions.ts b/src/libs/Permissions.ts
index 635e996c322f..88831f7444fe 100644
--- a/src/libs/Permissions.ts
+++ b/src/libs/Permissions.ts
@@ -39,7 +39,7 @@ function canUsePDFExport(betas: OnyxEntry<Beta[]>): boolean {
 }
 
 function canUseManagerMcTest(betas: OnyxEntry<Beta[]>): boolean {
-    return !!betas?.includes(CONST.BETAS.NEWDOT_MANAGER_MCTEST) || canUseAllBetas(betas);
+    return true;
 }
 
 function canUseInternationalBankAccount(betas: OnyxEntry<Beta[]>): boolean {
diff --git a/src/libs/actions/Welcome/index.ts b/src/libs/actions/Welcome/index.ts
index 3f31d58ce490..e959d84c9c13 100644
--- a/src/libs/actions/Welcome/index.ts
+++ b/src/libs/actions/Welcome/index.ts
@@ -207,9 +207,9 @@ function setSelfTourViewed(shouldUpdateOnyxDataOnlyLocally = false) {
     API.write(WRITE_COMMANDS.SELF_TOUR_VIEWED, null, {optimisticData});
 }
 
-function dismissProductTraining(elementName: string, isDismissedUsingX = false) {
+function dismissProductTraining(elementName: string, isDismissedUsingCloseButton = false) {
     const date = new Date();
-    const dismissedMethod = isDismissedUsingX ? 'x' : 'click';
+    const dismissedMethod = isDismissedUsingCloseButton ? 'x' : 'click';
     const optimisticData = [
         {
             onyxMethod: Onyx.METHOD.MERGE,

From 505141e4a93f506b353c0f28b772324275a0c176 Mon Sep 17 00:00:00 2001
From: Ishpaul Singh <ishpaul207@gmail.com>
Date: Fri, 21 Mar 2025 01:41:05 +0530
Subject: [PATCH 13/17] revert unrelated change

---
 src/libs/Permissions.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libs/Permissions.ts b/src/libs/Permissions.ts
index 88831f7444fe..635e996c322f 100644
--- a/src/libs/Permissions.ts
+++ b/src/libs/Permissions.ts
@@ -39,7 +39,7 @@ function canUsePDFExport(betas: OnyxEntry<Beta[]>): boolean {
 }
 
 function canUseManagerMcTest(betas: OnyxEntry<Beta[]>): boolean {
-    return true;
+    return !!betas?.includes(CONST.BETAS.NEWDOT_MANAGER_MCTEST) || canUseAllBetas(betas);
 }
 
 function canUseInternationalBankAccount(betas: OnyxEntry<Beta[]>): boolean {

From 21d93d345345a739f3be428a5a1d742bbba130a4 Mon Sep 17 00:00:00 2001
From: Ishpaul Singh <ishpaul207@gmail.com>
Date: Fri, 21 Mar 2025 02:04:45 +0530
Subject: [PATCH 14/17] fix as per review

---
 src/libs/actions/Report.ts | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts
index 05b7e12e169b..1260d0f0b46a 100644
--- a/src/libs/actions/Report.ts
+++ b/src/libs/actions/Report.ts
@@ -4863,7 +4863,10 @@ function dismissChangePolicyModal() {
             onyxMethod: Onyx.METHOD.MERGE,
             key: ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING,
             value: {
-                [CONST.CHANGE_POLICY_TRAINING_MODAL]: DateUtils.getDBTime(date.valueOf()),
+                [CONST.CHANGE_POLICY_TRAINING_MODAL]: {
+                    timestamp: DateUtils.getDBTime(date.valueOf()),
+                    dismissedMethod: 'click'
+                },
             },
         },
     ];

From 345db1d13af3922e2e7c0ec9914ef35c111449de Mon Sep 17 00:00:00 2001
From: Ishpaul Singh <ishpaul207@gmail.com>
Date: Fri, 21 Mar 2025 02:09:40 +0530
Subject: [PATCH 15/17] prettier

---
 src/libs/actions/Report.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts
index 1260d0f0b46a..7331c75c770a 100644
--- a/src/libs/actions/Report.ts
+++ b/src/libs/actions/Report.ts
@@ -4865,7 +4865,7 @@ function dismissChangePolicyModal() {
             value: {
                 [CONST.CHANGE_POLICY_TRAINING_MODAL]: {
                     timestamp: DateUtils.getDBTime(date.valueOf()),
-                    dismissedMethod: 'click'
+                    dismissedMethod: 'click',
                 },
             },
         },

From 1215bf0695645659058768cd9e3aafdff2a0d58c Mon Sep 17 00:00:00 2001
From: Ishpaul Singh <ishpaul207@gmail.com>
Date: Fri, 21 Mar 2025 02:59:52 +0530
Subject: [PATCH 16/17] changes as per review

---
 src/components/ProductTrainingContext/index.tsx | 13 ++++++++++---
 src/libs/TooltipUtils.ts                        | 10 +---------
 2 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/src/components/ProductTrainingContext/index.tsx b/src/components/ProductTrainingContext/index.tsx
index 35b4574e1e5b..4103f7047578 100644
--- a/src/components/ProductTrainingContext/index.tsx
+++ b/src/components/ProductTrainingContext/index.tsx
@@ -209,7 +209,7 @@ const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shou
         return shouldShow && shouldRenderTooltip(tooltipName) && !shouldHideToolTip;
     }, [shouldRenderTooltip, tooltipName, shouldShow, shouldHideToolTip]);
 
-    const hideProductTrainingTooltip = useCallback(
+    const hideTooltip = useCallback(
         (isDismissedUsingCloseButton = false) => {
             if (!shouldShowProductTrainingTooltip) {
                 return;
@@ -261,7 +261,7 @@ const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shou
                     {!tooltip?.shouldRenderActionButtons && (
                         <PressableWithoutFeedback
                             onPress={() => {
-                                hideProductTrainingTooltip(true);
+                                hideTooltip(true);
                             }}
                             accessibilityLabel={translate('productTrainingTooltip.scanTestTooltip.noThanks')}
                             role={CONST.ROLE.BUTTON}
@@ -316,9 +316,16 @@ const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shou
         translate,
         config.onConfirm,
         config.onDismiss,
-        hideProductTrainingTooltip,
+        hideTooltip,
     ]);
 
+    const hideProductTrainingTooltip = useCallback(
+        () => {
+           hideTooltip(false);
+        },
+        [hideTooltip],
+    );
+
     return {
         renderProductTrainingTooltip,
         hideProductTrainingTooltip,
diff --git a/src/libs/TooltipUtils.ts b/src/libs/TooltipUtils.ts
index f77dbe95fb6c..aa2040ce035f 100644
--- a/src/libs/TooltipUtils.ts
+++ b/src/libs/TooltipUtils.ts
@@ -1,15 +1,7 @@
-import Onyx from 'react-native-onyx';
 import type {OnyxEntry} from 'react-native-onyx';
-import ONYXKEYS from '@src/ONYXKEYS';
 import type {DismissedProductTraining} from '@src/types/onyx';
 
-let nvpDismissedProductTraining: OnyxEntry<DismissedProductTraining>;
-Onyx.connect({
-    key: ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING,
-    callback: (value) => (nvpDismissedProductTraining = value),
-});
-
-function isProductTrainingElementDismissed(elementName: keyof DismissedProductTraining, dismissedProductTraining: OnyxEntry<DismissedProductTraining> = nvpDismissedProductTraining) {
+function isProductTrainingElementDismissed(elementName: keyof DismissedProductTraining, dismissedProductTraining: OnyxEntry<DismissedProductTraining>) {
     return typeof dismissedProductTraining?.[elementName] === 'string' ? !!dismissedProductTraining?.[elementName] : !!dismissedProductTraining?.[elementName]?.timestamp;
 }
 

From 20d98ce1c1365772ed7f43366ec47b9150cc71e1 Mon Sep 17 00:00:00 2001
From: Ishpaul Singh <ishpaul207@gmail.com>
Date: Fri, 21 Mar 2025 03:03:54 +0530
Subject: [PATCH 17/17] prettier

---
 src/components/ProductTrainingContext/index.tsx | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/src/components/ProductTrainingContext/index.tsx b/src/components/ProductTrainingContext/index.tsx
index 4103f7047578..02f6ad4a9c84 100644
--- a/src/components/ProductTrainingContext/index.tsx
+++ b/src/components/ProductTrainingContext/index.tsx
@@ -319,12 +319,9 @@ const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shou
         hideTooltip,
     ]);
 
-    const hideProductTrainingTooltip = useCallback(
-        () => {
-           hideTooltip(false);
-        },
-        [hideTooltip],
-    );
+    const hideProductTrainingTooltip = useCallback(() => {
+        hideTooltip(false);
+    }, [hideTooltip]);
 
     return {
         renderProductTrainingTooltip,
