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
1 change: 1 addition & 0 deletions src/apps/accounts/src/lib/assets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './security'
export * from './preferences'
export * from './payments'
export * from './tools'
export * from './tcandyou'
11 changes: 11 additions & 0 deletions src/apps/accounts/src/lib/assets/tcandyou/data_science.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions src/apps/accounts/src/lib/assets/tcandyou/design.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions src/apps/accounts/src/lib/assets/tcandyou/develop.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions src/apps/accounts/src/lib/assets/tcandyou/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ReactComponent as DevelopmentTrackIcon } from './develop.svg'
import { ReactComponent as DesignTrackIcon } from './design.svg'
import { ReactComponent as DataScienceTrackIcon } from './data_science.svg'
import ethereumCommunityImage from './ico-ethereum.png'
import ibmCommunityImage from './ico-ibmcloud.png'
import veteransCommunityImage from './ico-veteran.png'

export {
ethereumCommunityImage,
ibmCommunityImage,
veteransCommunityImage,
DesignTrackIcon,
DataScienceTrackIcon,
DevelopmentTrackIcon,
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { AccountTab } from './account'
import { PreferencesTab } from './preferences'
import { PaymentsTab } from './payments'
import { ToolsTab } from './tools'
import { TCandYouTab } from './tcandyou'
import styles from './AccountSettingsTabs.module.scss'

interface AccountSettingsTabsProps {
Expand All @@ -23,7 +24,9 @@ const AccountSettingsTabs: FC<AccountSettingsTabsProps> = (props: AccountSetting
const [activeTab, setActiveTab]: [string, Dispatch<SetStateAction<string>>]
= useState<string>(activeTabHash)

const memberTraits: UserTraits[] | undefined = useMemberTraits(props.profile.handle)
const { data: memberTraits }: {
data: UserTraits[] | undefined
} = useMemberTraits(props.profile.handle)

function handleTabChange(tabId: string): void {
setActiveTab(tabId)
Expand All @@ -45,6 +48,10 @@ const AccountSettingsTabs: FC<AccountSettingsTabsProps> = (props: AccountSetting
'Topcoder'].join(' | ')}
</PageTitle>

{activeTab === AccountSettingsTabViews.tcandyou && (
<TCandYouTab profile={props.profile} memberTraits={memberTraits} />
)}

{activeTab === AccountSettingsTabViews.tools && (
<ToolsTab profile={props.profile} memberTraits={memberTraits} />
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import { Dispatch, FC, useCallback, useEffect, useMemo, useState } from 'react'
import { has, trim } from 'lodash'
import { toast } from 'react-toastify'
import { KeyedMutator } from 'swr'

import {
Collapsible,
Form,
FormInputModel,
FormToggleSwitch,
} from '~/libs/ui'
import { updateMemberPasswordAsync, updateMemberTraitsAsync, UserProfile, UserTrait, UserTraits } from '~/libs/core'
import {
updateMemberPasswordAsync,
updateMemberTraitsAsync,
useMemberTraits,
UserProfile,
UserTrait,
UserTraits,
} from '~/libs/core'
import { SettingSection } from '~/apps/accounts/src/lib'

import { UserAndPassFromConfig } from './user-and-pass.form.config'
Expand All @@ -30,6 +38,8 @@ const UserAndPassword: FC<UserAndPasswordProps> = (props: UserAndPasswordProps)
[props.memberTraits],
)

const { mutate: mutateTraits }: { mutate: KeyedMutator<any> } = useMemberTraits(props.profile.handle)

const [userConsent, setUserConsent]: [boolean, Dispatch<boolean>] = useState(false)

const requestGenerator: (inputs: ReadonlyArray<FormInputModel>) => any
Expand Down Expand Up @@ -70,6 +80,7 @@ const UserAndPassword: FC<UserAndPasswordProps> = (props: UserAndPasswordProps)
}])
.then(() => {
setUserConsent(!userConsent)
mutateTraits()
toast.success('User consent updated successfully.')
})
.catch(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ export enum AccountSettingsTabViews {
account = '1',
preferences = '2',
payment = '3',
tcandyou = '4',
}

export const AccountSettingsTabsConfig: TabsNavItem[] = [
{
id: AccountSettingsTabViews.tcandyou,
title: 'Topcoder & You',
},
{
id: AccountSettingsTabViews.tools,
title: 'Tools',
Expand All @@ -28,6 +33,7 @@ export const AccountSettingsTabsConfig: TabsNavItem[] = [

export function getHashFromTabId(tabId: string): string {
switch (tabId) {
case AccountSettingsTabViews.tcandyou: return '#tcandyou'
case AccountSettingsTabViews.tools: return '#tools'
case AccountSettingsTabViews.account: return '#account'
case AccountSettingsTabViews.preferences: return '#preferences'
Expand All @@ -38,6 +44,7 @@ export function getHashFromTabId(tabId: string): string {

export function getTabIdFromHash(hash: string): string {
switch (hash) {
case '#tcandyou': return AccountSettingsTabViews.tcandyou
case '#tools': return AccountSettingsTabViews.tools
case '#account': return AccountSettingsTabViews.account
case '#preferences': return AccountSettingsTabViews.preferences
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@import '@libs/ui/styles/includes';

.container {
background-color: $black-5;
padding: $sp-6;
margin: $sp-8 0;
border-radius: 6px;

@include ltelg {
padding: $sp-4;
}
}
27 changes: 27 additions & 0 deletions src/apps/accounts/src/settings/tabs/tcandyou/TCandYouTab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { FC } from 'react'

import { UserProfile, UserTraits } from '~/libs/core'

import { Tracks } from './tracks'
import { Communities } from './communities'
import styles from './TCandYouTab.module.scss'

interface TCandYouTabProps {
profile: UserProfile
memberTraits: UserTraits[] | undefined
}

const TCandYouTab: FC<TCandYouTabProps> = (props: TCandYouTabProps) => (
<div className={styles.container}>
<h3>You And Topcoder</h3>

<Tracks profile={props.profile} />

<Communities
communityTraits={props.memberTraits?.find(trait => trait.traitId === 'communities')}
profile={props.profile}
/>
</div>
)

export default TCandYouTab
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
@import '@libs/ui/styles/includes';

.container {
margin: $sp-8 0;

.content {
display: flex;
flex-direction: column;
margin-bottom: 0;

.communityCard {
border: 1px solid #d4d4d4;
border-radius: 8px;
padding: $sp-4;
margin-bottom: $sp-4;
display: flex;
justify-content: space-between;
align-items: flex-start;

.communityCardHeader {
display: flex;
align-items: flex-start;

@include ltelg {
flex-direction: column;
}
}

img {
margin-right: $sp-4;
border-radius: 4px;

@include ltelg {
margin-right: 0;
margin-bottom: $sp-4;
}
}

.communityInfo {
flex: 1;

.infoText {
padding-right: 74px;
color: #767676;
margin: $sp-3 0;
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react'
import { bind } from 'lodash'
import { KeyedMutator } from 'swr'
import { toast } from 'react-toastify'

import { updateMemberTraitsAsync, useMemberTraits, UserProfile, UserTraits } from '~/libs/core'
import { Button, Collapsible, FormToggleSwitch } from '~/libs/ui'

import { communitiesConfig } from './communities-config'
import styles from './Communities.module.scss'

interface CommunitiesProps {
communityTraits: UserTraits | undefined
profile: UserProfile
}

interface CommunitiesDataStatus {
[key: string]: boolean
}

const Communities: FC<CommunitiesProps> = (props: CommunitiesProps) => {
const [memberCommunities, setMemberCommunities]: [
CommunitiesDataStatus | undefined,
Dispatch<SetStateAction<CommunitiesDataStatus | undefined>>
]
= useState<CommunitiesDataStatus | undefined>()

const { mutate: mutateTraits }: { mutate: KeyedMutator<any> } = useMemberTraits(props.profile.handle)

useEffect(() => {
setMemberCommunities(props.communityTraits?.traits.data[0])
}, [props.communityTraits])

function handleCommunitiesChange(communityId: string): void {
const updatedCommunities: CommunitiesDataStatus = {
...memberCommunities,
[communityId]: !memberCommunities?.[communityId],
}

updateMemberTraitsAsync(props.profile.handle, [{
categoryName: 'Communities',
traitId: 'communities',
traits: {
data: [updatedCommunities],
},
}])
.then(() => {
setMemberCommunities(updatedCommunities)
mutateTraits()
toast.success('Communities updated successfully.')
})
.catch(() => {
toast.error('Failed to update user Communities.')
})
}

function handleLearnMoreClick(link: string): void {
window.open(link, '_blank')
}

return (
<Collapsible
header={<h3>Your Communities</h3>}
containerClass={styles.container}
contentClass={styles.content}
>
{
communitiesConfig.map(community => (
<div className={styles.communityCard} key={community.id}>
<div className={styles.communityCardHeader}>
<img src={community.icon} alt={community.name} />
<div className={styles.communityInfo}>
<p className='body-main-bold'>{community.name}</p>
<p className={styles.infoText}>{community.description}</p>
<Button
secondary
size='sm'
label='Learn More'
onClick={bind(handleLearnMoreClick, this, community.link)}
/>
</div>
</div>
<FormToggleSwitch
name={community.id}
onChange={bind(handleCommunitiesChange, this, community.id)}
value={memberCommunities?.[community.id] || false}
/>
</div>
))
}
</Collapsible>
)
}

export default Communities
Loading