From 093e1d71cf7510033f97eec7167e1ceea558dd4b Mon Sep 17 00:00:00 2001 From: Rayane <77965000+rayane-d@users.noreply.github.com> Date: Wed, 19 Mar 2025 15:39:16 +0100 Subject: [PATCH 01/12] Update inbox tooltip and add expense report filter type tooltip --- src/CONST.ts | 1 + .../ProductTrainingContext/TOOLTIPS.ts | 19 +++++++-- src/languages/en.ts | 12 ++++-- src/languages/es.ts | 12 ++++-- src/pages/Search/SearchTypeMenu.tsx | 42 ++++++++++++++----- src/styles/variables.ts | 1 + src/types/onyx/DismissedProductTraining.ts | 7 ++++ .../ProductTrainingContextProvider.tsx | 6 +-- 8 files changed, 77 insertions(+), 23 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index cfccbfd12ff1d..9a9c64a8662ba 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -6817,6 +6817,7 @@ const CONST = { SCAN_TEST_TOOLTIP: 'scanTestTooltip', SCAN_TEST_TOOLTIP_MANAGER: 'scanTestTooltipManager', SCAN_TEST_CONFIRMATION: 'scanTestConfirmation', + EXPENSE_REPORTS_FILTER: 'expenseReportsFilter', }, CHANGE_POLICY_TRAINING_MODAL: 'changePolicyModal', SMART_BANNER_HEIGHT: 152, diff --git a/src/components/ProductTrainingContext/TOOLTIPS.ts b/src/components/ProductTrainingContext/TOOLTIPS.ts index 90e91166fba76..82972a3ab31bd 100644 --- a/src/components/ProductTrainingContext/TOOLTIPS.ts +++ b/src/components/ProductTrainingContext/TOOLTIPS.ts @@ -15,6 +15,7 @@ const { SCAN_TEST_TOOLTIP, SCAN_TEST_TOOLTIP_MANAGER, SCAN_TEST_CONFIRMATION, + EXPENSE_REPORTS_FILTER, } = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES; type ProductTrainingTooltipName = ValueOf; @@ -97,13 +98,14 @@ const TOOLTIPS: Record = { }, [BOTTOM_NAV_INBOX_TOOLTIP]: { content: [ - {text: 'productTrainingTooltip.bottomNavInboxTooltip.part1', isBold: true}, - {text: 'productTrainingTooltip.bottomNavInboxTooltip.part2', isBold: false}, + {text: 'productTrainingTooltip.bottomNavInboxTooltip.part1', isBold: false}, + {text: 'productTrainingTooltip.bottomNavInboxTooltip.part2', isBold: true}, {text: 'productTrainingTooltip.bottomNavInboxTooltip.part3', isBold: false}, + {text: 'productTrainingTooltip.bottomNavInboxTooltip.part4', isBold: true}, ], onHideTooltip: () => dismissProductTraining(BOTTOM_NAV_INBOX_TOOLTIP), name: BOTTOM_NAV_INBOX_TOOLTIP, - priority: 900, + priority: 1700, shouldShow: () => true, }, [LHN_WORKSPACE_CHAT_TOOLTIP]: { @@ -117,6 +119,17 @@ const TOOLTIPS: Record = { priority: 800, shouldShow: () => true, }, + [EXPENSE_REPORTS_FILTER]: { + content: [ + {text: 'productTrainingTooltip.expenseReportsFilter.part1', isBold: false}, + {text: 'productTrainingTooltip.expenseReportsFilter.part2', isBold: true}, + {text: 'productTrainingTooltip.expenseReportsFilter.part3', isBold: false}, + ], + onHideTooltip: () => dismissProductTraining(EXPENSE_REPORTS_FILTER), + name: EXPENSE_REPORTS_FILTER, + priority: 2000, + shouldShow: ({shouldUseNarrowLayout}) => !shouldUseNarrowLayout, + }, [SCAN_TEST_TOOLTIP]: { content: [ {text: 'productTrainingTooltip.scanTestTooltip.part1', isBold: false}, diff --git a/src/languages/en.ts b/src/languages/en.ts index 5f44cde8afb56..9b8f8992ac889 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -5964,9 +5964,10 @@ const translations = { part2: ' here!', }, bottomNavInboxTooltip: { - part1: 'Your to-do list', - part2: '\n🟢 = ready for you', - part3: ' 🔴 = needs review', + part1: 'Check what ', + part2: 'needs your attention', + part3: '\nand ', + part4: 'chat about expenses.', }, workspaceChatTooltip: { part1: 'Submit expenses', @@ -5978,6 +5979,11 @@ const translations = { part2: ', start chatting,', part3: '\nand more!', }, + expenseReportsFilter: { + part1: 'Welcome!\nFind all of your ', + part2: "company's reports", + part3: ' here.', + }, scanTestTooltip: { part1: 'Want to see how Scan works?', part2: ' Try a test \nreceipt!', diff --git a/src/languages/es.ts b/src/languages/es.ts index 33b62a5eb8d46..042b179e2d82c 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -6486,9 +6486,10 @@ const translations = { part2: ' aquí!', }, bottomNavInboxTooltip: { - part1: 'Tu lista de tareas', - part2: '\n🟢 = listo para ti', - part3: ' 🔴 = necesita revisión', + part1: 'Consulta lo que ', + part2: 'requiere tu atención', + part3: '\ny ', + part4: 'chatea sobre gastos.', }, workspaceChatTooltip: { part1: 'Envía gastos', @@ -6500,6 +6501,11 @@ const translations = { part2: ', comienza a chatear,', part3: '\ny mucho más!', }, + expenseReportsFilter: { + part1: '¡Bienvenido!\nEncuentra todos los ', + part2: 'informes de tu empresa', + part3: ' aquí.', + }, scanTestTooltip: { part1: '¿Quieres ver cómo funciona Escanear?', part2: ' \n¡Prueba con un recibo de prueba!', diff --git a/src/pages/Search/SearchTypeMenu.tsx b/src/pages/Search/SearchTypeMenu.tsx index 0f85d2984a367..52e007118dda6 100644 --- a/src/pages/Search/SearchTypeMenu.tsx +++ b/src/pages/Search/SearchTypeMenu.tsx @@ -48,10 +48,16 @@ function SearchTypeMenu({queryJSON}: SearchTypeMenuProps) { const {isOffline} = useNetwork(); const shouldShowSavedSearchesMenuItemTitle = Object.values(savedSearches ?? {}).filter((s) => s.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || isOffline).length > 0; const isFocused = useIsFocused(); - const {shouldShowProductTrainingTooltip, renderProductTrainingTooltip, hideProductTrainingTooltip} = useProductTrainingContext( - CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.RENAME_SAVED_SEARCH, - shouldShowSavedSearchesMenuItemTitle && isFocused, - ); + const { + shouldShowProductTrainingTooltip: shouldShowSavedSearchTooltip, + renderProductTrainingTooltip: renderSavedSearchTooltip, + hideProductTrainingTooltip: hideSavedSearchTooltip, + } = useProductTrainingContext(CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.RENAME_SAVED_SEARCH, shouldShowSavedSearchesMenuItemTitle && isFocused); + const { + shouldShowProductTrainingTooltip: shouldShowExpenseReportsTypeTooltip, + renderProductTrainingTooltip: renderExpenseReportsTypeTooltip, + hideProductTrainingTooltip: hideExpenseReportsTypeTooltip, + } = useProductTrainingContext(CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.EXPENSE_REPORTS_FILTER, true); const {showDeleteModal, DeleteConfirmModal} = useDeleteSavedSearch(); const [session] = useOnyx(ONYXKEYS.SESSION); const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY); @@ -88,9 +94,9 @@ function SearchTypeMenu({queryJSON}: SearchTypeMenuProps) { ), style: [styles.alignItemsCenter], @@ -101,23 +107,23 @@ function SearchTypeMenu({queryJSON}: SearchTypeMenuProps) { tooltipShiftHorizontal: variables.savedSearchShiftHorizontal, tooltipShiftVertical: variables.savedSearchShiftVertical, tooltipWrapperStyle: [styles.mh4, styles.pv2, styles.productTrainingTooltipWrapper], - renderTooltipContent: renderProductTrainingTooltip, + renderTooltipContent: renderSavedSearchTooltip, }; }, [ allCards, hash, getOverflowMenu, + shouldShowSavedSearchTooltip, + hideSavedSearchTooltip, styles.alignItemsCenter, styles.mh4, styles.pv2, styles.productTrainingTooltipWrapper, + renderSavedSearchTooltip, personalDetails, reports, taxRates, - shouldShowProductTrainingTooltip, - hideProductTrainingTooltip, - renderProductTrainingTooltip, cardFeedNamesWithType, ], ); @@ -186,7 +192,12 @@ function SearchTypeMenu({queryJSON}: SearchTypeMenuProps) { > {typeMenuItems.map((item, index) => { + const shouldShowTooltip = item.translationPath === 'common.expenseReports' && index !== activeItemIndex && shouldShowExpenseReportsTypeTooltip; + const onPress = singleExecution(() => { + if (shouldShowTooltip) { + hideExpenseReportsTypeTooltip(); + } clearAllFilters(); clearSelectedTransactions(); Navigation.navigate(item.getRoute(queryJSON.policyID)); @@ -205,6 +216,15 @@ function SearchTypeMenu({queryJSON}: SearchTypeMenuProps) { focused={index === activeItemIndex} onPress={onPress} shouldIconUseAutoWidthStyle + shouldRenderTooltip={shouldShowTooltip} + renderTooltipContent={renderExpenseReportsTypeTooltip} + tooltipAnchorAlignment={{ + horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, + vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP, + }} + tooltipShiftHorizontal={variables.expenseReportsTypeTooltipShiftHorizontal} + tooltipWrapperStyle={styles.productTrainingTooltipWrapper} + onEducationTooltipPress={onPress} /> ); })} diff --git a/src/styles/variables.ts b/src/styles/variables.ts index 2b39f2320b91f..6f828f396db74 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -275,6 +275,7 @@ export default { searchFiltersTooltipShiftHorizontalNarrow: -10, searchFiltersTooltipShiftVerticalNarrow: 5, bottomTabInboxTooltipShiftHorizontal: 36, + expenseReportsTypeTooltipShiftHorizontal: 10, inlineImagePreviewMinSize: 64, inlineImagePreviewMaxSize: 148, diff --git a/src/types/onyx/DismissedProductTraining.ts b/src/types/onyx/DismissedProductTraining.ts index 283c660be2e11..da7c2751e5e09 100644 --- a/src/types/onyx/DismissedProductTraining.ts +++ b/src/types/onyx/DismissedProductTraining.ts @@ -12,6 +12,7 @@ const { SCAN_TEST_TOOLTIP, SCAN_TEST_TOOLTIP_MANAGER, SCAN_TEST_CONFIRMATION, + EXPENSE_REPORTS_FILTER, } = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES; /** * This type is used to store the timestamp of when the user dismisses a product training ui elements. @@ -77,6 +78,12 @@ type DismissedProductTraining = { */ [SCAN_TEST_CONFIRMATION]: string; + /** + * When user dismisses the expenseReportsFilter product training tooltip, we store the timestamp here. + */ + [EXPENSE_REPORTS_FILTER]: string; + + /** * When user dismisses the ChangeReportPolicy feature training modal, we store the timestamp here. */ diff --git a/tests/ui/components/ProductTrainingContextProvider.tsx b/tests/ui/components/ProductTrainingContextProvider.tsx index 6bc131f80be2d..0a4e6fd45ec9d 100644 --- a/tests/ui/components/ProductTrainingContextProvider.tsx +++ b/tests/ui/components/ProductTrainingContextProvider.tsx @@ -197,10 +197,10 @@ describe('ProductTrainingContextProvider', () => { Onyx.merge(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: true}); await waitForBatchedUpdatesWithAct(); - const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.CONCEIRGE_LHN_GBR; + const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.EXPENSE_REPORTS_FILTER; const {result, rerender} = renderHook(() => useProductTrainingContext(testTooltip), {wrapper}); // Then narrow layout tooltip should not show - expect(result.current.shouldShowProductTrainingTooltip).toBe(false); + expect(result.current.shouldShowProductTrainingTooltip).toBe(true); // When narrow layout changes to true mockUseResponsiveLayout.mockReturnValue({...DEFAULT_USE_RESPONSIVE_LAYOUT_VALUE, shouldUseNarrowLayout: true}); @@ -208,7 +208,7 @@ describe('ProductTrainingContextProvider', () => { await waitForBatchedUpdatesWithAct(); // Then narrow layout tooltip should show - expect(result.current.shouldShowProductTrainingTooltip).toBe(true); + expect(result.current.shouldShowProductTrainingTooltip).toBe(false); }); it('should handle wide layout specific tooltips based on screen width', async () => { // When narrow layout is true From 1ba51c4859ca43751799ad7885ac630d8688d533 Mon Sep 17 00:00:00 2001 From: Rayane <77965000+rayane-d@users.noreply.github.com> Date: Wed, 9 Apr 2025 14:09:51 +0100 Subject: [PATCH 02/12] prettier --- src/types/onyx/DismissedProductTraining.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/types/onyx/DismissedProductTraining.ts b/src/types/onyx/DismissedProductTraining.ts index cb687220bf5d2..8d91c66a1c743 100644 --- a/src/types/onyx/DismissedProductTraining.ts +++ b/src/types/onyx/DismissedProductTraining.ts @@ -67,7 +67,6 @@ type DismissedProductTraining = { */ [EXPENSE_REPORTS_FILTER]: string; - /** * When user dismisses the ChangeReportPolicy feature training modal, we store the timestamp here. */ From d982a3c1b822829676e02a1b4bb54b98df71233d Mon Sep 17 00:00:00 2001 From: Rayane <77965000+rayane-d@users.noreply.github.com> Date: Wed, 9 Apr 2025 14:09:58 +0100 Subject: [PATCH 03/12] fix test --- tests/ui/components/ProductTrainingContextProvider.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/ui/components/ProductTrainingContextProvider.tsx b/tests/ui/components/ProductTrainingContextProvider.tsx index b40c8972da78e..13bf30d42b9ad 100644 --- a/tests/ui/components/ProductTrainingContextProvider.tsx +++ b/tests/ui/components/ProductTrainingContextProvider.tsx @@ -258,10 +258,9 @@ describe('ProductTrainingContextProvider', () => { Onyx.merge(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: true}); await waitForBatchedUpdatesWithAct(); - // TODO: To be replaced by expense reports search tooltip - const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.CONCEIRGE_LHN_GBR; + const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.EXPENSE_REPORTS_FILTER; const {result, rerender} = renderHook(() => useProductTrainingContext(testTooltip), {wrapper}); - // Then narrow layout tooltip should not show + // Then wide layout tooltip should show expect(result.current.shouldShowProductTrainingTooltip).toBe(true); // When narrow layout changes to true @@ -269,7 +268,7 @@ describe('ProductTrainingContextProvider', () => { rerender({}); await waitForBatchedUpdatesWithAct(); - // Then narrow layout tooltip should show + // Then narrow layout tooltip should hide expect(result.current.shouldShowProductTrainingTooltip).toBe(false); }); it('should handle wide layout specific tooltips based on screen width', async () => { From cc3a2f5289ae7dc4664a4ff7b10b3fa5c8b80c57 Mon Sep 17 00:00:00 2001 From: Rayane <77965000+rayane-d@users.noreply.github.com> Date: Wed, 9 Apr 2025 16:41:18 +0100 Subject: [PATCH 04/12] include user policy admin and migration in visibility conditions --- .../ProductTrainingContext/TOOLTIPS.ts | 9 ++++--- .../ProductTrainingContext/index.tsx | 24 ++++++++++++++++++- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/components/ProductTrainingContext/TOOLTIPS.ts b/src/components/ProductTrainingContext/TOOLTIPS.ts index b7180aeb073e4..ce97556371a13 100644 --- a/src/components/ProductTrainingContext/TOOLTIPS.ts +++ b/src/components/ProductTrainingContext/TOOLTIPS.ts @@ -18,7 +18,9 @@ const { type ProductTrainingTooltipName = ValueOf; type ShouldShowConditionProps = { - shouldUseNarrowLayout?: boolean; + shouldUseNarrowLayout: boolean; + isUserPolicyAdmin: boolean; + hasBeenAddedToNudgeMigration: boolean; }; type TooltipData = { @@ -74,7 +76,7 @@ const TOOLTIPS: Record = { onHideTooltip: () => dismissProductTraining(BOTTOM_NAV_INBOX_TOOLTIP), name: BOTTOM_NAV_INBOX_TOOLTIP, priority: 1700, - shouldShow: () => true, + shouldShow: ({hasBeenAddedToNudgeMigration}) => hasBeenAddedToNudgeMigration, }, [LHN_WORKSPACE_CHAT_TOOLTIP]: { content: [ @@ -96,7 +98,8 @@ const TOOLTIPS: Record = { onHideTooltip: () => dismissProductTraining(EXPENSE_REPORTS_FILTER), name: EXPENSE_REPORTS_FILTER, priority: 2000, - shouldShow: ({shouldUseNarrowLayout}) => !shouldUseNarrowLayout, + shouldShow: ({shouldUseNarrowLayout, isUserPolicyAdmin, hasBeenAddedToNudgeMigration}: ShouldShowConditionProps) => + !shouldUseNarrowLayout && isUserPolicyAdmin && hasBeenAddedToNudgeMigration, }, [SCAN_TEST_TOOLTIP]: { content: [ diff --git a/src/components/ProductTrainingContext/index.tsx b/src/components/ProductTrainingContext/index.tsx index c877e1d45fbce..74a71937055f3 100644 --- a/src/components/ProductTrainingContext/index.tsx +++ b/src/components/ProductTrainingContext/index.tsx @@ -12,6 +12,7 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {parseFSAttributes} from '@libs/Fullstory'; import {hasCompletedGuidedSetupFlowSelector} from '@libs/onboardingSelectors'; +import {getActiveAdminWorkspaces} from '@libs/PolicyUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type ChildrenProps from '@src/types/utils/ChildrenProps'; @@ -51,6 +52,16 @@ function ProductTrainingContextProvider({children}: ChildrenProps) { selector: hasCompletedGuidedSetupFlowSelector, }); + const [allPolicies, allPoliciesMetadata] = useOnyx(ONYXKEYS.COLLECTION.POLICY); + const [currentUserLogin, currentUserLoginMetadata] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.email}); + + const isUserPolicyAdmin = useMemo(() => { + if (!allPolicies || !currentUserLogin || isLoadingOnyxValue(allPoliciesMetadata, currentUserLoginMetadata)) { + return false; + } + return getActiveAdminWorkspaces(allPolicies, currentUserLogin).length > 0; + }, [allPolicies, currentUserLogin, allPoliciesMetadata, currentUserLoginMetadata]); + const [dismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING); const {shouldUseNarrowLayout} = useResponsiveLayout(); @@ -125,9 +136,20 @@ function ProductTrainingContextProvider({children}: ChildrenProps) { return tooltipConfig.shouldShow({ shouldUseNarrowLayout, + isUserPolicyAdmin, + hasBeenAddedToNudgeMigration, }); }, - [dismissedProductTraining, hasBeenAddedToNudgeMigration, isOnboardingCompleted, isOnboardingCompletedMetadata, shouldUseNarrowLayout, isModalVisible, isLoadingApp], + [ + dismissedProductTraining, + hasBeenAddedToNudgeMigration, + isOnboardingCompleted, + isOnboardingCompletedMetadata, + shouldUseNarrowLayout, + isModalVisible, + isLoadingApp, + isUserPolicyAdmin, + ], ); const registerTooltip = useCallback( From 99709eecb724dbb9e731a6273de378993284631b Mon Sep 17 00:00:00 2001 From: Rayane <77965000+rayane-d@users.noreply.github.com> Date: Wed, 9 Apr 2025 16:50:48 +0100 Subject: [PATCH 05/12] fix test --- tests/ui/components/ProductTrainingContextProvider.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/ui/components/ProductTrainingContextProvider.tsx b/tests/ui/components/ProductTrainingContextProvider.tsx index 13bf30d42b9ad..a453cf8e14585 100644 --- a/tests/ui/components/ProductTrainingContextProvider.tsx +++ b/tests/ui/components/ProductTrainingContextProvider.tsx @@ -252,6 +252,15 @@ describe('ProductTrainingContextProvider', () => { describe('Layout Specific Behavior', () => { it('should handle narrow layout specific tooltips based on screen width', async () => { + // When migrated user has dismissed welcome modal + Onyx.merge(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: true}); + 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()), + }); + await waitForBatchedUpdatesWithAct(); + // When narrow layout is false mockUseResponsiveLayout.mockReturnValue({...DEFAULT_USE_RESPONSIVE_LAYOUT_VALUE, shouldUseNarrowLayout: false}); From 8bf03550c945f87c5999cfa6bbe6cf5ae9733ac2 Mon Sep 17 00:00:00 2001 From: Rayane <77965000+rayane-d@users.noreply.github.com> Date: Wed, 9 Apr 2025 16:56:31 +0100 Subject: [PATCH 06/12] remove unnecessary test --- .../ProductTrainingContextProvider.tsx | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/tests/ui/components/ProductTrainingContextProvider.tsx b/tests/ui/components/ProductTrainingContextProvider.tsx index a453cf8e14585..c763e64e50ab2 100644 --- a/tests/ui/components/ProductTrainingContextProvider.tsx +++ b/tests/ui/components/ProductTrainingContextProvider.tsx @@ -251,35 +251,6 @@ describe('ProductTrainingContextProvider', () => { }); describe('Layout Specific Behavior', () => { - it('should handle narrow layout specific tooltips based on screen width', async () => { - // When migrated user has dismissed welcome modal - Onyx.merge(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: true}); - 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()), - }); - await waitForBatchedUpdatesWithAct(); - - // When narrow layout is false - mockUseResponsiveLayout.mockReturnValue({...DEFAULT_USE_RESPONSIVE_LAYOUT_VALUE, shouldUseNarrowLayout: false}); - - Onyx.merge(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: true}); - await waitForBatchedUpdatesWithAct(); - - const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.EXPENSE_REPORTS_FILTER; - const {result, rerender} = renderHook(() => useProductTrainingContext(testTooltip), {wrapper}); - // Then wide layout tooltip should show - expect(result.current.shouldShowProductTrainingTooltip).toBe(true); - - // When narrow layout changes to true - mockUseResponsiveLayout.mockReturnValue({...DEFAULT_USE_RESPONSIVE_LAYOUT_VALUE, shouldUseNarrowLayout: true}); - rerender({}); - await waitForBatchedUpdatesWithAct(); - - // Then narrow layout tooltip should hide - expect(result.current.shouldShowProductTrainingTooltip).toBe(false); - }); it('should handle wide layout specific tooltips based on screen width', async () => { // When narrow layout is true mockUseResponsiveLayout.mockReturnValue({...DEFAULT_USE_RESPONSIVE_LAYOUT_VALUE, shouldUseNarrowLayout: true}); From af1f1a498cefaf6433a3eabed7f5ebe8081e4508 Mon Sep 17 00:00:00 2001 From: Rayane <77965000+rayane-d@users.noreply.github.com> Date: Tue, 22 Apr 2025 22:40:04 +0100 Subject: [PATCH 07/12] correct type --- src/types/onyx/DismissedProductTraining.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/onyx/DismissedProductTraining.ts b/src/types/onyx/DismissedProductTraining.ts index e53034a177cd4..28a19a9e42927 100644 --- a/src/types/onyx/DismissedProductTraining.ts +++ b/src/types/onyx/DismissedProductTraining.ts @@ -76,7 +76,7 @@ type DismissedProductTraining = { /** * When user dismisses the expenseReportsFilter product training tooltip, we store the timestamp here. */ - [EXPENSE_REPORTS_FILTER]: string; + [EXPENSE_REPORTS_FILTER]: DismissedProductTrainingElement; /** * When user dismisses the ChangeReportPolicy feature training modal, we store the timestamp here. From 6f3704dee1285ba2217031ed32c55426ffb90790 Mon Sep 17 00:00:00 2001 From: Rayane <77965000+rayane-d@users.noreply.github.com> Date: Tue, 22 Apr 2025 22:43:37 +0100 Subject: [PATCH 08/12] Fix Changed files ESLint check errors --- src/components/ProductTrainingContext/index.tsx | 13 +++++++------ src/pages/Search/SearchTypeMenu.tsx | 12 ++++++------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/components/ProductTrainingContext/index.tsx b/src/components/ProductTrainingContext/index.tsx index e1f437c285150..1a6f7642d3873 100644 --- a/src/components/ProductTrainingContext/index.tsx +++ b/src/components/ProductTrainingContext/index.tsx @@ -49,15 +49,16 @@ const ProductTrainingContext = createContext({ }); function ProductTrainingContextProvider({children}: ChildrenProps) { - const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP, {initialValue: true}); - const [tryNewDot] = useOnyx(ONYXKEYS.NVP_TRYNEWDOT); + const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP, {initialValue: true, canBeMissing: true}); + const [tryNewDot] = useOnyx(ONYXKEYS.NVP_TRYNEWDOT, {canBeMissing: true}); const hasBeenAddedToNudgeMigration = !!tryNewDot?.nudgeMigration?.timestamp; const [isOnboardingCompleted = true, isOnboardingCompletedMetadata] = useOnyx(ONYXKEYS.NVP_ONBOARDING, { selector: hasCompletedGuidedSetupFlowSelector, + canBeMissing: true, }); - const [allPolicies, allPoliciesMetadata] = useOnyx(ONYXKEYS.COLLECTION.POLICY); - const [currentUserLogin, currentUserLoginMetadata] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.email}); + const [allPolicies, allPoliciesMetadata] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true}); + const [currentUserLogin, currentUserLoginMetadata] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.email, canBeMissing: true}); const isUserPolicyAdmin = useMemo(() => { if (!allPolicies || !currentUserLogin || isLoadingOnyxValue(allPoliciesMetadata, currentUserLoginMetadata)) { @@ -66,10 +67,10 @@ function ProductTrainingContextProvider({children}: ChildrenProps) { return getActiveAdminWorkspaces(allPolicies, currentUserLogin).length > 0; }, [allPolicies, currentUserLogin, allPoliciesMetadata, currentUserLoginMetadata]); - const [dismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING); + const [dismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true}); const {shouldUseNarrowLayout} = useResponsiveLayout(); - const [modal] = useOnyx(ONYXKEYS.MODAL); + const [modal] = useOnyx(ONYXKEYS.MODAL, {canBeMissing: true}); // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const isModalVisible = modal?.isVisible || modal?.willAlertModalBecomeVisible; diff --git a/src/pages/Search/SearchTypeMenu.tsx b/src/pages/Search/SearchTypeMenu.tsx index 7fdcdcf175878..18af8c966b327 100644 --- a/src/pages/Search/SearchTypeMenu.tsx +++ b/src/pages/Search/SearchTypeMenu.tsx @@ -52,7 +52,7 @@ function SearchTypeMenu({queryJSON}: SearchTypeMenuProps) { const {singleExecution} = useSingleExecution(); const {translate} = useLocalize(); const {canUseLeftHandBar} = usePermissions(); - const [savedSearches] = useOnyx(ONYXKEYS.SAVED_SEARCHES); + const [savedSearches] = useOnyx(ONYXKEYS.SAVED_SEARCHES, {canBeMissing: true}); const {isOffline} = useNetwork(); const shouldShowSavedSearchesMenuItemTitle = Object.values(savedSearches ?? {}).filter((s) => s.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || isOffline).length > 0; const isFocused = useIsFocused(); @@ -67,12 +67,12 @@ function SearchTypeMenu({queryJSON}: SearchTypeMenuProps) { hideProductTrainingTooltip: hideExpenseReportsTypeTooltip, } = useProductTrainingContext(CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.EXPENSE_REPORTS_FILTER, true); const {showDeleteModal, DeleteConfirmModal} = useDeleteSavedSearch(); - const [session] = useOnyx(ONYXKEYS.SESSION); - const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY); + const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: true}); + const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true}); const personalDetails = usePersonalDetails(); - const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT); - const [userCardList] = useOnyx(ONYXKEYS.CARD_LIST); - const [workspaceCardFeeds] = useOnyx(ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST); + const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: true}); + const [userCardList] = useOnyx(ONYXKEYS.CARD_LIST, {canBeMissing: true}); + const [workspaceCardFeeds] = useOnyx(ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST, {canBeMissing: true}); const allCards = useMemo(() => mergeCardListWithWorkspaceFeeds(workspaceCardFeeds ?? CONST.EMPTY_OBJECT, userCardList), [userCardList, workspaceCardFeeds]); const taxRates = getAllTaxRates(); const {clearSelectedTransactions} = useSearchContext(); From 4703bb18eb524dd82ce9135342c151684468b39d Mon Sep 17 00:00:00 2001 From: Rayane <77965000+rayane-d@users.noreply.github.com> Date: Wed, 23 Apr 2025 15:30:39 +0100 Subject: [PATCH 09/12] update translations --- src/languages/es.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/languages/es.ts b/src/languages/es.ts index 3493c4092c555..73ae914191ac0 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -6730,10 +6730,10 @@ const translations = { part2: ' aquí', }, bottomNavInboxTooltip: { - part1: 'Consulta lo que ', - part2: 'requiere tu atención', + part1: 'Revisa lo que ', + part2: 'necesita tu atención', part3: '\ny ', - part4: 'chatea sobre gastos.', + part4: 'chatea sobre los gastos.', }, workspaceChatTooltip: { part1: 'Envía gastos', @@ -6746,9 +6746,9 @@ const translations = { part3: '\ny mucho más!', }, expenseReportsFilter: { - part1: '¡Bienvenido!\nEncuentra todos los ', - part2: 'informes de tu empresa', - part3: ' aquí.', + part1: '¡Bienvenido!\nAquí encontrarás todos los ', + part2: 'informes de tu empresa.', + part3: '', }, scanTestTooltip: { part1: '¿Quieres ver cómo funciona Escanear?', From a7ddc82ad0965cfe1cf7ac02e0026be3a312b7cc Mon Sep 17 00:00:00 2001 From: Rayane <77965000+rayane-d@users.noreply.github.com> Date: Wed, 23 Apr 2025 15:53:57 +0100 Subject: [PATCH 10/12] improve Spanish translations for expense reports filter --- src/languages/es.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/languages/es.ts b/src/languages/es.ts index 73ae914191ac0..65147a89148ec 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -6746,9 +6746,9 @@ const translations = { part3: '\ny mucho más!', }, expenseReportsFilter: { - part1: '¡Bienvenido!\nAquí encontrarás todos los ', - part2: 'informes de tu empresa.', - part3: '', + part1: '¡Bienvenido! Aquí encontrarás todos los\n', + part2: 'informes de tu empresa', + part3: '.', }, scanTestTooltip: { part1: '¿Quieres ver cómo funciona Escanear?', From 40e21184125662aaa57a1d8de8428d9a164644ef Mon Sep 17 00:00:00 2001 From: Rayane <77965000+rayane-d@users.noreply.github.com> Date: Wed, 23 Apr 2025 16:01:17 +0100 Subject: [PATCH 11/12] fix formatting in expense reports filter translation --- src/languages/en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index 89105f6892915..4a75c7082f4d3 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -6223,7 +6223,7 @@ const translations = { part3: '\nand more!', }, expenseReportsFilter: { - part1: 'Welcome!\nFind all of your ', + part1: 'Welcome! Find all of your\n', part2: "company's reports", part3: ' here.', }, From a2033624ccf9e7acaab40c7e776f91061e7ace77 Mon Sep 17 00:00:00 2001 From: Rayane <77965000+rayane-d@users.noreply.github.com> Date: Wed, 23 Apr 2025 17:06:38 +0100 Subject: [PATCH 12/12] adjust line breaks --- src/languages/en.ts | 4 ++-- src/languages/es.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index d6de6ba10b1ef..eeb5544bd354d 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -6224,8 +6224,8 @@ const translations = { part3: '\nand more!', }, expenseReportsFilter: { - part1: 'Welcome! Find all of your\n', - part2: "company's reports", + part1: 'Welcome! Find all of your', + part2: "\ncompany's reports", part3: ' here.', }, scanTestTooltip: { diff --git a/src/languages/es.ts b/src/languages/es.ts index 9ffd33790cc1b..33bb784df54d9 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -6747,8 +6747,8 @@ const translations = { part3: '\ny mucho más!', }, expenseReportsFilter: { - part1: '¡Bienvenido! Aquí encontrarás todos los\n', - part2: 'informes de tu empresa', + part1: '¡Bienvenido! Aquí encontrarás todos los', + part2: '\ninformes de tu empresa', part3: '.', }, scanTestTooltip: {