Skip to content
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

[FEQ] P2PV2 - nada/PM integration in sell form #56

Merged
merged 5 commits into from
May 9, 2024
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
13 changes: 2 additions & 11 deletions src/components/AdvertsTableRow/AdvertsTableRow.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Fragment, memo, useEffect, useRef } from 'react';
import clsx from 'clsx';
import { useHistory } from 'react-router-dom';
import { TAdvertiserPaymentMethod, TAdvertsTableRowRenderer, TCurrency, TExchangeRate, TPaymentMethod } from 'types';
import { TAdvertsTableRowRenderer, TCurrency, TExchangeRate, TPaymentMethod } from 'types';
import { Badge, BuySellForm, PaymentMethodLabel, StarRating, UserAvatar } from '@/components';
import { ADVERTISER_URL, BUY_SELL } from '@/constants';
import { api } from '@/hooks';
import { useIsAdvertiser, useModalManager } from '@/hooks/custom-hooks';
import { useModalManager } from '@/hooks/custom-hooks';
import { generateEffectiveRate, getCurrentRoute } from '@/utils';
import { LabelPairedChevronRightMdRegularIcon } from '@deriv/quill-icons';
import { useExchangeRates } from '@deriv-com/api-hooks';
Expand All @@ -21,17 +21,9 @@
const history = useHistory();
const isBuySellPage = getCurrentRoute() === 'buy-sell';

const isAdvertiser = useIsAdvertiser();
const { data: paymentMethods } = api.paymentMethods.useGet();
const { data: advertiserPaymentMethods, get } = api.advertiserPaymentMethods.useGet();
const { data } = api.advertiser.useGetInfo() || {};

useEffect(() => {
if (isAdvertiser) {
get();
}
}, [isAdvertiser]);

const { daily_buy = 0, daily_buy_limit = 0, daily_sell = 0, daily_sell_limit = 0 } = data || {};

const exchangeRateRef = useRef<TExchangeRate | null>(null);
Expand All @@ -57,7 +49,7 @@
target_currencies: [local_currency],
});
}
}, [local_currency]);

Check warning on line 52 in src/components/AdvertsTableRow/AdvertsTableRow.tsx

View workflow job for this annotation

GitHub Actions / build_to_cloudflare_pages

React Hook useEffect has a missing dependency: 'subscribeRates'. Either include it or remove the dependency array

const Container = isMobile ? 'div' : Fragment;

Expand Down Expand Up @@ -192,7 +184,6 @@
<BuySellForm
advert={props}
advertiserBuyLimit={Number(daily_buy_limit) - Number(daily_buy)}
advertiserPaymentMethods={advertiserPaymentMethods as TAdvertiserPaymentMethod[]}
advertiserSellLimit={Number(daily_sell_limit) - Number(daily_sell)}
balanceAvailable={data?.balance_available ?? 0}
displayEffectiveRate={displayEffectiveRate}
Expand Down
12 changes: 12 additions & 0 deletions src/components/BuySellForm/BuySellForm.scss
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,17 @@
& .mobile-wrapper__body {
overflow: auto;
}

& .payment-method-form {
background: #fff;
z-index: 1;
inset: 0;

&__form {
& .payment-methods-form-footer {
bottom: 0;
}
}
}
}
}
24 changes: 18 additions & 6 deletions src/components/BuySellForm/BuySellForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import { useEffect, useState } from 'react';
import { Control, FieldValues, useForm } from 'react-hook-form';
import { useHistory } from 'react-router-dom';
import { TCurrency, THooks, TPaymentMethod } from 'types';
import { TAdvertiserPaymentMethod, TCurrency, THooks, TPaymentMethod } from 'types';
import { BUY_SELL, ORDERS_URL, RATE_TYPE } from '@/constants';
import { api } from '@/hooks';
import { api, useIsAdvertiser } from '@/hooks';
import { getPaymentMethodObjects, removeTrailingZeros, roundOffDecimal, setDecimalPlaces } from '@/utils';
import { InlineMessage, Text, useDevice } from '@deriv-com/ui';
import { LightDivider } from '../LightDivider';
Expand All @@ -21,7 +21,6 @@
type TBuySellFormProps = {
advert: THooks.Advert.GetList[number];
advertiserBuyLimit: number;
advertiserPaymentMethods: THooks.AdvertiserPaymentMethods.Get;
advertiserSellLimit: number;
balanceAvailable: number;
displayEffectiveRate: string;
Expand All @@ -46,7 +45,6 @@
const BuySellForm = ({
advert,
advertiserBuyLimit,
advertiserPaymentMethods,
advertiserSellLimit,
balanceAvailable,
displayEffectiveRate,
Expand All @@ -56,7 +54,15 @@
paymentMethods,
}: TBuySellFormProps) => {
const { data: orderCreatedInfo, isSuccess, mutate } = api.order.useCreate();
const isAdvertiser = useIsAdvertiser();
const [selectedPaymentMethods, setSelectedPaymentMethods] = useState<number[]>([]);
const { data: advertiserPaymentMethods, get } = api.advertiserPaymentMethods.useGet();

useEffect(() => {
if (isAdvertiser) {
get();
}
}, [isAdvertiser]);

Check warning on line 65 in src/components/BuySellForm/BuySellForm.tsx

View workflow job for this annotation

GitHub Actions / build_to_cloudflare_pages

React Hook useEffect has a missing dependency: 'get'. Either include it or remove the dependency array

const {
account_currency,
Expand All @@ -73,7 +79,9 @@
type,
} = advert;

const advertiserPaymentMethodObjects = getPaymentMethodObjects(advertiserPaymentMethods);
const advertiserPaymentMethodObjects = getPaymentMethodObjects(
advertiserPaymentMethods as TAdvertiserPaymentMethod[]
);

const paymentMethodObjects = getPaymentMethodObjects(paymentMethods);

Expand Down Expand Up @@ -128,6 +136,10 @@
payload.payment_info = getValues('bank_details');
}

if (isBuy) {
payload.contact_info = getValues('contact_details');
}

mutate(payload);
};

Expand Down Expand Up @@ -155,7 +167,7 @@
accountCurrency={account_currency as TCurrency}
isBuy={isBuy}
isModalOpen={isModalOpen}
isValid={isValid}
isValid={isValid && ((isBuy && selectedPaymentMethods.length > 0) || !isBuy)}
onRequestClose={onRequestClose}
onSubmit={onSubmit}
>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { TPaymentMethod } from 'types';
import { LightDivider } from '@/components';
import { useCallback, useReducer } from 'react';
import { TPaymentMethod, TSelectedPaymentMethod } from 'types';
import { LightDivider, PaymentMethodForm } from '@/components';
import { useModalManager } from '@/hooks';
import { advertiserPaymentMethodsReducer } from '@/reducers';
import { sortPaymentMethodsWithAvailability } from '@/utils';
import { Text, useDevice } from '@deriv-com/ui';
import { PaymentMethodCard } from '../../PaymentMethodCard';
Expand All @@ -17,34 +20,26 @@ const BuySellPaymentSection = ({
}: TBuySellPaymentSectionProps) => {
const { isMobile } = useDevice();
const sortedList = sortPaymentMethodsWithAvailability(availablePaymentMethods);
//TODO: below section to be modified to handle payment method addition after handling of modal provider
// const [formState, dispatch] = useReducer(advertiserPaymentMethodsReducer, {});

// const handleAddPaymentMethod = (selectedPaymentMethod?: TSelectedPaymentMethod) => {
// dispatch({
// payload: {
// selectedPaymentMethod,
// },
// type: 'ADD',
// });
// };
const [formState, dispatch] = useReducer(advertiserPaymentMethodsReducer, {});
const { hideModal, isModalOpenFor, showModal } = useModalManager();

// const handleResetFormState = useCallback(() => {
// dispatch({ type: 'RESET' });
// }, []);
const handleAddPaymentMethod = (displayName: string, selectedPaymentMethod?: TSelectedPaymentMethod) => {
dispatch({
payload: {
selectedPaymentMethod: {
...selectedPaymentMethod,
displayName,
method: selectedPaymentMethod?.method ?? selectedPaymentMethod?.id,
},
},
type: 'ADD',
});
};

// if (formState?.isVisible) {
// return (
// <PaymentMethodForm
// displayFullPage={isMobile}
// displayModal={!isMobile}
// formState={formState}
// isDisabled
// onAdd={handleAddPaymentMethod}
// onResetFormState={handleResetFormState}
// />
// );
// }
const handleResetFormState = useCallback(() => {
dispatch({ type: 'RESET' });
}, []);

return (
<>
Expand All @@ -62,7 +57,10 @@ const BuySellPaymentSection = ({
<PaymentMethodCard
key={paymentMethod?.id}
medium
onClickAdd={() => undefined}
onClickAdd={() => {
showModal('PaymentMethodForm', { shouldStackModals: false });
handleAddPaymentMethod(paymentMethod?.display_name, paymentMethod);
}}
onSelectPaymentMethodCard={onSelectPaymentMethodCard}
paymentMethod={paymentMethod}
selectedPaymentMethodIds={selectedPaymentMethodIds}
Expand All @@ -71,6 +69,14 @@ const BuySellPaymentSection = ({
</div>
</div>
<LightDivider />
{isModalOpenFor('PaymentMethodForm') && (
<PaymentMethodForm
displayModal={!isMobile && !!isModalOpenFor('PaymentMethodForm')}
formState={formState}
onRequestClose={hideModal}
onResetFormState={handleResetFormState}
/>
)}
</>
);
};
Expand Down
65 changes: 38 additions & 27 deletions src/components/BuySellForm/__tests__/BuySellForm.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,52 @@ import userEvent from '@testing-library/user-event';
import BuySellForm from '../BuySellForm';

const mockMutateFn = jest.fn();
const mockModalManager = {
hideModal: jest.fn(),
isModalOpenFor: jest.fn().mockReturnValue(false),
showModal: jest.fn(),
};

jest.mock('@/hooks', () => ({
api: {
advertiserPaymentMethods: {
useGet: jest.fn(() => ({
data: [
{
display_name: 'alipay',
fields: {
account: {
display_name: 'Alipay ID',
required: 1,
type: 'text' as 'memo' | 'text',
value: '12345',
},
instructions: {
display_name: 'Instructions',
required: 0,
type: 'memo' as 'memo' | 'text',
value: 'Alipay instructions',
},
},
id: '1',
is_enabled: 1 as 0 | 1,
method: 'alipay',
type: 'ewallet' as 'bank' | 'ewallet' | 'other',
used_by_adverts: ['1'],
used_by_orders: ['1'],
},
],
get: jest.fn(),
})),
},
order: {
useCreate: jest.fn(() => ({
mutate: mockMutateFn,
})),
},
},
useIsAdvertiser: jest.fn(() => true),
useModalManager: jest.fn(() => mockModalManager),
}));

jest.mock('@deriv-com/ui', () => ({
Expand Down Expand Up @@ -57,36 +95,9 @@ jest.mock('@/utils', () => ({
}));
const mockFloatingPointValidator = floatingPointValidator as jest.Mock;

type TNumber = 0 | 1;

const mockProps = {
advert: mockAdvertValues,
advertiserBuyLimit: 1000,
advertiserPaymentMethods: [
{
display_name: 'alipay',
fields: {
account: {
display_name: 'Alipay ID',
required: 1,
type: 'text' as 'memo' | 'text',
value: '12345',
},
instructions: {
display_name: 'Instructions',
required: 0,
type: 'memo' as 'memo' | 'text',
value: 'Alipay instructions',
},
},
id: '1',
is_enabled: 1 as TNumber,
method: 'alipay',
type: 'ewallet' as 'bank' | 'ewallet' | 'other',
used_by_adverts: ['1'],
used_by_orders: ['1'],
},
],
advertiserSellLimit: 1000,
balanceAvailable: 10,
displayEffectiveRate: '1',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { TAccount, TBankName, THooks, TName } from 'types';
import { useDevice } from '@/hooks';
import { Text } from '@deriv-com/ui';
import './PaymentMethodCardBody.scss';

Expand All @@ -14,13 +15,15 @@ const PaymentMethodCardBody = ({
const displayName = paymentMethod?.display_name;
const modifiedDisplayName = displayName?.replace(/\s|-/gm, '');
const isBankOrOther = modifiedDisplayName && ['BankTransfer', 'Other'].includes(modifiedDisplayName);
const { isMobile } = useDevice();
const textSize = isMobile ? 'md' : 'sm';
return (
<div className='payment-method-card__body'>
{isBankOrOther && !shouldShowPaymentMethodDisplayName ? null : <Text>{displayName}</Text>}
<Text>
{isBankOrOther && !shouldShowPaymentMethodDisplayName ? null : <Text size={textSize}>{displayName}</Text>}
<Text size={textSize}>
{(paymentMethod.fields?.bank_name as TBankName)?.value ?? (paymentMethod.fields?.name as TName)?.value}
</Text>
<Text>{(paymentMethod.fields?.account as TAccount)?.value}</Text>
<Text size={textSize}>{(paymentMethod.fields?.account as TAccount)?.value}</Text>
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { render, screen } from '@testing-library/react';
import { PaymentMethodCardBody } from '../PaymentMethodCardBody';

jest.mock('@deriv-com/ui', () => ({
...jest.requireActual('@deriv-com/ui'),
useDevice: jest.fn(() => {
false;
}),
}));

describe('PaymentMethodCardBody', () => {
it('should render the component correctly', () => {
render(
Expand Down
Loading
Loading