Skip to content

Commit c846de6

Browse files
authored
Merge pull request #973 from topcoder-platform/LVT-256
Lvt 256
2 parents e000f3a + 53f1c9c commit c846de6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1493
-1146
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ workflows:
257257
branches:
258258
only:
259259
- dev
260-
- feat/wallet-admin
260+
- LVT-256
261261

262262
- deployQa:
263263
context: org-global

src/apps/wallet-admin/src/home/tabs/WalletAdminTabs.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { PageTitle, TabsNavbar, TabsNavItem } from '~/libs/ui'
77
import { getHashFromTabId, getTabIdFromHash, WalletAdminTabsConfig, WalletAdminTabViews } from './config'
88
import { PaymentsTab } from './payments'
99
import { HomeTab } from './home'
10+
import { TaxFormsTab } from './tax-forms'
11+
import { PaymentMethodsTab } from './payment-methods'
1012
import styles from './WalletAdminTabs.module.scss'
1113

1214
interface WalletHomeProps {
@@ -44,6 +46,10 @@ const WalletAdminTabs: FC<WalletHomeProps> = (props: WalletHomeProps) => {
4446
{activeTab === WalletAdminTabViews.home && <HomeTab profile={props.profile} />}
4547

4648
{activeTab === WalletAdminTabViews.payments && <PaymentsTab profile={props.profile} />}
49+
50+
{activeTab === WalletAdminTabViews.taxforms && <TaxFormsTab profile={props.profile} />}
51+
52+
{activeTab === WalletAdminTabViews.withdrawalmethods && <PaymentMethodsTab profile={props.profile} />}
4753
</div>
4854
)
4955
}

src/apps/wallet-admin/src/home/tabs/config/wallet-tabs-config.ts

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import { TabsNavItem } from '~/libs/ui'
33
export enum WalletAdminTabViews {
44
home = '0',
55
payments = '1',
6-
// taxforms = '2',
7-
// withdrawalmethods = '3',
6+
taxforms = '2',
7+
withdrawalmethods = '3',
88
}
99

1010
export const WalletAdminTabsConfig: TabsNavItem[] = [
@@ -16,14 +16,14 @@ export const WalletAdminTabsConfig: TabsNavItem[] = [
1616
id: WalletAdminTabViews.payments,
1717
title: 'Payments',
1818
},
19-
// {
20-
// id: WalletAdminTabViews.withdrawalmethods,
21-
// title: 'Withdrawal Methods',
22-
// },
23-
// {
24-
// id: WalletAdminTabViews.taxforms,
25-
// title: 'Tax Forms',
26-
// },
19+
{
20+
id: WalletAdminTabViews.withdrawalmethods,
21+
title: 'Payment Providers',
22+
},
23+
{
24+
id: WalletAdminTabViews.taxforms,
25+
title: 'Tax Forms',
26+
},
2727
]
2828

2929
export function getHashFromTabId(tabId: string): string {
@@ -32,23 +32,23 @@ export function getHashFromTabId(tabId: string): string {
3232
return '#home'
3333
case WalletAdminTabViews.payments:
3434
return '#payments'
35-
// case WalletAdminTabViews.taxforms:
36-
// return '#tax-forms'
37-
// case WalletAdminTabViews.withdrawalmethods:
38-
// return '#withdrawal-methods'
35+
case WalletAdminTabViews.taxforms:
36+
return '#tax-forms'
37+
case WalletAdminTabViews.withdrawalmethods:
38+
return '#payment-providers'
3939
default:
4040
return '#home'
4141
}
4242
}
4343

4444
export function getTabIdFromHash(hash: string): string {
4545
switch (hash) {
46-
case '#winnings':
46+
case '#payments':
4747
return WalletAdminTabViews.payments
48-
// case '#tax-forms':
49-
// return WalletAdminTabViews.taxforms
50-
// case '#withdrawal-methods':
51-
// return WalletAdminTabViews.withdrawalmethods
48+
case '#tax-forms':
49+
return WalletAdminTabViews.taxforms
50+
case '#payment-providers':
51+
return WalletAdminTabViews.withdrawalmethods
5252
default:
5353
return WalletAdminTabViews.home
5454
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
@import '@libs/ui/styles/includes';
2+
3+
.container {
4+
background-color: $black-5;
5+
padding: $sp-6;
6+
margin: $sp-8 0;
7+
border-radius: 6px;
8+
9+
@include ltelg {
10+
padding: $sp-4;
11+
}
12+
13+
.header {
14+
display: flex;
15+
justify-content: flex-start;
16+
gap: 5px;
17+
align-items: center;
18+
19+
@include ltelg {
20+
flex-direction: column;
21+
}
22+
}
23+
24+
.content {
25+
background-color: $tc-white;
26+
border-radius: 4px;
27+
margin-top: $sp-4;
28+
.centered {
29+
height: 200px;
30+
display: flex;
31+
justify-content: space-around;
32+
align-items: center;
33+
}
34+
}
35+
}
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
/* eslint-disable max-len */
2+
/* eslint-disable react/jsx-no-bind */
3+
import { toast } from 'react-toastify'
4+
import React, { FC, useCallback, useEffect } from 'react'
5+
6+
import { Collapsible, ConfirmModal, LoadingCircles } from '~/libs/ui'
7+
import { UserProfile } from '~/libs/core'
8+
9+
import { PaymentProvider } from '../../../lib/models/PaymentProvider'
10+
import { deletePaymentProvider, getMemberHandle, getPaymentMethods } from '../../../lib/services/wallet'
11+
import { FilterBar, PaymentMethodTable } from '../../../lib'
12+
import { PaginationInfo } from '../../../lib/models/PaginationInfo'
13+
14+
import styles from './PaymentMethodsTab.module.scss'
15+
16+
interface ListViewProps {
17+
// eslint-disable-next-line react/no-unused-prop-types
18+
profile: UserProfile
19+
}
20+
21+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
22+
const ListView: FC<ListViewProps> = (props: ListViewProps) => {
23+
const [confirmFlow, setConfirmFlow] = React.useState<{
24+
provider: PaymentProvider
25+
} | undefined>(undefined)
26+
const [isLoading, setIsLoading] = React.useState<boolean>(false)
27+
const [filters, setFilters] = React.useState<Record<string, string[]>>({})
28+
const [paymentMethods, setPaymentMethods] = React.useState<PaymentProvider[]>([])
29+
const [userIds, setUserIds] = React.useState<string[]>([])
30+
const [pagination, setPagination] = React.useState<PaginationInfo>({
31+
currentPage: 1,
32+
pageSize: 10,
33+
totalItems: 0,
34+
totalPages: 0,
35+
})
36+
37+
const fetchPaymentProviders = useCallback(async () => {
38+
if (isLoading) {
39+
return
40+
}
41+
42+
setIsLoading(true)
43+
try {
44+
45+
const paymentMethodsResponse = await getPaymentMethods(pagination.pageSize, (pagination.currentPage - 1) * pagination.pageSize, userIds)
46+
const tmpUserIds = paymentMethodsResponse.paymentMethods.map(provider => provider.userId)
47+
const handleMap = await getMemberHandle(tmpUserIds)
48+
49+
const userPaymentMethods = paymentMethodsResponse.paymentMethods.map((provider: PaymentProvider) => ({ ...provider, handle: handleMap.get(parseInt(provider.userId, 10)) ?? provider.userId }))
50+
51+
setPaymentMethods(userPaymentMethods)
52+
setPagination(paymentMethodsResponse.pagination)
53+
} catch (apiError) {
54+
console.error('Failed to fetch winnings:', apiError)
55+
} finally {
56+
setIsLoading(false)
57+
}
58+
// eslint-disable-next-line react-hooks/exhaustive-deps
59+
}, [pagination.pageSize, pagination.currentPage, userIds])
60+
61+
useEffect(() => {
62+
fetchPaymentProviders()
63+
}, [fetchPaymentProviders])
64+
65+
return (
66+
<>
67+
<div className={styles.container}>
68+
<div className={styles.header}>
69+
<h3>Member Payment Providers</h3>
70+
</div>
71+
<div className={styles.content}>
72+
<Collapsible header={<h3>Member Payment Providers Listing</h3>}>
73+
<FilterBar
74+
filters={[
75+
{
76+
key: 'userIds',
77+
label: 'Username/Handle',
78+
type: 'member_autocomplete',
79+
},
80+
{
81+
key: 'pageSize',
82+
label: 'Members per page',
83+
options: [
84+
{
85+
label: '10',
86+
value: '10',
87+
},
88+
{
89+
label: '50',
90+
value: '50',
91+
},
92+
{
93+
label: '100',
94+
value: '100',
95+
},
96+
],
97+
type: 'dropdown',
98+
},
99+
]}
100+
onFilterChange={(key: string, value: string[]) => {
101+
const newPagination = {
102+
...pagination,
103+
currentPage: 1,
104+
}
105+
if (key === 'pageSize') {
106+
newPagination.pageSize = parseInt(value[0], 10)
107+
}
108+
109+
if (key === 'userIds') {
110+
setUserIds(value)
111+
}
112+
113+
setPagination(newPagination)
114+
setFilters({
115+
...filters,
116+
[key]: value,
117+
})
118+
}}
119+
onResetFilters={() => {
120+
setPagination({
121+
...pagination,
122+
currentPage: 1,
123+
pageSize: 10,
124+
})
125+
setFilters({})
126+
}}
127+
/>
128+
{isLoading && <LoadingCircles className={styles.centered} />}
129+
{!isLoading && paymentMethods.length > 0 && (
130+
<PaymentMethodTable
131+
paymentMethods={paymentMethods}
132+
numPages={pagination.totalPages}
133+
currentPage={pagination.currentPage}
134+
onPreviousPageClick={() => {
135+
setPagination({
136+
...pagination,
137+
currentPage: pagination.currentPage - 1,
138+
})
139+
}}
140+
onNextPageClick={() => {
141+
setPagination({
142+
...pagination,
143+
currentPage: pagination.currentPage + 1,
144+
})
145+
}}
146+
onPageClick={(pageNumber: number) => {
147+
setPagination({
148+
...pagination,
149+
currentPage: pageNumber,
150+
})
151+
}}
152+
onDeleteClick={async (provider: PaymentProvider) => {
153+
setConfirmFlow({ provider })
154+
}}
155+
/>
156+
)}
157+
{!isLoading && paymentMethods.length === 0 && (
158+
<div className={styles.centered}>
159+
<p className='body-main'>
160+
{Object.keys(filters).length === 0
161+
? 'Member payment-providers will appear here.'
162+
: 'No payment-provider found for the selected member(s).'}
163+
</p>
164+
</div>
165+
)}
166+
</Collapsible>
167+
</div>
168+
</div>
169+
{confirmFlow && (
170+
<ConfirmModal
171+
title='Delete Confirmation'
172+
action='delete'
173+
onClose={() => {
174+
setConfirmFlow(undefined)
175+
}}
176+
onConfirm={async () => {
177+
const userId = confirmFlow.provider.userId
178+
const providerId = confirmFlow.provider.id!
179+
setConfirmFlow(undefined)
180+
181+
toast.success('Deleting payment provider. Please wait...', { position: 'bottom-right' })
182+
try {
183+
await deletePaymentProvider(userId, providerId)
184+
toast.success('Successfully deleted payment provider.', { position: 'bottom-right' })
185+
} catch (err) {
186+
toast.error('Failed to delete users payment provider. Please try again later', { position: 'bottom-right' })
187+
}
188+
189+
fetchPaymentProviders()
190+
}}
191+
open={confirmFlow !== undefined}
192+
>
193+
<div>
194+
<p>
195+
Are you sure you want to reset the payment provider of the member
196+
{' '}
197+
{confirmFlow.provider.handle}
198+
?
199+
</p>
200+
<br />
201+
<p>This action cannot be undone.</p>
202+
</div>
203+
</ConfirmModal>
204+
)}
205+
</>
206+
)
207+
}
208+
209+
export default ListView
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as PaymentMethodsTab } from './PaymentMethodsTab'

0 commit comments

Comments
 (0)