Skip to content

Commit 4685d84

Browse files
feat: add dismissable profile completion indicator (#5294)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
1 parent 44867ff commit 4685d84

4 files changed

Lines changed: 64 additions & 33 deletions

File tree

packages/shared/src/features/profile/components/ProfileWidgets/ProfileCompletion.spec.tsx

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
import React from 'react';
22
import { render, screen } from '@testing-library/react';
3+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
34
import type {
45
ProfileCompletion as ProfileCompletionData,
56
LoggedUser,
67
} from '../../../../lib/user';
78
import { ProfileCompletion } from './ProfileCompletion';
89
import { AuthContextProvider } from '../../../../contexts/AuthContext';
910

11+
const queryClient = new QueryClient({
12+
defaultOptions: {
13+
queries: {
14+
retry: false,
15+
},
16+
},
17+
});
18+
1019
const createMockUser = (
1120
profileCompletion: ProfileCompletionData,
1221
): LoggedUser => ({
@@ -27,20 +36,22 @@ const createMockUser = (
2736

2837
const renderWithAuth = (user: LoggedUser | null) => {
2938
return render(
30-
<AuthContextProvider
31-
user={user}
32-
updateUser={jest.fn()}
33-
tokenRefreshed
34-
getRedirectUri={jest.fn()}
35-
closeLogin={jest.fn()}
36-
loadingUser={false}
37-
loadedUserFromCache
38-
refetchBoot={jest.fn()}
39-
firstLoad={false}
40-
isValidSession
41-
>
42-
<ProfileCompletion />
43-
</AuthContextProvider>,
39+
<QueryClientProvider client={queryClient}>
40+
<AuthContextProvider
41+
user={user}
42+
updateUser={jest.fn()}
43+
tokenRefreshed
44+
getRedirectUri={jest.fn()}
45+
closeLogin={jest.fn()}
46+
loadingUser={false}
47+
loadedUserFromCache
48+
refetchBoot={jest.fn()}
49+
firstLoad={false}
50+
isValidSession
51+
>
52+
<ProfileCompletion />
53+
</AuthContextProvider>
54+
</QueryClientProvider>,
4455
);
4556
};
4657

packages/shared/src/features/profile/components/ProfileWidgets/ProfileCompletion.tsx

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ import Link from '../../../../components/utilities/Link';
1414
import { anchorDefaultRel } from '../../../../lib/strings';
1515
import { webappUrl } from '../../../../lib/constants';
1616
import { useAuthContext } from '../../../../contexts/AuthContext';
17+
import CloseButton from '../../../../components/CloseButton';
18+
import { ButtonSize } from '../../../../components/buttons/Button';
19+
import { useProfileCompletionIndicator } from '../../../../hooks/profile/useProfileCompletionIndicator';
1720

1821
type CompletionItem = {
1922
label: string;
@@ -75,6 +78,7 @@ export const ProfileCompletion = ({
7578
className,
7679
}: ProfileCompletionProps): ReactElement | null => {
7780
const { user } = useAuthContext();
81+
const { dismissIndicator } = useProfileCompletionIndicator();
7882
const profileCompletion = user?.profileCompletion;
7983

8084
const items = useMemo(
@@ -103,16 +107,21 @@ export const ProfileCompletion = ({
103107
}
104108

105109
return (
106-
<Link href={redirectPath}>
107-
<a
108-
href={redirectPath}
109-
rel={anchorDefaultRel}
110-
className={classNames(
111-
'flex cursor-pointer flex-col gap-6 border border-action-help-active bg-action-help-float p-4 hover:bg-action-help-hover laptop:rounded-16',
112-
className,
113-
)}
114-
>
115-
<div className="flex w-full items-center gap-6">
110+
<div
111+
className={classNames(
112+
'flex cursor-pointer flex-col border border-action-help-active bg-action-help-float hover:bg-action-help-hover laptop:rounded-16',
113+
className,
114+
)}
115+
>
116+
<div className="flex justify-end px-2 pt-2">
117+
<CloseButton size={ButtonSize.XSmall} onClick={dismissIndicator} />
118+
</div>
119+
<Link href={redirectPath}>
120+
<a
121+
href={redirectPath}
122+
rel={anchorDefaultRel}
123+
className="flex w-full items-center gap-6 p-4 pt-0"
124+
>
116125
<div className="flex min-w-0 flex-1 flex-col gap-1">
117126
<div className="flex items-center gap-1">
118127
<InfoIcon
@@ -152,8 +161,8 @@ export const ProfileCompletion = ({
152161
color="help"
153162
/>
154163
</div>
155-
</div>
156-
</a>
157-
</Link>
164+
</a>
165+
</Link>
166+
</div>
158167
);
159168
};

packages/shared/src/graphql/actions.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export enum ActionType {
5656
ProfileCompleted = 'profile_completed',
5757
ClickedOpportunityNavigation = 'click_opportunity_navigation',
5858
ProfileCompletionCard = 'profile_completion_card',
59+
DismissProfileCompletionIndicator = 'dismiss_profile_completion_indicator',
5960
}
6061

6162
export const cvActions = [
Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,31 @@
1+
import { useCallback } from 'react';
12
import { useAuthContext } from '../../contexts/AuthContext';
2-
import { useFeature } from '../../components/GrowthBookProvider';
3-
import { featureProfileCompletionIndicator } from '../../lib/featureManagement';
3+
import { useActions } from '../useActions';
4+
import { ActionType } from '../../graphql/actions';
45

56
interface UseProfileCompletionIndicator {
67
showIndicator: boolean;
8+
dismissIndicator: () => void;
79
}
810

911
export const useProfileCompletionIndicator =
1012
(): UseProfileCompletionIndicator => {
1113
const { user } = useAuthContext();
14+
const { checkHasCompleted, completeAction, isActionsFetched } =
15+
useActions();
1216
const profileCompletionPercentage =
1317
user?.profileCompletion?.percentage ?? 100;
14-
const profileCompletionThreshold = useFeature(
15-
featureProfileCompletionIndicator,
16-
);
18+
19+
const isDismissed =
20+
isActionsFetched &&
21+
checkHasCompleted(ActionType.DismissProfileCompletionIndicator);
22+
23+
const dismissIndicator = useCallback(() => {
24+
completeAction(ActionType.DismissProfileCompletionIndicator);
25+
}, [completeAction]);
1726

1827
return {
19-
showIndicator: profileCompletionPercentage < profileCompletionThreshold,
28+
showIndicator: profileCompletionPercentage < 100 && !isDismissed,
29+
dismissIndicator,
2030
};
2131
};

0 commit comments

Comments
 (0)