From 21f170479ef888bb8573a59448063c964d89c30e Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Fri, 14 Jul 2023 17:54:54 +0300 Subject: [PATCH 1/3] MP-216 init --- .../src/settings/tabs/account/AccountTab.tsx | 3 ++ .../account/address/MemberAddress.module.scss | 19 ++++++++ .../tabs/account/address/MemberAddress.tsx | 43 +++++++++++++++++++ .../settings/tabs/account/address/index.ts | 1 + .../core/lib/profile/user-profile.model.ts | 7 +++ 5 files changed, 73 insertions(+) create mode 100644 src/apps/accounts/src/settings/tabs/account/address/MemberAddress.module.scss create mode 100644 src/apps/accounts/src/settings/tabs/account/address/MemberAddress.tsx create mode 100644 src/apps/accounts/src/settings/tabs/account/address/index.ts diff --git a/src/apps/accounts/src/settings/tabs/account/AccountTab.tsx b/src/apps/accounts/src/settings/tabs/account/AccountTab.tsx index 536d321a6..b0551acda 100644 --- a/src/apps/accounts/src/settings/tabs/account/AccountTab.tsx +++ b/src/apps/accounts/src/settings/tabs/account/AccountTab.tsx @@ -5,6 +5,7 @@ import { UserProfile, UserTraits } from '~/libs/core' import { AccountRole } from './account-role' import { SecuritySection } from './security' import { UserAndPassword } from './user-and-pass' +import { MemberAddress } from './address' import styles from './AccountTab.module.scss' interface AccountTabProps { @@ -20,6 +21,8 @@ const AccountTab: FC = (props: AccountTabProps) => ( + + ) diff --git a/src/apps/accounts/src/settings/tabs/account/address/MemberAddress.module.scss b/src/apps/accounts/src/settings/tabs/account/address/MemberAddress.module.scss new file mode 100644 index 000000000..09192f31e --- /dev/null +++ b/src/apps/accounts/src/settings/tabs/account/address/MemberAddress.module.scss @@ -0,0 +1,19 @@ +@import '@libs/ui/styles/includes'; + +.container { + margin: $sp-8 0; + + .content { + display: grid; + grid-template-columns: repeat(2, 1fr); + margin-bottom: 0; + + @include ltelg { + grid-template-columns: 1fr; + } + + >p { + max-width: 380px; + } + } +} \ No newline at end of file diff --git a/src/apps/accounts/src/settings/tabs/account/address/MemberAddress.tsx b/src/apps/accounts/src/settings/tabs/account/address/MemberAddress.tsx new file mode 100644 index 000000000..e14c10407 --- /dev/null +++ b/src/apps/accounts/src/settings/tabs/account/address/MemberAddress.tsx @@ -0,0 +1,43 @@ +import { Dispatch, FC, useCallback, useEffect, useMemo, useState } from 'react' +import { toast } from 'react-toastify' + +import { + Collapsible, +} from '~/libs/ui' +import { + UserProfile, +} from '~/libs/core' + +import styles from './MemberAddress.module.scss' + +interface MemberAddressProps { + profile: UserProfile +} + +const MemberAddress: FC = (props: MemberAddressProps) => { + const [formValues, setFormValues]: [any, Dispatch] = useState({ + country: props.profile.homeCountryCode || props.profile.competitionCountryCode, + ...props.profile.addresses ? props.profile.addresses[0] : {}, + }) + + console.log('formValues', formValues) + + return ( + Address} + containerClass={styles.container} + contentClass={styles.content} + > +

+ By keeping this information up to date we may surprise you with a cool T-shirt. + Sharing your contact details will never result in robocalls about health insurance plans or junk mail. +

+ +
+ +
+
+ ) +} + +export default MemberAddress diff --git a/src/apps/accounts/src/settings/tabs/account/address/index.ts b/src/apps/accounts/src/settings/tabs/account/address/index.ts new file mode 100644 index 000000000..33f8c6ff5 --- /dev/null +++ b/src/apps/accounts/src/settings/tabs/account/address/index.ts @@ -0,0 +1 @@ +export { default as MemberAddress } from './MemberAddress' diff --git a/src/libs/core/lib/profile/user-profile.model.ts b/src/libs/core/lib/profile/user-profile.model.ts index df103b652..0b16be9fa 100644 --- a/src/libs/core/lib/profile/user-profile.model.ts +++ b/src/libs/core/lib/profile/user-profile.model.ts @@ -1,6 +1,13 @@ export type TC_TRACKS = 'DEVELOP' | 'DESIGN' | 'DATA_SCIENCE' export interface UserProfile { + addresses?: Array<{ + city?: string + stateCode?: string + streetAddr1?: string + streetAddr2?: string + zip?: string + }> competitionCountryCode: string createdAt: number description: string From c12c790fc5fc9b2128b0f6b4ead07977080536e1 Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Fri, 14 Jul 2023 18:40:27 +0300 Subject: [PATCH 2/3] MP-216 address form --- .../account/address/MemberAddress.module.scss | 8 ++ .../tabs/account/address/MemberAddress.tsx | 136 +++++++++++++++++- .../core/lib/profile/data-providers/index.ts | 1 + .../data-providers/useCountryLookup.ts | 10 ++ 4 files changed, 149 insertions(+), 6 deletions(-) create mode 100644 src/libs/core/lib/profile/data-providers/useCountryLookup.ts diff --git a/src/apps/accounts/src/settings/tabs/account/address/MemberAddress.module.scss b/src/apps/accounts/src/settings/tabs/account/address/MemberAddress.module.scss index 09192f31e..32ea795a5 100644 --- a/src/apps/accounts/src/settings/tabs/account/address/MemberAddress.module.scss +++ b/src/apps/accounts/src/settings/tabs/account/address/MemberAddress.module.scss @@ -15,5 +15,13 @@ >p { max-width: 380px; } + + .form { + .formCTAs { + margin-top: $sp-4; + padding-top: $sp-4; + border-top: 2px solid $black-10; + } + } } } \ No newline at end of file diff --git a/src/apps/accounts/src/settings/tabs/account/address/MemberAddress.tsx b/src/apps/accounts/src/settings/tabs/account/address/MemberAddress.tsx index e14c10407..2787d7845 100644 --- a/src/apps/accounts/src/settings/tabs/account/address/MemberAddress.tsx +++ b/src/apps/accounts/src/settings/tabs/account/address/MemberAddress.tsx @@ -1,10 +1,15 @@ -import { Dispatch, FC, useCallback, useEffect, useMemo, useState } from 'react' +import { Dispatch, FC, SetStateAction, useCallback, useEffect, useMemo, useState } from 'react' import { toast } from 'react-toastify' +import { bind, trim } from 'lodash' +import classNames from 'classnames' import { - Collapsible, + Button, + Collapsible, InputSelect, InputText, } from '~/libs/ui' import { + CountryLookup, + useCountryLookup, UserProfile, } from '~/libs/core' @@ -15,12 +20,50 @@ interface MemberAddressProps { } const MemberAddress: FC = (props: MemberAddressProps) => { + const countryLookup: CountryLookup[] | undefined + = useCountryLookup() + const [formValues, setFormValues]: [any, Dispatch] = useState({ country: props.profile.homeCountryCode || props.profile.competitionCountryCode, ...props.profile.addresses ? props.profile.addresses[0] : {}, }) - console.log('formValues', formValues) + const [formErrors, setFormErrors]: [ + { [key: string]: string }, + Dispatch> + ] + = useState<{ [key: string]: string }>({}) + + const [isSaving, setIsSaving]: [boolean, Dispatch>] + = useState(false) + + const [isFormChanged, setIsFormChanged]: [boolean, Dispatch>] + = useState(false) + + function handleFormValueChange(key: string, event: React.ChangeEvent): void { + const oldFormValues = { ...formValues } + + setFormValues({ + ...oldFormValues, + [key]: event.target.value, + }) + setIsFormChanged(true) + } + + function handleFormAction(): void { + if (!trim(formValues.city)) { + setFormErrors({ city: 'Please select a city' }) + return + } + + if (!formValues.country) { + setFormErrors({ country: 'Please select a country' }) + return + } + + setIsSaving(true) + + } return ( = (props: MemberAddressProps) => { Sharing your contact details will never result in robocalls about health insurance plans or junk mail.

-
- -
+
+
+ + + + + + ({ + label: cl.country, + value: cl.countryCode, + }))} + value={formValues.country} + onChange={bind(handleFormValueChange, this, 'country')} + name='country' + label='Country *' + error={formErrors.country} + placeholder='Select a Country' + dirty + /> + +
+
+
+
) } diff --git a/src/libs/core/lib/profile/data-providers/index.ts b/src/libs/core/lib/profile/data-providers/index.ts index fbb7d6d0d..1eca95f91 100644 --- a/src/libs/core/lib/profile/data-providers/index.ts +++ b/src/libs/core/lib/profile/data-providers/index.ts @@ -10,3 +10,4 @@ export * from './useMemberMFAStatus' export * from './useDiceIdConnection' export * from './useMemberTraits' export * from './useMemberDevicesLookup' +export * from './useCountryLookup' diff --git a/src/libs/core/lib/profile/data-providers/useCountryLookup.ts b/src/libs/core/lib/profile/data-providers/useCountryLookup.ts new file mode 100644 index 000000000..02c9b0972 --- /dev/null +++ b/src/libs/core/lib/profile/data-providers/useCountryLookup.ts @@ -0,0 +1,10 @@ +import { SWRResponse } from 'swr' +import useSWRImmutable from 'swr/immutable' + +import { CountryLookup, countryLookupURL } from '~/libs/core' + +export function useCountryLookup(): CountryLookup[] | undefined { + const { data }: SWRResponse = useSWRImmutable(countryLookupURL) + + return data ? data.result?.content : undefined +} From 19882140c4c23f1e083b99fd53a6b714e194d322 Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Mon, 17 Jul 2023 05:58:58 +0300 Subject: [PATCH 3/3] MP-216 save address --- .../tabs/account/address/MemberAddress.tsx | 38 ++++++++++++++++--- .../lib/profile/modify-user-profile.model.ts | 9 +++++ 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/apps/accounts/src/settings/tabs/account/address/MemberAddress.tsx b/src/apps/accounts/src/settings/tabs/account/address/MemberAddress.tsx index 2787d7845..6d55d1a18 100644 --- a/src/apps/accounts/src/settings/tabs/account/address/MemberAddress.tsx +++ b/src/apps/accounts/src/settings/tabs/account/address/MemberAddress.tsx @@ -1,4 +1,4 @@ -import { Dispatch, FC, SetStateAction, useCallback, useEffect, useMemo, useState } from 'react' +import { Dispatch, FC, SetStateAction, useState } from 'react' import { toast } from 'react-toastify' import { bind, trim } from 'lodash' import classNames from 'classnames' @@ -9,6 +9,7 @@ import { } from '~/libs/ui' import { CountryLookup, + updateMemberProfileAsync, useCountryLookup, UserProfile, } from '~/libs/core' @@ -63,6 +64,31 @@ const MemberAddress: FC = (props: MemberAddressProps) => { setIsSaving(true) + updateMemberProfileAsync( + props.profile.handle, + { + addresses: [{ + city: formValues.city, + stateCode: formValues.stateCode, + streetAddr1: formValues.streetAddr1, + streetAddr2: formValues.streetAddr2, + zip: formValues.zip, + }], + competitionCountryCode: formValues.country, + homeCountryCode: formValues.country, + }, + ) + .then(() => { + toast.success('Your account has been updated.', { position: toast.POSITION.BOTTOM_RIGHT }) + setFormErrors({}) + }) + .catch(() => { + toast.error('Something went wrong. Please try again.', { position: toast.POSITION.BOTTOM_RIGHT }) + }) + .finally(() => { + setIsFormChanged(false) + setIsSaving(false) + }) } return ( @@ -88,7 +114,7 @@ const MemberAddress: FC = (props: MemberAddressProps) => { dirty tabIndex={0} type='text' - onChange={bind(handleFormValueChange, this, 'address')} + onChange={bind(handleFormValueChange, this, 'streetAddr1')} value={formValues.streetAddr1} /> = (props: MemberAddressProps) => { dirty tabIndex={0} type='text' - onChange={bind(handleFormValueChange, this, 'address2')} + onChange={bind(handleFormValueChange, this, 'streetAddr2')} value={formValues.streetAddr2} /> = (props: MemberAddressProps) => { + competitionCountryCode?: string + homeCountryCode?: string firstName?: string lastName?: string tracks?: TC_TRACKS[],