Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ const MemberAddress: FC<MemberAddressProps> = (props: MemberAddressProps) => {
props.profile.handle,
{
addresses: [{
city: formValues.city,
stateCode: formValues.stateCode,
streetAddr1: formValues.streetAddr1,
streetAddr2: formValues.streetAddr2,
zip: formValues.zip,
city: trim(formValues.city),
stateCode: trim(formValues.stateCode),
streetAddr1: trim(formValues.streetAddr1),
streetAddr2: trim(formValues.streetAddr2),
zip: trim(formValues.zip),
}],
competitionCountryCode: formValues.country,
homeCountryCode: formValues.country,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@
align-items: center;
margin-bottom: $sp-2;

svg {
> svg {
margin-right: $sp-2;
width: 24px;
height: 24px;
}

> button {
margin-left: auto;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { FC, useMemo } from 'react'
import { Dispatch, FC, SetStateAction, useMemo, useState } from 'react'
import cityTimezones from 'city-timezones'
import moment from 'moment-timezone'

import { useCountryName, UserProfile } from '~/libs/core'
import { IconSolid } from '~/libs/ui'

import { EditMemberPropertyBtn } from '../../components'

import { ModifyLocationModal } from './ModifyLocationModal'
import styles from './MemberLocalInfo.module.scss'

interface MemberLocalInfoProps {
profile: UserProfile | undefined
profile: UserProfile
authProfile: UserProfile | undefined
refreshProfile: (handle: string) => void
}

const MemberLocalInfo: FC<MemberLocalInfoProps> = (props: MemberLocalInfoProps) => {
Expand All @@ -35,11 +40,38 @@ const MemberLocalInfo: FC<MemberLocalInfoProps> = (props: MemberLocalInfoProps)
return moment.tz.zone(memberTimezone) ? memberTimezone : undefined
}, [city, memberCountry])

const canEdit: boolean = props.authProfile?.handle === props.profile.handle

const [isEditMode, setIsEditMode]: [boolean, Dispatch<SetStateAction<boolean>>]
= useState<boolean>(false)

function handleModifyLocationClick(): void {
setIsEditMode(true)
}

function handleModifyLocationModalClose(): void {
setIsEditMode(false)
}

function handleModifyLocationModalSave(): void {
setTimeout(() => {
setIsEditMode(false)
props.refreshProfile(props.profile.handle)
}, 1000)
}

return (
<div className={styles.container}>
<div className={styles.localInfo}>
<IconSolid.LocationMarkerIcon />
{`${!!city ? `${city}, ` : ''}${memberCountry}`}
{
canEdit && (
<EditMemberPropertyBtn
onClick={handleModifyLocationClick}
/>
)
}
</div>
{
!!memberCityTimezone && (
Expand All @@ -53,6 +85,16 @@ const MemberLocalInfo: FC<MemberLocalInfoProps> = (props: MemberLocalInfoProps)
</div>
)
}

{
isEditMode && (
<ModifyLocationModal
onClose={handleModifyLocationModalClose}
onSave={handleModifyLocationModalSave}
profile={props.profile}
/>
)
}
</div>
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@import '@libs/ui/styles/includes';

.modalButtons {
display: flex;
justify-content: space-between;
width: 100%;
}

.formError {
color: $red-100;
}

.editForm {
margin-top: $sp-4;

:global(.input-wrapper) {
margin-bottom: $sp-4;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { Dispatch, FC, SetStateAction, useState } from 'react'
import { bind, trim } from 'lodash'
import { toast } from 'react-toastify'

import { BaseModal, Button, InputSelect, InputText } from '~/libs/ui'
import {
CountryLookup,
updateMemberProfileAsync,
useCountryLookup,
UserProfile,
} from '~/libs/core'

import styles from './ModifyLocationModal.module.scss'

interface ModifyLocationModalProps {
onClose: () => void
onSave: () => void
profile: UserProfile
}

const ModifyLocationModal: FC<ModifyLocationModalProps> = (props: ModifyLocationModalProps) => {
const countryLookup: CountryLookup[] | undefined
= useCountryLookup()

const [formValues, setFormValues]: [any, Dispatch<any>] = useState({
country: props.profile.homeCountryCode || props.profile.competitionCountryCode,
...props.profile.addresses ? props.profile.addresses[0] : {},
})

const [formSaveError, setFormSaveError]: [
string | undefined,
Dispatch<SetStateAction<string | undefined>>
] = useState<string | undefined>()

const [isSaving, setIsSaving]: [boolean, Dispatch<SetStateAction<boolean>>]
= useState<boolean>(false)

const [isFormChanged, setIsFormChanged]: [boolean, Dispatch<SetStateAction<boolean>>]
= useState<boolean>(false)

function handleFormValueChange(key: string, event: React.ChangeEvent<HTMLInputElement>): void {
const oldFormValues = { ...formValues }

setFormValues({
...oldFormValues,
[key]: event.target.value,
})
setIsFormChanged(true)
}

function handleLocationSave(): void {
updateMemberProfileAsync(
props.profile.handle,
{
addresses: [{
...props.profile.addresses ? props.profile.addresses[0] : {},
city: trim(formValues.city),
}],
competitionCountryCode: formValues.country,
homeCountryCode: formValues.country,
},
)
.then(() => {
toast.success('Your location has been updated.', { position: toast.POSITION.BOTTOM_RIGHT })
props.onSave()
})
.catch((error: any) => {
toast.error('Something went wrong. Please try again.', { position: toast.POSITION.BOTTOM_RIGHT })
setFormSaveError(error.message || error)
})
.finally(() => {
setIsFormChanged(false)
setIsSaving(false)
})
}

return (
<BaseModal
onClose={props.onClose}
open
size='lg'
title='Location'
buttons={(
<div className={styles.modalButtons}>
<Button
label='Cancel'
onClick={props.onClose}
secondary
/>
<Button
label='Save'
onClick={handleLocationSave}
primary
disabled={isSaving || !isFormChanged}
/>
</div>
)}
>
<p>Provide details on your location.</p>
<form className={styles.editForm}>
<InputText
label='City'
name='city'
onChange={bind(handleFormValueChange, this, 'city')}
value={formValues.city}
tabIndex={0}
type='text'
placeholder='Select your city name'
/>
<InputSelect
options={(countryLookup || []).map((cl: CountryLookup) => ({
label: cl.country,
value: cl.countryCode,
}))}
value={formValues.country}
onChange={bind(handleFormValueChange, this, 'country')}
name='country'
label='Country *'
placeholder='Select a Country'
/>
</form>

{
formSaveError && (
<div className={styles.formError}>
{formSaveError}
</div>
)
}

</BaseModal>
)
}

export default ModifyLocationModal
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as ModifyLocationModal } from './ModifyLocationModal'
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ const ProfilePageLayout: FC<ProfilePageLayoutProps> = (props: ProfilePageLayoutP

<MemberLinks profile={props.profile} authProfile={props.authProfile} />

<MemberLocalInfo profile={props.profile} />
<MemberLocalInfo
profile={props.profile}
authProfile={props.authProfile}
refreshProfile={props.refreshProfile}
/>
</div>
<div className={styles.profileInfoRight}>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
UserTraitIds,
UserTraits,
} from '~/libs/core'
import { Button } from '~/libs/ui'

import { EditMemberPropertyBtn } from '../../components'
import { EDIT_MODE_QUERY_PARAM, profileEditModes } from '../../config'
Expand Down Expand Up @@ -72,9 +71,10 @@ const ProfileHeader: FC<ProfileHeaderProps> = (props: ProfileHeaderProps) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.authProfile])

function handleHireMeClick(): void {
console.log('Hire Me button clicked')
}
// Enable this with talent search app
// function handleHireMeClick(): void {
// console.log('Hire Me button clicked')
// }

function handleModifyNameClick(): void {
setIsNameEditMode(true)
Expand Down Expand Up @@ -165,15 +165,16 @@ const ProfileHeader: FC<ProfileHeaderProps> = (props: ProfileHeaderProps) => {
{canEdit ? 'I am' : `${props.profile.firstName} is`}
</span>
<OpenForGigs canEdit={canEdit} authProfile={props.authProfile} profile={props.profile} />
{
{/* Enable this with talent search app */}
{/* {
!canEdit && (
<Button
label={`Hire ${props.profile.firstName}`}
primary
onClick={handleHireMeClick}
/>
)
}
} */}
</div>
) : undefined
}
Expand Down