-
Notifications
You must be signed in to change notification settings - Fork 10
Pm 959 tc finance integration #1075
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,10 +4,11 @@ import { FC, useEffect, useState } from 'react' | |
import { UserProfile } from '~/libs/core' | ||
import { IconOutline, LinkButton, LoadingCircles } from '~/libs/ui' | ||
|
||
import { Balance, WalletDetails } from '../../../lib/models/WalletDetails' | ||
import { getWalletDetails } from '../../../lib/services/wallet' | ||
import { Balance } from '../../../lib/models/WalletDetails' | ||
import { InfoRow } from '../../../lib' | ||
import { BannerImage, BannerText } from '../../../lib/assets/home' | ||
import { nullToZero } from '../../../lib/util' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider checking if |
||
import { useWalletDetails, WalletDetailsResponse } from '../../../lib/hooks/use-wallet-details' | ||
import Chip from '../../../lib/components/chip/Chip' | ||
|
||
import styles from './Home.module.scss' | ||
|
@@ -17,27 +18,8 @@ interface HomeTabProps { | |
} | ||
|
||
const HomeTab: FC<HomeTabProps> = () => { | ||
const [walletDetails, setWalletDetails] = useState<WalletDetails | undefined>(undefined) | ||
const [isLoading, setIsLoading] = useState(false) | ||
const { data: walletDetails, isLoading, error }: WalletDetailsResponse = useWalletDetails() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider handling the |
||
const [balanceSum, setBalanceSum] = useState(0) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
const [error, setError] = useState<string | undefined>(undefined) | ||
|
||
useEffect(() => { | ||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type | ||
const fetchWalletDetails = async () => { | ||
setIsLoading(true) | ||
try { | ||
const details = await getWalletDetails() | ||
setWalletDetails(details) | ||
} catch (apiError) { | ||
setError('Error fetching wallet details') | ||
} | ||
|
||
setIsLoading(false) | ||
} | ||
|
||
fetchWalletDetails() | ||
}, []) | ||
|
||
useEffect(() => { | ||
if (walletDetails) { | ||
|
@@ -58,7 +40,7 @@ const HomeTab: FC<HomeTabProps> = () => { | |
<BannerImage /> | ||
</div> | ||
{isLoading && <LoadingCircles />} | ||
{!isLoading && ( | ||
{!isLoading && walletDetails && ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider adding a null check for |
||
<div className={styles['info-row-container']}> | ||
<InfoRow | ||
title='Account Balance' | ||
|
@@ -75,6 +57,24 @@ const HomeTab: FC<HomeTabProps> = () => { | |
} | ||
/> | ||
|
||
{walletDetails.withdrawalMethod.isSetupComplete && walletDetails.taxForm.isSetupComplete && ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider adding a check for |
||
<InfoRow | ||
title='Est. Payment Fees and Tax Withholding %' | ||
// eslint-disable-next-line max-len | ||
value={`Fee: ${nullToZero(walletDetails.estimatedFees)} USD / Tax Withholding: ${nullToZero(walletDetails.taxWithholdingPercentage)}%`} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment |
||
action={ | ||
<LinkButton | ||
label='ADJUST YOUR PAYOUT SETTINGS' | ||
iconToRight | ||
icon={IconOutline.ArrowRightIcon} | ||
size='md' | ||
link | ||
to='#payout' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
/> | ||
} | ||
/> | ||
)} | ||
|
||
{!walletDetails?.withdrawalMethod.isSetupComplete && ( | ||
<InfoRow | ||
title='Withdrawal Method' | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,5 +31,20 @@ | |
justify-content: space-around; | ||
align-items: center; | ||
} | ||
|
||
} | ||
} | ||
|
||
.taxes { | ||
display: block; | ||
line-height: 20px; | ||
font-size: 14px; | ||
|
||
+ .taxes { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider using a more descriptive class name instead of |
||
margin-top: 10px; | ||
} | ||
|
||
&.mt { | ||
margin-top: 20px; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
/* eslint-disable react/jsx-no-bind */ | ||
import { toast } from 'react-toastify' | ||
import { AxiosError } from 'axios' | ||
import { Link } from 'react-router-dom' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
import React, { FC, useCallback, useEffect } from 'react' | ||
|
||
import { Collapsible, ConfirmModal, LoadingCircles } from '~/libs/ui' | ||
|
@@ -12,6 +13,8 @@ import { Winning, WinningDetail } from '../../../lib/models/WinningDetail' | |
import { FilterBar } from '../../../lib' | ||
import { ConfirmFlowData } from '../../../lib/models/ConfirmFlowData' | ||
import { PaginationInfo } from '../../../lib/models/PaginationInfo' | ||
import { useWalletDetails, WalletDetailsResponse } from '../../../lib/hooks/use-wallet-details' | ||
import { nullToZero } from '../../../lib/util' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The function |
||
import PaymentsTable from '../../../lib/components/payments-table/PaymentTable' | ||
|
||
import styles from './Winnings.module.scss' | ||
|
@@ -74,6 +77,8 @@ const ListView: FC<ListViewProps> = (props: ListViewProps) => { | |
const [selectedPayments, setSelectedPayments] = React.useState<{ [paymentId: string]: Winning }>({}) | ||
const [isLoading, setIsLoading] = React.useState<boolean>(false) | ||
const [filters, setFilters] = React.useState<Record<string, string[]>>({}) | ||
const { data: walletDetails }: WalletDetailsResponse = useWalletDetails() | ||
|
||
const [pagination, setPagination] = React.useState<PaginationInfo>({ | ||
currentPage: 1, | ||
pageSize: 10, | ||
|
@@ -180,6 +185,58 @@ const ListView: FC<ListViewProps> = (props: ListViewProps) => { | |
fetchWinnings() | ||
} | ||
|
||
function handlePayMeClick( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider renaming |
||
paymentIds: { [paymentId: string]: Winning }, | ||
totalAmount: string, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
): void { | ||
setConfirmFlow({ | ||
action: 'Yes', | ||
callback: () => processPayouts(Object.keys(paymentIds)), | ||
content: ( | ||
<> | ||
You are about to process payments for a total of USD | ||
{' '} | ||
{totalAmount} | ||
. | ||
<br /> | ||
<br /> | ||
{walletDetails && ( | ||
<> | ||
<div className={styles.taxes}> | ||
Est. Payment Fees: | ||
{' '} | ||
{nullToZero(walletDetails.estimatedFees)} | ||
{' '} | ||
USD and Tax Withholding: | ||
{' '} | ||
{`${nullToZero(walletDetails.taxWithholdingPercentage)}%`} | ||
{' '} | ||
will be applied on the payment. | ||
</div> | ||
<div className={styles.taxes}> | ||
{walletDetails.primaryCurrency && ( | ||
<> | ||
You will receive the payment in | ||
{' '} | ||
{walletDetails.primaryCurrency} | ||
{' '} | ||
currency after 2% coversion fees applied. | ||
</> | ||
)} | ||
</div> | ||
<div className={`${styles.taxes} ${styles.mt}`}> | ||
You can adjust your payout settings to customize your estimated payment fee and tax withholding percentage in | ||
{' '} | ||
<Link to='#payout'>Payout</Link> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
</div> | ||
</> | ||
)} | ||
</> | ||
), | ||
title: 'Are you sure?', | ||
}) | ||
} | ||
|
||
return ( | ||
<> | ||
<div className={styles.container}> | ||
|
@@ -338,17 +395,7 @@ const ListView: FC<ListViewProps> = (props: ListViewProps) => { | |
currentPage: pageNumber, | ||
}) | ||
}} | ||
onPayMeClick={async function onPayMeClicked( | ||
paymentIds: { [paymentId: string]: Winning }, | ||
totalAmount: string, | ||
) { | ||
setConfirmFlow({ | ||
action: 'Yes', | ||
callback: () => processPayouts(Object.keys(paymentIds)), | ||
content: `You are about to process payments for a total of USD ${totalAmount}`, | ||
title: 'Are you sure?', | ||
}) | ||
}} | ||
onPayMeClick={handlePayMeClick} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The function |
||
/> | ||
)} | ||
{!isLoading && winnings.length === 0 && ( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,7 +23,7 @@ | |
align-items: center; | ||
flex-grow: 1; | ||
padding-left: 10px; | ||
gap: 200px; | ||
gap: 50px; | ||
} | ||
|
||
.value { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import useSWR, { KeyedMutator, SWRResponse } from 'swr' | ||
|
||
import { WalletDetails } from '../models/WalletDetails' | ||
import { getWalletDetails } from '../services/wallet' | ||
|
||
export interface Response<T> { | ||
data?: Readonly<T> | ||
error?: Readonly<string> | ||
mutate: KeyedMutator<any> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider specifying a more precise type for |
||
isLoading?: Readonly<boolean> | ||
} | ||
|
||
export type WalletDetailsResponse = Response<WalletDetails> | ||
|
||
export function useWalletDetails(): WalletDetailsResponse { | ||
const { data, error, mutate, isValidating }: SWRResponse = useSWR('wallet-details', getWalletDetails) | ||
|
||
return { | ||
data, | ||
error, | ||
isLoading: isValidating && !data && !error, | ||
mutate, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,4 +17,7 @@ export interface WalletDetails { | |
taxForm: { | ||
isSetupComplete: boolean | ||
} | ||
primaryCurrency?: string | null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider using a more specific type for |
||
estimatedFees?: string | null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
taxWithholdingPercentage?: string | null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,10 +11,10 @@ import { TransactionResponse } from '../models/TransactionId' | |
import { PaginationInfo } from '../models/PaginationInfo' | ||
import ApiResponse from '../models/ApiResponse' | ||
|
||
const baseUrl = `${EnvironmentConfig.TC_FINANCE_API}` | ||
export const WALLET_API_BASE_URL = `${EnvironmentConfig.TC_FINANCE_API}` | ||
|
||
export async function getWalletDetails(): Promise<WalletDetails> { | ||
const response = await xhrGetAsync<ApiResponse<WalletDetails>>(`${baseUrl}/wallet`) | ||
const response = await xhrGetAsync<ApiResponse<WalletDetails>>(`${WALLET_API_BASE_URL}/wallet`) | ||
|
||
if (response.status === 'error') { | ||
throw new Error('Error fetching wallet details') | ||
|
@@ -43,7 +43,7 @@ export async function getPayments(userId: string, limit: number, offset: number, | |
...filteredFilters, | ||
}) | ||
|
||
const url = `${baseUrl}/user/winnings` | ||
const url = `${WALLET_API_BASE_URL}/user/winnings` | ||
const response = await xhrPostAsync<string, ApiResponse<{ | ||
winnings: WinningDetail[], | ||
pagination: PaginationInfo | ||
|
@@ -64,7 +64,7 @@ export async function processWinningsPayments(winningsIds: string[]): Promise<{ | |
const body = JSON.stringify({ | ||
winningsIds, | ||
}) | ||
const url = `${baseUrl}/withdraw` | ||
const url = `${WALLET_API_BASE_URL}/withdraw` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider verifying that |
||
const response = await xhrPostAsync<string, ApiResponse<{ processed: boolean }>>(url, body) | ||
|
||
if (response.status === 'error') { | ||
|
@@ -81,7 +81,7 @@ export async function verifyOtp(transactionId: string, code: string, blob: boole | |
transactionId, | ||
}) | ||
|
||
const url = `${baseUrl}/otp/verify` | ||
const url = `${WALLET_API_BASE_URL}/otp/verify` | ||
try { | ||
// eslint-disable-next-line max-len | ||
const response = await xhrPostAsyncWithBlobHandling<string, ApiResponse<OtpVerificationResponse> | Blob>(url, body, { | ||
|
@@ -107,7 +107,7 @@ export async function resendOtp(transactionId: string): Promise<TransactionRespo | |
transactionId, | ||
}) | ||
|
||
const url = `${baseUrl}/otp/resend` | ||
const url = `${WALLET_API_BASE_URL}/otp/resend` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The change from |
||
try { | ||
const response = await xhrPostAsync<string, ApiResponse<TransactionResponse>>(url, body) | ||
|
||
|
@@ -132,7 +132,7 @@ export async function resendOtp(transactionId: string): Promise<TransactionRespo | |
* @throws {Error} If the response does not contain a valid link. | ||
*/ | ||
export async function getTrolleyPortalLink(): Promise<string> { | ||
const url = `${baseUrl}/trolley/portal-link` | ||
const url = `${WALLET_API_BASE_URL}/trolley/portal-link` | ||
const response = await xhrGetAsync<{ link: string }>(url) | ||
|
||
if (!response.link) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './null-to-zero' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/** | ||
* Converts a given value to the string `'0'` if it is `null`, `undefined`, or the string `'null'`. | ||
* | ||
* @param value - The input value which can be a string, `null`, or `undefined`. | ||
* @returns The original value if it is a valid string (and not `'null'`), otherwise returns `'0'`. | ||
*/ | ||
export const nullToZero = (value: string | null | undefined): string => (value === 'null' ? '0' : value ?? '0') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider using strict equality checks for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The import statement for
WalletDetails
has been removed, but it is unclear if this is intentional or ifWalletDetails
is still needed elsewhere in the code. Please verify ifWalletDetails
is used in other parts of the file or project.