Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
2356176
MP-390 - Fix wording & winning icon for member stats
vas3a Dec 6, 2023
49af1fd
MP-390
vas3a Dec 6, 2023
503a433
update comment
vas3a Dec 6, 2023
f580ee8
Merge pull request #951 from topcoder-platform/MP-390_members-stats-fix
vas3a Dec 6, 2023
2c12f9a
MP-391 - fix rating display for CP track
vas3a Dec 13, 2023
ec43301
Merge pull request #952 from topcoder-platform/MP-391_member-profile-…
vas3a Dec 13, 2023
506fccb
feat: wallet app
rakibansary Jan 4, 2024
2bb8abd
fix: lint errors
rakibansary Jan 4, 2024
d186cd0
ci: deploy to dev
rakibansary Jan 4, 2024
b438e47
fix(core-163): navigation on link click
rakibansary Jan 10, 2024
c0c1698
fix(core-170): incorrect tab on refresh
rakibansary Jan 10, 2024
54712dc
fix(core-189): disable payme button when balance is zero
rakibansary Jan 10, 2024
c1cf54c
fix(core-184): tax forms tab layout
rakibansary Jan 10, 2024
5e9515f
fix(core-184): add resend otp flow
rakibansary Jan 10, 2024
3603957
fix(core-184): tax form flow
rakibansary Jan 12, 2024
5a59483
fix(tax-form): tax form layout and flow
rakibansary Jan 15, 2024
0ee226a
chore: lint fixes
rakibansary Jan 15, 2024
e23c871
fix(payment-providers): layout on mobile
rakibansary Jan 15, 2024
363bf33
fix(payment-providers): layout fixes
rakibansary Jan 16, 2024
af1ccf4
fix(tax-form): profile prop is not needed
rakibansary Jan 16, 2024
4d90343
fix(payment-providers): layout fixes
rakibansary Jan 16, 2024
de20599
fix(payment-providers): style & layout
rakibansary Jan 16, 2024
78c3c36
fix(payment-providers): paypal connection
rakibansary Jan 16, 2024
87e5afc
fix(core-234): show banner if user has already signed the doc
rakibansary Jan 16, 2024
bdfc149
fix(core-182): resend otp flow
rakibansary Jan 16, 2024
71231b5
fix(core-182): resend otp flow
rakibansary Jan 16, 2024
86fc1d1
fix(core-182): resend otp flow
rakibansary Jan 16, 2024
8f6638f
fix(core-171): show release date
rakibansary Jan 16, 2024
c958cf6
fix(core-171): show release date
rakibansary Jan 16, 2024
8fac88a
fix(payment-providers): connected label should not be clickable
rakibansary Jan 16, 2024
e56e3f6
fix(winnings): club installments together
rakibansary Jan 17, 2024
77618e1
fix(winnings): currency format
rakibansary Jan 17, 2024
695f604
fix(core-246): email should be bold
rakibansary Jan 17, 2024
6159ed6
feat(wallet-admin): first draft
rakibansary Jan 24, 2024
9e9de7e
wip: wallet admin
rakibansary Jan 28, 2024
0e01f11
fix(winnings): prettier table
rakibansary Jan 30, 2024
03b801e
fix(payment-providers): core-181 design fixes
rakibansary Jan 30, 2024
9962787
fix(lint): lint fixes
rakibansary Jan 30, 2024
2e07656
fix(winnings): core-241 select all checkbox
rakibansary Jan 30, 2024
b00fa57
fix(payment-provider): style issues
rakibansary Jan 31, 2024
78d8ac1
fix: lint & style issues
rakibansary Jan 31, 2024
3c180fd
feat(winnings): add filter bar
rakibansary Jan 31, 2024
663c832
feat(winnings): add pagination
rakibansary Jan 31, 2024
cd59b6d
fix(winnings): handle null search results
rakibansary Feb 1, 2024
4f9add3
fix(winnings): reset page when filters are changed
rakibansary Feb 1, 2024
d7bd18b
fix: text corrections
rakibansary Feb 1, 2024
705b52b
fix: keep selection state across page navigation
rakibansary Feb 1, 2024
896f60c
feat(winnings): add pagination size control
rakibansary Feb 1, 2024
9d8198f
fix(winnings): select all behaviour
rakibansary Feb 1, 2024
c99f8bf
fix: remove wallet-admin for production deploy
rakibansary Feb 7, 2024
62447ba
Merge branch 'dev' into CORE-96
rakibansary Feb 7, 2024
10c8603
Merge pull request #954 from topcoder-platform/CORE-96
rakibansary Feb 7, 2024
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: 0 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,6 @@ workflows:
branches:
only:
- dev
- MP-356_member-stats-and-history

- deployQa:
context: org-global
Expand Down
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
quote_type = single
3 changes: 3 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"semi": false
}
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"prettier.requireConfig": true,
"editor.formatOnSave": false
}
1 change: 1 addition & 0 deletions craco.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ module.exports = {
'@gamificationAdmin': resolve('src/apps/gamification-admin/src'),
'@talentSearch': resolve('src/apps/talent-search/src'),
'@profiles': resolve('src/apps/profiles/src'),
'@wallet': resolve('src/apps/wallet/src'),

'@platform': resolve('src/apps/platform/src'),
// aliases used in SCSS files
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@storybook/react": "^7.0.5",
"@stripe/react-stripe-js": "1.13.0",
"@stripe/stripe-js": "1.41.0",
"@tanstack/react-table": "^8.11.7",
"@types/testing-library__jest-dom": "^5.14.5",
"apexcharts": "^3.36.0",
"axios": "^1.1.2",
Expand Down Expand Up @@ -85,6 +86,7 @@
"react-helmet": "^6.1.0",
"react-html-parser": "^2.0.2",
"react-markdown": "8.0.6",
"react-otp-input": "^3.1.1",
"react-popper": "^2.3.0",
"react-redux": "^8.0.4",
"react-redux-toastr": "^7.6.10",
Expand Down
7 changes: 6 additions & 1 deletion src/apps/platform/src/platform.routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ import { profilesRoutes } from '~/apps/profiles'
import { talentSearchRoutes } from '~/apps/talent-search'
import { accountsRoutes } from '~/apps/accounts'
import { onboardingRoutes } from '~/apps/onboarding'
import { walletRoutes } from '~/apps/wallet'

const Home: LazyLoadedComponent = lazyLoad(() => import('./routes/home'), 'HomePage')
const Home: LazyLoadedComponent = lazyLoad(
() => import('./routes/home'),
'HomePage',
)

const homeRoutes: ReadonlyArray<PlatformRoute> = [
{
Expand All @@ -32,6 +36,7 @@ export const platformRoutes: Array<PlatformRoute> = [
...gamificationAdminRoutes,
...talentSearchRoutes,
...profilesRoutes,
...walletRoutes,
...accountsRoutes,
...homeRoutes,
]
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { getRatingColor, MemberStats, UserProfile } from '~/libs/core'
import { IconOutline } from '~/libs/ui'

import { useFetchActiveTracks } from '../../../hooks'
import { WinnerIcon } from '../../../lib'
import { formatPlural, WinnerIcon } from '../../../lib'
import { MemberProfileContextValue, useMemberProfileContext } from '../../../member-profile/MemberProfile.context'

import styles from './MemberStatsBlock.module.scss'
Expand Down Expand Up @@ -45,30 +45,25 @@ const MemberStatsBlock: FC<MemberStatsBlockProps> = props => {
<div className={styles.trackDetails}>
{!track.isDSTrack && ((track.submissions || track.wins) > 0) && (
<>
<WinnerIcon className='icon-xxxl' />
{track.wins > 0 && (
<WinnerIcon className='icon-xxxl' />
)}
<span className={styles.trackStats}>
<span className={styles.count}>
{track.wins || track.submissions}
</span>
<span className={styles.label}>
{track.wins > 0 ? 'Wins' : 'Submissions'}
{formatPlural(
track.wins || track.submissions || 0,
track.wins > 0 ? 'Win' : 'Submission',
)}
</span>
</span>
</>
)}
{/* competitive programming only */}
{track.isDSTrack && (
(track.percentile as number) >= 50 ? (
<span className={styles.trackStats}>
<span className={styles.count}>
{track.percentile}
%
</span>
<span className={styles.label}>
Percentile
</span>
</span>
) : (
(track.isCPTrack || (track.percentile as number) < 50) ? (
<>
<span
className={styles.icon}
Expand All @@ -83,6 +78,16 @@ const MemberStatsBlock: FC<MemberStatsBlockProps> = props => {
</span>
</span>
</>
) : (
<span className={styles.trackStats}>
<span className={styles.count}>
{track.percentile}
%
</span>
<span className={styles.label}>
Percentile
</span>
</span>
)
)}
<IconOutline.ChevronRightIcon
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { find, get } from 'lodash'

import { getRatingColor } from '~/libs/core'

import { numberToFixed } from '../../../lib'
import { formatPlural, numberToFixed } from '../../../lib'
import { TracksSummaryStats } from '../../../config'

import styles from './StatsSummaryBlock.module.scss'
Expand Down Expand Up @@ -49,7 +49,10 @@ const StatsSummaryBlock: FC<StatsSummaryBlockProps> = props => {
</span>
<span className={styles.summaryItemLabel}>
<span className='body-small'>
{props.trackTitle === 'Single Round Match' ? 'Competitions' : 'Challenges'}
{formatPlural(
props.challenges || 0,
props.trackTitle === 'Single Round Match' ? 'Competition' : 'Challenge',
)}
</span>
</span>
</div>
Expand All @@ -61,7 +64,7 @@ const StatsSummaryBlock: FC<StatsSummaryBlockProps> = props => {
</span>
<span className={styles.summaryItemLabel}>
<span className='body-small'>
Wins
{formatPlural(props.wins || 0, 'Win')}
</span>
</span>
</div>
Expand All @@ -73,7 +76,7 @@ const StatsSummaryBlock: FC<StatsSummaryBlockProps> = props => {
</span>
<span className={styles.summaryItemLabel}>
<span className='body-small'>
Submissions
{formatPlural(props.submissions || 0, 'Submission')}
</span>
</span>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import classNames from 'classnames'

import { IconSolid } from '~/libs/ui'

import { subTrackLabelToHumanName, WinnerIcon } from '../../../lib'
import { formatPlural, subTrackLabelToHumanName, WinnerIcon } from '../../../lib'

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

Expand All @@ -29,7 +29,9 @@ const SubTrackSummaryCard: FC<SubTrackSummaryCardProps> = props => (
{props.wins}
</span>
<span className={styles.statsItemLabel}>
<span className='label'>wins</span>
<span className='label'>
{formatPlural(props.wins || 0, 'Win')}
</span>
</span>
</div>
)}
Expand All @@ -38,7 +40,9 @@ const SubTrackSummaryCard: FC<SubTrackSummaryCardProps> = props => (
{props.submissions}
</span>
<span className={styles.statsItemLabel}>
<span className='label'>submissions</span>
<span className='label'>
{formatPlural(props.submissions || 0, 'Submission')}
</span>
</span>
</div>
</div>
Expand Down
2 changes: 2 additions & 0 deletions src/apps/profiles/src/hooks/useFetchActiveTracks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface MemberStatsTrack {
wins: number,
order?: number
isDSTrack?: boolean
isCPTrack?: boolean
}

/**
Expand Down Expand Up @@ -206,6 +207,7 @@ export const useFetchActiveTracks = (userHandle: string): MemberStatsTrack[] =>
return {
challenges: dataScienceSubTracks.SRM?.challenges ?? 0,
isActive: (dataScienceSubTracks.SRM?.challenges ?? 0) > 0,
isCPTrack: true,
isDSTrack: true,
name: 'Competitive Programming',
order: -2,
Expand Down
12 changes: 12 additions & 0 deletions src/apps/profiles/src/lib/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,15 @@ export function isValidURL(urlToValidate: string): boolean {

return true
}

/**
* Creates the string with the number of items and the word describing the item
* possibly in plural form.
*
* @param {number} count - The number of entities
* @param {string} baseWord - The base word that describes the entity
* @returns {string}
*/
export function formatPlural(count: number, baseWord: string): string {
return `${baseWord}${count === 1 ? '' : 's'}`
}
7 changes: 7 additions & 0 deletions src/apps/wallet/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"semi": false,
"trailingComma": "all",
"jsxSingleQuote": true,
"jsxBracketSameLine": true,
"printWidth": 120
}
Empty file added src/apps/wallet/README.md
Empty file.
1 change: 1 addition & 0 deletions src/apps/wallet/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './src'
20 changes: 20 additions & 0 deletions src/apps/wallet/src/WalletApp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { FC, useContext } from 'react'
import { Outlet, Routes } from 'react-router-dom'

import { routerContext, RouterContextData } from '~/libs/core'

import { toolTitle } from './wallet.routes'
import { WalletSwr } from './lib'

const AccountsApp: FC<{}> = () => {
const { getChildRoutes }: RouterContextData = useContext(routerContext)

return (
<WalletSwr>
<Outlet />
<Routes>{getChildRoutes(toolTitle)}</Routes>
</WalletSwr>
)
}

export default AccountsApp
19 changes: 19 additions & 0 deletions src/apps/wallet/src/home/WalletHomePage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { FC, useContext } from 'react'

import { profileContext, ProfileContextData } from '~/libs/core'
import { LoadingSpinner } from '~/libs/ui'

import { WalletLayout } from './page-layout'

const AccountSettingsPage: FC<{}> = () => {
const { profile, initialized }: ProfileContextData = useContext(profileContext)

return (
<>
<LoadingSpinner hide={initialized} />
{initialized && profile && <WalletLayout profile={profile} />}
</>
)
}

export default AccountSettingsPage
1 change: 1 addition & 0 deletions src/apps/wallet/src/home/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as WalletHomePage } from './WalletHomePage'
5 changes: 5 additions & 0 deletions src/apps/wallet/src/home/page-layout/WalletLayout.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@import '@libs/ui/styles/includes';

.contentLayoutOuter {
margin: $sp-8 auto !important;
}
20 changes: 20 additions & 0 deletions src/apps/wallet/src/home/page-layout/WalletLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { FC } from 'react'

import { UserProfile } from '~/libs/core'
import { ContentLayout } from '~/libs/ui'

import { WalletTabs } from '../tabs'

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

interface WalletHomeLayoutProps {
profile: UserProfile
}

const WalletLayout: FC<WalletHomeLayoutProps> = (props: WalletHomeLayoutProps) => (
<ContentLayout outerClass={styles.contentLayoutOuter}>
<WalletTabs profile={props.profile} />
</ContentLayout>
)

export default WalletLayout
1 change: 1 addition & 0 deletions src/apps/wallet/src/home/page-layout/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as WalletLayout } from './WalletLayout'
11 changes: 11 additions & 0 deletions src/apps/wallet/src/home/tabs/WalletTabs.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@import '@libs/ui/styles/includes';

.container {
form {
@include ltelg {
:global(.input-el) {
margin-bottom: $sp-4;
}
}
}
}
55 changes: 55 additions & 0 deletions src/apps/wallet/src/home/tabs/WalletTabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Dispatch, FC, SetStateAction, useEffect, useMemo, useState } from 'react'
import { useLocation } from 'react-router-dom'

import { UserProfile } from '~/libs/core'
import { PageTitle, TabsNavbar, TabsNavItem } from '~/libs/ui'

import { getHashFromTabId, getTabIdFromHash, WalletTabsConfig, WalletTabViews } from './config'
import { PaymentsTab } from './payments'
import { WinningsTab } from './winnings'
import { HomeTab } from './home'
import { TaxFormsTab } from './tax-forms'
import styles from './WalletTabs.module.scss'

interface WalletHomeProps {
profile: UserProfile
}

const WalletTabs: FC<WalletHomeProps> = (props: WalletHomeProps) => {
const { hash }: { hash: string } = useLocation()

const activeTabHash: string = useMemo<string>(() => getTabIdFromHash(hash), [hash])

const [activeTab, setActiveTab]: [string, Dispatch<SetStateAction<string>>] = useState<string>(activeTabHash)

useEffect(() => {
setActiveTab(activeTabHash)
}, [activeTabHash])

function handleTabChange(tabId: string): void {
setActiveTab(tabId)
window.location.hash = getHashFromTabId(tabId)
}

return (
<div className={styles.container}>
<TabsNavbar defaultActive={activeTab} onChange={handleTabChange} tabs={WalletTabsConfig} />

<PageTitle>
{[WalletTabsConfig.find((tab: TabsNavItem) => tab.id === activeTab)?.title, 'Wallet', 'Topcoder'].join(
' | ',
)}
</PageTitle>

{activeTab === WalletTabViews.withdrawalmethods && <PaymentsTab />}

{activeTab === WalletTabViews.winnings && <WinningsTab profile={props.profile} />}

{activeTab === WalletTabViews.home && <HomeTab profile={props.profile} />}

{activeTab === WalletTabViews.taxforms && <TaxFormsTab profile={props.profile} />}
</div>
)
}

export default WalletTabs
1 change: 1 addition & 0 deletions src/apps/wallet/src/home/tabs/config/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './wallet-tabs-config'
Loading