From 1e8b3cc2b6e92eb5d24215be0bc52a9a828c94fb Mon Sep 17 00:00:00 2001 From: Amar Trebinjac Date: Tue, 13 Jan 2026 17:05:19 +0100 Subject: [PATCH 1/3] feat: add dismissable profile completion indicator Add dismiss button to profile completion card in dropdown menu. When dismissed, both the yellow indicator dot on the profile button and the card are permanently hidden. Uses the action pattern for persistent dismissal tracking. - Add DismissProfileCompletionIndicator action type - Update useProfileCompletionIndicator to check dismissal status - Add showDismiss prop to ProfileCompletion component - Display dismiss button above card content in dropdown only - Remove feature flag and always show indicator for incomplete profiles Co-Authored-By: Claude Haiku 4.5 --- .../components/ProfileMenu/ProfileMenu.tsx | 2 +- .../ProfileWidgets/ProfileCompletion.tsx | 42 +++++++++++++------ packages/shared/src/graphql/actions.ts | 1 + .../profile/useProfileCompletionIndicator.ts | 22 +++++++--- 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/packages/shared/src/components/ProfileMenu/ProfileMenu.tsx b/packages/shared/src/components/ProfileMenu/ProfileMenu.tsx index 7c38a2d63c..20a1a5fa71 100644 --- a/packages/shared/src/components/ProfileMenu/ProfileMenu.tsx +++ b/packages/shared/src/components/ProfileMenu/ProfileMenu.tsx @@ -62,7 +62,7 @@ export default function ProfileMenu({ position={InteractivePopupPosition.ProfileMenu} className="flex w-full max-w-80 flex-col gap-3 !rounded-10 border border-border-subtlest-tertiary !bg-accent-pepper-subtlest p-3" > - {showProfileCompletion && } + {showProfileCompletion && } { export const ProfileCompletion = ({ className, + showDismiss = false, }: ProfileCompletionProps): ReactElement | null => { const { user } = useAuthContext(); + const { dismissIndicator } = useProfileCompletionIndicator(); const profileCompletion = user?.profileCompletion; const items = useMemo( @@ -103,16 +109,26 @@ export const ProfileCompletion = ({ } return ( - - -
+ ); }; diff --git a/packages/shared/src/graphql/actions.ts b/packages/shared/src/graphql/actions.ts index 1e4a28c6a3..d774f40a8e 100644 --- a/packages/shared/src/graphql/actions.ts +++ b/packages/shared/src/graphql/actions.ts @@ -56,6 +56,7 @@ export enum ActionType { ProfileCompleted = 'profile_completed', ClickedOpportunityNavigation = 'click_opportunity_navigation', ProfileCompletionCard = 'profile_completion_card', + DismissProfileCompletionIndicator = 'dismiss_profile_completion_indicator', } export const cvActions = [ diff --git a/packages/shared/src/hooks/profile/useProfileCompletionIndicator.ts b/packages/shared/src/hooks/profile/useProfileCompletionIndicator.ts index 2932c52c87..dd5dda09dd 100644 --- a/packages/shared/src/hooks/profile/useProfileCompletionIndicator.ts +++ b/packages/shared/src/hooks/profile/useProfileCompletionIndicator.ts @@ -1,21 +1,31 @@ +import { useCallback } from 'react'; import { useAuthContext } from '../../contexts/AuthContext'; -import { useFeature } from '../../components/GrowthBookProvider'; -import { featureProfileCompletionIndicator } from '../../lib/featureManagement'; +import { useActions } from '../useActions'; +import { ActionType } from '../../graphql/actions'; interface UseProfileCompletionIndicator { showIndicator: boolean; + dismissIndicator: () => void; } export const useProfileCompletionIndicator = (): UseProfileCompletionIndicator => { const { user } = useAuthContext(); + const { checkHasCompleted, completeAction, isActionsFetched } = + useActions(); const profileCompletionPercentage = user?.profileCompletion?.percentage ?? 100; - const profileCompletionThreshold = useFeature( - featureProfileCompletionIndicator, - ); + + const isDismissed = + isActionsFetched && + checkHasCompleted(ActionType.DismissProfileCompletionIndicator); + + const dismissIndicator = useCallback(() => { + completeAction(ActionType.DismissProfileCompletionIndicator); + }, [completeAction]); return { - showIndicator: profileCompletionPercentage < profileCompletionThreshold, + showIndicator: profileCompletionPercentage < 100 && !isDismissed, + dismissIndicator, }; }; From 1670f68fbf28b05c9704b23b066794a13f094b29 Mon Sep 17 00:00:00 2001 From: Amar Trebinjac Date: Tue, 13 Jan 2026 17:17:24 +0100 Subject: [PATCH 2/3] test: add QueryClientProvider to ProfileCompletion tests The ProfileCompletion component now uses useProfileCompletionIndicator which relies on useActions that requires QueryClientProvider. Co-Authored-By: Claude Opus 4.5 --- .../ProfileWidgets/ProfileCompletion.spec.tsx | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/packages/shared/src/features/profile/components/ProfileWidgets/ProfileCompletion.spec.tsx b/packages/shared/src/features/profile/components/ProfileWidgets/ProfileCompletion.spec.tsx index 74922ca082..32778fca44 100644 --- a/packages/shared/src/features/profile/components/ProfileWidgets/ProfileCompletion.spec.tsx +++ b/packages/shared/src/features/profile/components/ProfileWidgets/ProfileCompletion.spec.tsx @@ -1,5 +1,6 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import type { ProfileCompletion as ProfileCompletionData, LoggedUser, @@ -7,6 +8,14 @@ import type { import { ProfileCompletion } from './ProfileCompletion'; import { AuthContextProvider } from '../../../../contexts/AuthContext'; +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, +}); + const createMockUser = ( profileCompletion: ProfileCompletionData, ): LoggedUser => ({ @@ -27,20 +36,22 @@ const createMockUser = ( const renderWithAuth = (user: LoggedUser | null) => { return render( - - - , + + + + + , ); }; From 3a54ef200019ae877ee133b403b939dd1ecb7fc7 Mon Sep 17 00:00:00 2001 From: Amar Trebinjac Date: Tue, 13 Jan 2026 17:27:04 +0100 Subject: [PATCH 3/3] refactor: always show dismiss button on ProfileCompletion Remove showDismiss prop and always display the dismiss button regardless of where the component is rendered. Co-Authored-By: Claude Opus 4.5 --- .../src/components/ProfileMenu/ProfileMenu.tsx | 2 +- .../ProfileWidgets/ProfileCompletion.tsx | 15 ++++----------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/packages/shared/src/components/ProfileMenu/ProfileMenu.tsx b/packages/shared/src/components/ProfileMenu/ProfileMenu.tsx index 20a1a5fa71..7c38a2d63c 100644 --- a/packages/shared/src/components/ProfileMenu/ProfileMenu.tsx +++ b/packages/shared/src/components/ProfileMenu/ProfileMenu.tsx @@ -62,7 +62,7 @@ export default function ProfileMenu({ position={InteractivePopupPosition.ProfileMenu} className="flex w-full max-w-80 flex-col gap-3 !rounded-10 border border-border-subtlest-tertiary !bg-accent-pepper-subtlest p-3" > - {showProfileCompletion && } + {showProfileCompletion && } { export const ProfileCompletion = ({ className, - showDismiss = false, }: ProfileCompletionProps): ReactElement | null => { const { user } = useAuthContext(); const { dismissIndicator } = useProfileCompletionIndicator(); @@ -115,19 +113,14 @@ export const ProfileCompletion = ({ className, )} > - {showDismiss && ( -
- -
- )} +
+ +