Skip to content

Commit 56d2a72

Browse files
committed
feat(wallet-admin): see payout audit details from external provider
Signed-off-by: Rakib Ansary <rakibansary@topcoder.com>
1 parent a2bccbc commit 56d2a72

File tree

7 files changed

+127
-7
lines changed

7 files changed

+127
-7
lines changed

src/apps/wallet-admin/src/home/tabs/payments/PaymentsTab.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,8 @@ const ListView: FC<ListViewProps> = (props: ListViewProps) => {
489489
</div>
490490
{confirmFlow && (
491491
<ConfirmModal
492+
maxWidth='800px'
493+
size='lg'
492494
showButtons={confirmFlow.showButtons}
493495
title={confirmFlow.title}
494496
action={confirmFlow.action}

src/apps/wallet-admin/src/lib/components/payment-view/PaymentView.module.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
.infoItem {
1414
display: flex;
1515
flex-direction: column;
16+
gap: 2px;
1617
}
1718

1819
.label {

src/apps/wallet-admin/src/lib/components/payment-view/PaymentView.tsx

Lines changed: 91 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable react/no-array-index-key */
12
/* eslint-disable unicorn/no-null */
23
/* eslint-disable max-len */
34
/* eslint-disable react/jsx-no-bind */
@@ -8,7 +9,8 @@ import { TOPCODER_URL } from '~/config/environments/default.env'
89

910
import { WinningsAudit } from '../../models/WinningsAudit'
1011
import { Winning } from '../../models/WinningDetail'
11-
import { fetchAuditLogs, getMemberHandle } from '../../services/wallet'
12+
import { PayoutAudit } from '../../models/PayoutAudit'
13+
import { fetchAuditLogs, fetchPayoutAuditLogs, getMemberHandle } from '../../services/wallet'
1214

1315
import styles from './PaymentView.module.scss'
1416

@@ -17,11 +19,12 @@ interface PaymentViewProps {
1719
}
1820

1921
const PaymentView: React.FC<PaymentViewProps> = (props: PaymentViewProps) => {
20-
const [view, setView] = React.useState<'details' | 'audit'>('details')
22+
const [view, setView] = React.useState<'details' | 'audit' | 'external_transaction'>('details')
2123
const [auditLines, setAuditLines] = React.useState<WinningsAudit[]>([])
24+
const [externalTransactionAudit, setExternalTransactionAudit] = React.useState<PayoutAudit[]>([])
2225

23-
const handleToggleView = (): void => {
24-
setView(view === 'details' ? 'audit' : 'details')
26+
const handleToggleView = (newView: 'audit' | 'details' | 'external_transaction'): void => {
27+
setView(newView)
2528
}
2629

2730
React.useEffect(() => {
@@ -45,6 +48,11 @@ const PaymentView: React.FC<PaymentViewProps> = (props: PaymentViewProps) => {
4548
.catch(() => {
4649
setAuditLines([])
4750
})
51+
} else if (view === 'external_transaction') {
52+
fetchPayoutAuditLogs(props.payment.id)
53+
.then(payoutAudit => {
54+
setExternalTransactionAudit(payoutAudit)
55+
})
4856
}
4957
}, [props.payment.id, view])
5058

@@ -125,9 +133,15 @@ const PaymentView: React.FC<PaymentViewProps> = (props: PaymentViewProps) => {
125133

126134
<div className={styles.infoItem}>
127135
<Button
128-
onClick={handleToggleView}
136+
onClick={() => handleToggleView('audit')}
129137
label='View Audit'
130138
/>
139+
{props.payment.status.toUpperCase() === 'PAID' && (
140+
<Button
141+
onClick={() => handleToggleView('external_transaction')}
142+
label='External Transaction Details'
143+
/>
144+
)}
131145
</div>
132146
</>
133147
)}
@@ -179,12 +193,83 @@ const PaymentView: React.FC<PaymentViewProps> = (props: PaymentViewProps) => {
179193
</div>
180194
<div className={styles.infoItem}>
181195
<Button
182-
onClick={handleToggleView}
196+
onClick={() => handleToggleView('details')}
197+
label='Back to Details'
198+
/>
199+
</div>
200+
</>
201+
)}
202+
203+
{view === 'external_transaction' && (
204+
<>
205+
<div className={styles.auditSection}>
206+
{externalTransactionAudit && externalTransactionAudit.length > 0 && externalTransactionAudit.map((externalTransaction: PayoutAudit, index: number) => (
207+
<>
208+
<Collapsible
209+
key={`internal-record${index}`}
210+
header={(
211+
<h3>Internal Record</h3>
212+
)}
213+
containerClass={styles.container}
214+
contentClass={styles.content}
215+
>
216+
<div className={styles.auditItem}>
217+
<div>
218+
<p>
219+
<strong>Provider Used:</strong>
220+
{' '}
221+
{externalTransaction.paymentMethodUsed}
222+
</p>
223+
<p>
224+
<strong>Status:</strong>
225+
{' '}
226+
{externalTransaction.status}
227+
</p>
228+
<p>
229+
<strong>Processed At:</strong>
230+
{' '}
231+
{externalTransaction.createdAt}
232+
</p>
233+
<p>
234+
<strong>Totl Amount Processed:</strong>
235+
{' '}
236+
{externalTransaction.totalNetAmount}
237+
</p>
238+
</div>
239+
</div>
240+
</Collapsible>
241+
<Collapsible
242+
key={`external-record${index}`}
243+
header={(
244+
<h3>External Record</h3>
245+
)}
246+
containerClass={styles.container}
247+
contentClass={styles.content}
248+
>
249+
<div className={styles.auditItem}>
250+
<div>
251+
<pre>{JSON.stringify(externalTransaction.externalTransactionDetails, undefined, 2)}</pre>
252+
</div>
253+
</div>
254+
</Collapsible>
255+
</>
256+
))}
257+
{(externalTransactionAudit === undefined)
258+
&& (
259+
<div className={styles.auditItem}>
260+
<p>No external transaction data is available</p>
261+
</div>
262+
)}
263+
</div>
264+
<div className={styles.infoItem}>
265+
<Button
266+
onClick={() => handleToggleView('details')}
183267
label='Back to Details'
184268
/>
185269
</div>
186270
</>
187271
)}
272+
188273
</div>
189274
</div>
190275
)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export interface PayoutAudit {
2+
externalTransactionId: string
3+
status: string
4+
totalNetAmount: number
5+
createdAt: string
6+
metadata: string
7+
paymentMethodUsed: string
8+
externalTransactionDetails: any
9+
}

src/apps/wallet-admin/src/lib/services/wallet.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { TaxForm } from '../models/TaxForm'
99
import { TransactionResponse } from '../models/TransactionId'
1010
import { PaginationInfo } from '../models/PaginationInfo'
1111
import { WinningsAudit } from '../models/WinningsAudit'
12+
import { PayoutAudit } from '../models/PayoutAudit'
1213
import ApiResponse from '../models/ApiResponse'
1314

1415
const baseUrl = `${EnvironmentConfig.API.V5}/payments`
@@ -54,6 +55,22 @@ export async function fetchAuditLogs(paymentId: string): Promise<WinningsAudit[]
5455

5556
}
5657

58+
export async function fetchPayoutAuditLogs(paymentId: string): Promise<PayoutAudit[]> {
59+
// eslint-disable-next-line max-len
60+
const response = await xhrGetAsync<ApiResponse<PayoutAudit[]>>(`${baseUrl}/admin/winnings/${paymentId}/audit-payout`)
61+
62+
if (response.status === 'error') {
63+
throw new Error('Error fetching audit logs')
64+
}
65+
66+
if (response.data.length === 0) {
67+
throw new Error('No payout audit logs found')
68+
}
69+
70+
return response.data
71+
72+
}
73+
5774
export async function editPayment(updates: {
5875
winningsId: string,
5976
paymentStatus?: 'ON_HOLD_ADMIN' | 'OWED' | 'CANCELLED',

src/libs/ui/lib/components/modals/base-modal/BaseModal.module.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,8 @@
8282
padding: 0;
8383
margin: 0;
8484
}
85+
86+
.modal-lg {
87+
max-width: 800px;
88+
}
8589
}

src/libs/ui/lib/components/modals/confirm/ConfirmModal.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ export interface ConfirmModalProps extends ModalProps {
1010
title: string
1111
canSave?: boolean
1212
showButtons?: boolean
13+
maxWidth?: string
14+
size?: 'sm' | 'md' | 'lg'
1315
}
1416

1517
const ConfirmModal: FC<ConfirmModalProps> = (props: ConfirmModalProps) => (
1618
<BaseModal
1719
{...props}
18-
styles={{ modal: { maxWidth: '450px' } }}
20+
styles={{ modal: { maxWidth: props.maxWidth ?? '450px' } }}
1921
buttons={(
2022
props.showButtons !== false && (
2123
<>

0 commit comments

Comments
 (0)