Skip to content

Commit adbe492

Browse files
authored
Merge pull request #943 from topcoder-platform/TAL-93_update-available-for-gigs-flag
TAL-93 update available for gigs flag ->dev
2 parents 2195252 + ec44f65 commit adbe492

File tree

10 files changed

+70
-135
lines changed

10 files changed

+70
-135
lines changed

src/apps/onboarding/src/config/index.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,4 @@
1-
export const ACTIONS: {
2-
MEMBER: {
3-
GET_MEMBER: string;
4-
UPDATE_MEMBER_PHOTO_URL: string;
5-
SET_WORKS: string;
6-
SET_EDUCATIONS: string;
7-
SET_PERSONALIZATIONS: string;
8-
SET_ADDRESS: string;
9-
SET_CONNECT_INFO: string;
10-
SET_DESCRIPTION: string;
11-
SET_LOADING_MEMBER_TRAITS: string;
12-
SET_LOADING_MEMBER_INFO: string;
13-
};
14-
} = {
1+
export const ACTIONS = {
152
MEMBER: {
163
GET_MEMBER: 'GET_MEMBER',
174
SET_ADDRESS: 'SET_ADDRESS',
@@ -20,6 +7,7 @@ export const ACTIONS: {
207
SET_EDUCATIONS: 'SET_EDUCATIONS',
218
SET_LOADING_MEMBER_INFO: 'SET_LOADING_MEMBER_INFO',
229
SET_LOADING_MEMBER_TRAITS: 'SET_LOADING_MEMBER_TRAITS',
10+
SET_OPEN_FOR_WORK: 'SET_OPEN_FOR_WORK',
2311
SET_PERSONALIZATIONS: 'SET_PERSONALIZATIONS',
2412
SET_WORKS: 'SET_WORKS',
2513
UPDATE_MEMBER_PHOTO_URL: 'UPDATE_MEMBER_PHOTO_URL',

src/apps/onboarding/src/models/MemberInfo.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export default interface MemberInfo {
1515
maxRating: MemberMaxRating
1616
skills: Array<UserSkill>
1717
stats: Array<MemberStats>
18+
availableForGigs: boolean
1819
addresses?: MemberAddress[]
1920
country: string
2021
photoURL: string

src/apps/onboarding/src/models/PersonalizationInfo.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ export default interface PersonalizationInfo {
22
referAs?: string
33
profileSelfTitle?: string
44
shortBio?: string
5-
availableForGigs?: boolean
65
}
76

87
export const emptyPersonalizationInfo: () => PersonalizationInfo = () => ({
9-
availableForGigs: true,
108
profileSelfTitle: '',
119
referAs: '',
1210
shortBio: '',

src/apps/onboarding/src/pages/open-to-work/index.tsx

Lines changed: 27 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,51 @@
11
import { useNavigate } from 'react-router-dom'
2-
import { FC, MutableRefObject, useEffect, useMemo, useRef } from 'react'
2+
import { FC, MutableRefObject, useEffect, useRef, useState } from 'react'
33
import { connect } from 'react-redux'
4+
import { pick } from 'lodash'
45
import classNames from 'classnames'
56

67
import { Button, IconOutline, PageDivider } from '~/libs/ui'
78
import { FormInputCheckbox } from '~/apps/self-service/src/components/form-elements'
89

9-
import { createMemberPersonalizations, updateMemberPersonalizations } from '../../redux/actions/member'
1010
import { ProgressBar } from '../../components/progress-bar'
11-
import { useAutoSavePersonalization, useAutoSavePersonalizationType } from '../../hooks/useAutoSavePersonalization'
12-
import PersonalizationInfo, { emptyPersonalizationInfo } from '../../models/PersonalizationInfo'
11+
import { updateMemberOpenForWork } from '../../redux/actions/member'
1312

1413
import styles from './styles.module.scss'
1514

1615
const FormInputCheckboxMiddleware: any = FormInputCheckbox as any
1716

18-
const blankPersonalizationInfo: PersonalizationInfo = emptyPersonalizationInfo()
19-
20-
interface PageOpenToWorkContentReduxProps {
21-
reduxPersonalizations: PersonalizationInfo[] | undefined
22-
loadingMemberTraits: boolean
23-
}
24-
25-
interface PageOpenToWorkContentProps extends PageOpenToWorkContentReduxProps {
26-
updateMemberPersonalizations: (infos: PersonalizationInfo[]) => void
27-
createMemberPersonalizations: (infos: PersonalizationInfo[]) => void
17+
interface PageOpenToWorkContentProps {
18+
availableForGigs: boolean
19+
updateMemberOpenForWork: (isOpenForWork: boolean) => void
2820
}
2921

3022
export const PageOpenToWorkContent: FC<PageOpenToWorkContentProps> = props => {
3123
const navigate: any = useNavigate()
3224

25+
const [loading, setLoading] = useState<boolean>(false)
26+
3327
const shouldSavingData: MutableRefObject<boolean> = useRef<boolean>(false)
3428
const shouldNavigateTo: MutableRefObject<string> = useRef<string>('')
3529

36-
const {
37-
loading,
38-
personalizationInfo,
39-
setPersonalizationInfo,
40-
}: useAutoSavePersonalizationType = useAutoSavePersonalization(
41-
props.reduxPersonalizations,
42-
['availableForGigs'],
43-
props.updateMemberPersonalizations,
44-
props.createMemberPersonalizations,
45-
shouldSavingData,
46-
)
47-
48-
const availableForGigsValue: boolean | undefined = useMemo(() => {
49-
if (!personalizationInfo || personalizationInfo.availableForGigs === undefined) {
50-
return blankPersonalizationInfo.availableForGigs
51-
}
52-
53-
return personalizationInfo.availableForGigs
54-
}, [personalizationInfo])
55-
5630
useEffect(() => {
5731
if (!loading && !shouldSavingData.current && !!shouldNavigateTo.current) {
5832
navigate(shouldNavigateTo.current)
5933
}
6034
/* eslint-disable react-hooks/exhaustive-deps */
6135
}, [loading])
6236

63-
function checkToNavigateNextPage(pageUrl: string): void {
64-
if (!personalizationInfo || personalizationInfo.availableForGigs === undefined) {
65-
shouldNavigateTo.current = pageUrl
66-
setPersonalizationInfo({
67-
...(personalizationInfo || {}),
68-
availableForGigs: blankPersonalizationInfo.availableForGigs,
69-
})
70-
} else {
71-
navigate(pageUrl)
72-
}
37+
function goToPreviousStep(): void {
38+
navigate('../skills')
39+
}
40+
41+
function goToNextStep(): void {
42+
navigate('../works')
43+
}
44+
45+
async function handleSaveAvailableForGigs(e: any): Promise<void> {
46+
setLoading(true)
47+
await props.updateMemberOpenForWork(e.target.checked)
48+
setLoading(false)
7349
}
7450

7551
return (
@@ -90,15 +66,10 @@ export const PageOpenToWorkContent: FC<PageOpenToWorkContentProps> = props => {
9066
<div className='mt-26'>
9167
<FormInputCheckboxMiddleware
9268
label='Yes, I’m open to work'
93-
checked={availableForGigsValue}
69+
checked={props.availableForGigs}
9470
inline
95-
onChange={function onChange(e: any) {
96-
setPersonalizationInfo({
97-
...(personalizationInfo || {}),
98-
availableForGigs: e.target.checked,
99-
})
100-
}}
101-
disabled={props.loadingMemberTraits || loading}
71+
onChange={handleSaveAvailableForGigs}
72+
disabled={loading}
10273
/>
10374
</div>
10475
</div>
@@ -117,18 +88,14 @@ export const PageOpenToWorkContent: FC<PageOpenToWorkContentProps> = props => {
11788
iconToLeft
11889
disabled={loading}
11990
icon={IconOutline.ChevronLeftIcon}
120-
onClick={function previousPage() {
121-
checkToNavigateNextPage('../skills')
122-
}}
91+
onClick={goToPreviousStep}
12392
/>
12493
<Button
12594
size='lg'
12695
primary
12796
iconToLeft
12897
disabled={loading}
129-
onClick={function nextPage() {
130-
checkToNavigateNextPage('../works')
131-
}}
98+
onClick={goToNextStep}
13299
>
133100
next
134101
</Button>
@@ -137,22 +104,10 @@ export const PageOpenToWorkContent: FC<PageOpenToWorkContentProps> = props => {
137104
)
138105
}
139106

140-
const mapStateToProps: (state: any) => PageOpenToWorkContentReduxProps
141-
= (state: any): PageOpenToWorkContentReduxProps => {
142-
const {
143-
loadingMemberTraits,
144-
personalizations,
145-
}: any = state.member
146-
147-
return {
148-
loadingMemberTraits,
149-
reduxPersonalizations: personalizations,
150-
}
151-
}
107+
const mapStateToProps: any = (state: any) => pick(state.member, 'availableForGigs')
152108

153109
const mapDispatchToProps: any = {
154-
createMemberPersonalizations,
155-
updateMemberPersonalizations,
110+
updateMemberOpenForWork,
156111
}
157112

158113
export const PageOpenToWork: any = connect(mapStateToProps, mapDispatchToProps)(PageOpenToWorkContent)

src/apps/onboarding/src/redux/actions/member.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import _ from 'lodash'
22

3-
import { TokenModel, UserTraitCategoryNames, UserTraitIds } from '~/libs/core'
3+
import { TokenModel, updateMemberProfileAsync, UserTraitCategoryNames, UserTraitIds } from '~/libs/core'
44
import { getAsync as getAsyncToken } from '~/libs/core/lib/auth/token-functions/token.functions'
55
import {
66
createMemberTraits,
@@ -396,6 +396,11 @@ export const setMemberPhotoUrl: any = (photoUrl: string) => ({
396396
type: ACTIONS.MEMBER.UPDATE_MEMBER_PHOTO_URL,
397397
})
398398

399+
export const setMemberOpenForWork: any = (isOpenForWork: boolean) => ({
400+
payload: isOpenForWork,
401+
type: ACTIONS.MEMBER.SET_OPEN_FOR_WORK,
402+
})
403+
399404
export const updateMemberHomeAddresss: any = (addresses: MemberAddress[]) => async (dispatch: any) => {
400405
try {
401406
const tokenInfo: TokenModel = await getAsyncToken()
@@ -436,3 +441,16 @@ export const updateMemberPhotoUrl: any = (photoURL: string) => async (dispatch:
436441
} catch (error) {
437442
}
438443
}
444+
445+
export const updateMemberOpenForWork: any = (isOpenForWork: boolean) => async (dispatch: any) => {
446+
try {
447+
const tokenInfo: TokenModel = await getAsyncToken()
448+
449+
await updateMemberProfileAsync(
450+
tokenInfo.handle || '',
451+
{ availableForGigs: isOpenForWork },
452+
)
453+
dispatch(setMemberOpenForWork(isOpenForWork))
454+
} catch (error) {
455+
}
456+
}

src/apps/onboarding/src/redux/reducers/member.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable complexity */
12
import _ from 'lodash'
23

34
import { notifyUniNavi } from '~/apps/profiles/src/lib'
@@ -19,6 +20,7 @@ const initialState: {
1920
connectInfo?: ConnectInfo
2021
loadingMemberTraits?: boolean
2122
loadingMemberInfo?: boolean
23+
availableForGigs?: boolean
2224
} = {
2325
}
2426

@@ -35,6 +37,11 @@ const memberReducer: any = (
3537
...state,
3638
memberInfo: action.payload,
3739
}
40+
case ACTIONS.MEMBER.SET_OPEN_FOR_WORK:
41+
return {
42+
...state,
43+
availableForGigs: action.payload,
44+
}
3845
case ACTIONS.MEMBER.SET_WORKS:
3946
return {
4047
...state,

src/apps/profiles/src/member-profile/profile-header/OpenForGigs/OpenForGigs.tsx

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import { Dispatch, FC, SetStateAction, useEffect, useMemo, useState } from 'react'
1+
import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react'
22
import { useSearchParams } from 'react-router-dom'
3-
import { KeyedMutator } from 'swr'
43
import classNames from 'classnames'
54

6-
import { useMemberTraits, UserProfile, UserTrait, UserTraitIds, UserTraits } from '~/libs/core'
5+
import { UserProfile } from '~/libs/core'
76

87
import { EditMemberPropertyBtn } from '../../../components'
98
import { OpenForGigsModifyModal } from '../OpenForGigsModifyModal'
@@ -26,24 +25,15 @@ const OpenForGigs: FC<OpenForGigsProps> = (props: OpenForGigsProps) => {
2625
const [isEditMode, setIsEditMode]: [boolean, Dispatch<SetStateAction<boolean>>]
2726
= useState<boolean>(false)
2827

28+
const openForWork = props.profile.availableForGigs
29+
2930
useEffect(() => {
3031
if (props.authProfile && editMode === profileEditModes.openForWork) {
3132
setIsEditMode(true)
3233
}
3334
// eslint-disable-next-line react-hooks/exhaustive-deps
3435
}, [props.authProfile])
3536

36-
const { data: memberPersonalizationTraits, mutate: mutateTraits }: {
37-
data: UserTraits[] | undefined,
38-
mutate: KeyedMutator<any>,
39-
}
40-
= useMemberTraits(props.profile.handle, { traitIds: UserTraitIds.personalization })
41-
42-
const openForWork: UserTrait | undefined
43-
= useMemo(() => memberPersonalizationTraits?.[0]?.traits?.data?.find(
44-
(trait: UserTrait) => trait.availableForGigs !== undefined,
45-
), [memberPersonalizationTraits])
46-
4737
function handleModifyOpenForWorkClick(): void {
4838
setIsEditMode(true)
4939
}
@@ -55,16 +45,15 @@ const OpenForGigs: FC<OpenForGigsProps> = (props: OpenForGigsProps) => {
5545
function handleModifyOpenForWorkSave(): void {
5646
setTimeout(() => {
5747
setIsEditMode(false)
58-
mutateTraits()
5948
props.refreshProfile(props.profile.handle)
6049
triggerSurvey()
6150
}, 1000)
6251
}
6352

6453
return props.canEdit || openForWork ? (
6554
<div className={styles.container}>
66-
<p className={classNames('body-main-bold', !openForWork?.availableForGigs ? styles.notOopenToWork : '')}>
67-
{openForWork?.availableForGigs ? 'open to work' : 'not open to work'}
55+
<p className={classNames('body-main-bold', !openForWork ? styles.notOopenToWork : '')}>
56+
{openForWork ? 'open to work' : 'not open to work'}
6857
</p>
6958
{
7059
props.canEdit && (
@@ -78,8 +67,7 @@ const OpenForGigs: FC<OpenForGigsProps> = (props: OpenForGigsProps) => {
7867
<OpenForGigsModifyModal
7968
onClose={handleModifyOpenForWorkClose}
8069
onSave={handleModifyOpenForWorkSave}
81-
openForWork={openForWork?.availableForGigs || false}
82-
memberPersonalizationTraitsFullData={memberPersonalizationTraits?.[0]?.traits?.data}
70+
openForWork={openForWork ?? false}
8371
profile={props.profile}
8472
/>
8573
)

src/apps/profiles/src/member-profile/profile-header/OpenForGigsModifyModal/OpenForGigsModifyModal.tsx

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,15 @@
11
import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react'
22
import { toast } from 'react-toastify'
3-
import { reject } from 'lodash'
43

54
import { BaseModal, Button, InputText } from '~/libs/ui'
6-
import {
7-
updateOrCreateMemberTraitsAsync,
8-
UserProfile,
9-
UserTrait,
10-
UserTraitCategoryNames,
11-
UserTraitIds,
12-
} from '~/libs/core'
5+
import { updateMemberProfileAsync, UserProfile } from '~/libs/core'
136

147
import styles from './OpenForGigsModifyModal.module.scss'
158

169
interface OpenForGigsModifyModalProps {
1710
onClose: () => void
1811
onSave: () => void
1912
openForWork: boolean
20-
memberPersonalizationTraitsFullData: UserTrait[] | undefined
2113
profile: UserProfile
2214
}
2315

@@ -35,24 +27,10 @@ const OpenForGigsModifyModal: FC<OpenForGigsModifyModalProps> = (props: OpenForG
3527
function handleOpenForWorkSave(): void {
3628
setIsSaving(true)
3729

38-
const updatedPersonalizationTraits: UserTrait[]
39-
= reject(
40-
props.memberPersonalizationTraitsFullData,
41-
(trait: UserTrait) => trait.availableForGigs !== undefined,
42-
)
43-
44-
updateOrCreateMemberTraitsAsync(props.profile.handle, [{
45-
categoryName: UserTraitCategoryNames.personalization,
46-
traitId: UserTraitIds.personalization,
47-
traits: {
48-
data: [
49-
...(updatedPersonalizationTraits || []),
50-
{
51-
availableForGigs: openForWork,
52-
},
53-
],
54-
},
55-
}])
30+
updateMemberProfileAsync(
31+
props.profile.handle,
32+
{ availableForGigs: openForWork },
33+
)
5634
.then(() => {
5735
toast.success('Work availability updated successfully.', { position: toast.POSITION.BOTTOM_RIGHT })
5836
props.onSave()

src/libs/core/lib/profile/modify-user-profile.model.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export interface UpdateProfileRequest {
88
streetAddr2?: string
99
zip?: string
1010
}>
11+
availableForGigs?: boolean,
1112
competitionCountryCode?: string
1213
homeCountryCode?: string
1314
firstName?: string

0 commit comments

Comments
 (0)