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

Nada/FEQ-2238/buy sell form and table changes #89

Closed
wants to merge 5 commits into from
Closed
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
3 changes: 1 addition & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ import { initializeI18n, TranslationProvider } from '@deriv-com/translations';
import { useDevice } from '@deriv-com/ui';
import AppContent from './routes/AppContent';

//TODO: replace with ${process.env.VITE_PROJECT_NAME}/${process.env.VITE_CROWDIN_BRANCH_NAME}
const i18nInstance = initializeI18n({
cdnUrl: `https://pub-5ce11fcb15f34c0a9ce8ba7086d16e6a.r2.dev/p2p/DP2P`,
cdnUrl: `https://pub-5ce11fcb15f34c0a9ce8ba7086d16e6a.r2.dev/${import.meta.env.VITE_PROJECT_NAME}/${import.meta.env.VITE_CROWDIN_BRANCH_NAME}`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we also replace https://pub-5ce11fcb15f34c0a9ce8ba7086d16e6a.r2.dev?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we better to use it from github env variables

});

const App = () => {
Expand Down
72 changes: 49 additions & 23 deletions src/components/AdvertsTableRow/AdvertsTableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import clsx from 'clsx';
import { useHistory, useLocation } from 'react-router-dom';
import { TAdvertsTableRowRenderer, TCurrency } from 'types';
import { Badge, BuySellForm, PaymentMethodLabel, StarRating, UserAvatar } from '@/components';
import { NicknameModal } from '@/components/Modals';
import { ErrorModal, NicknameModal } from '@/components/Modals';
import { ADVERTISER_URL, BUY_SELL } from '@/constants';
import { api } from '@/hooks';
import { useIsAdvertiser, useIsAdvertiserBarred, useModalManager, usePoiPoaStatus } from '@/hooks/custom-hooks';
import { generateEffectiveRate, getCurrentRoute } from '@/utils';
import { generateEffectiveRate, getCurrentRoute, getEligibilityErrorMessage } from '@/utils';
import { LabelPairedChevronRightMdRegularIcon } from '@deriv/quill-icons';
import { useExchangeRates } from '@deriv-com/api-hooks';
import { Localize } from '@deriv-com/translations';
import { Localize, useTranslations } from '@deriv-com/translations';
import { Button, Text, useDevice } from '@deriv-com/ui';
import './AdvertsTableRow.scss';

Expand All @@ -28,6 +28,7 @@ const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => {
const { data } = api.advertiser.useGetInfo() || {};
const { data: poiPoaData } = usePoiPoaStatus();
const { isPoaVerified, isPoiVerified } = poiPoaData || {};
const { localize } = useTranslations();

const exchangeRateRef = useRef<number | undefined>(undefined);

Expand All @@ -36,7 +37,9 @@ const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => {
advertiser_details,
counterparty_type,
effective_rate,
eligibility_status: eligibilityStatus = [],
id: advertId,
is_eligible: isEligible,
local_currency = '',
max_order_amount_limit_display,
min_order_amount_limit_display,
Expand Down Expand Up @@ -81,6 +84,8 @@ const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => {
const isMyAdvert = data?.id === id;
const ratingAverageDecimal = rating_average ? Number(rating_average).toFixed(1) : null;
const textColor = isMobile ? 'less-prominent' : 'general';
const size = isMobile ? 'md' : 'sm';
const buttonTextSize = isMobile ? 'md' : 'xs';

return (
<div
Expand Down Expand Up @@ -113,7 +118,7 @@ const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => {
'mb-[-0.5rem]': hasRating,
})}
>
<Text size={isMobile ? 'md' : 'sm'} weight={isMobile ? 'bold' : 400}>
<Text size={size} weight={isMobile ? 'bold' : 400}>
{name}
</Text>
<Badge tradeCount={completed_orders_count} />
Expand Down Expand Up @@ -154,7 +159,7 @@ const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => {
{isMobile && 'Limits:'} {min_order_amount_limit_display}-{max_order_amount_limit_display}{' '}
{account_currency}
</Text>
<Text className='text-wrap w-[90%]' color='success' size={isMobile ? 'md' : 'sm'} weight='bold'>
<Text className='text-wrap w-[90%]' color='success' size={size} weight='bold'>
{displayEffectiveRate} {local_currency}
</Text>
</Container>
Expand All @@ -177,30 +182,43 @@ const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => {
{!isMyAdvert && (
<div
className={clsx('flex relative', {
'flex-col h-full justify-center': isBuySellPage,
'flex-col h-full justify-center items-end': isBuySellPage,
'flex-row justify-end': !isBuySellPage,
})}
>
{isMobile && isBuySellPage && (
<LabelPairedChevronRightMdRegularIcon className='absolute top-0 right-0' />
)}
<Button
className='lg:w-[7.5rem]'
disabled={isAdvertiserBarred}
onClick={() => {
if (!isPoaVerified || !isPoiVerified) {
const searchParams = new URLSearchParams(location.search);
searchParams.set('poi_poa_verified', 'false');
history.replace({ pathname: location.pathname, search: searchParams.toString() });
} else {
showModal(isAdvertiser ? 'BuySellForm' : 'NicknameModal');
}
}}
size={isMobile ? 'md' : 'sm'}
textSize={isMobile ? 'md' : 'xs'}
>
{isBuyAdvert ? 'Buy' : 'Sell'} {account_currency}
</Button>
{isEligible === 0 ? (
<Button
className='border px-[1.6rem]'
color='black'
onClick={() => showModal('ErrorModal')}
size={size}
textSize={buttonTextSize}
variant='outlined'
>
<Localize i18n_default_text='Unavailable' />
</Button>
) : (
<Button
className='lg:w-[7.5rem]'
disabled={isAdvertiserBarred}
onClick={() => {
if (!isPoaVerified || !isPoiVerified) {
const searchParams = new URLSearchParams(location.search);
searchParams.set('poi_poa_verified', 'false');
history.replace({ pathname: location.pathname, search: searchParams.toString() });
} else {
showModal(isAdvertiser ? 'BuySellForm' : 'NicknameModal');
}
}}
size={size}
textSize={buttonTextSize}
>
{isBuyAdvert ? 'Buy' : 'Sell'} {account_currency}
</Button>
)}
</div>
)}
{isModalOpenFor('BuySellForm') && (
Expand All @@ -211,6 +229,14 @@ const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => {
/>
)}
{isModalOpenFor('NicknameModal') && <NicknameModal isModalOpen onRequestClose={hideModal} />}
{isModalOpenFor('ErrorModal') && (
<ErrorModal
isModalOpen
message={localize(getEligibilityErrorMessage(eligibilityStatus))}
onRequestClose={hideModal}
showTitle={false}
/>
)}
</div>
);
});
Expand Down
134 changes: 71 additions & 63 deletions src/components/BuySellForm/BuySellData/BuySellData.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { forwardRef } from 'react';
import { THooks } from 'types';
import { PaymentMethodWithIcon } from '@/components';
import { formatTime } from '@/utils';
Expand All @@ -18,76 +19,83 @@ type TBuySellDataProps = {
};

type TType = THooks.AdvertiserPaymentMethods.Get[number]['type'];
const BuySellData = ({
accountCurrency,
expiryPeriod,
instructions = '',
isBuy,
localCurrency,
name,
paymentMethodNames,
paymentMethods,
rate,
}: TBuySellDataProps) => {
const { isMobile } = useDevice();
const labelSize = isMobile ? 'sm' : 'xs';
const valueSize = isMobile ? 'md' : 'sm';
const paymentMethodTypes = paymentMethods?.reduce((acc: Record<string, string>, curr) => {
if (curr.display_name && curr.type) {
acc[curr.display_name] = curr.type;
}
return acc;
}, {});
const BuySellData = forwardRef<HTMLDivElement, TBuySellDataProps>(
(
{
accountCurrency,
expiryPeriod,
instructions = '',
isBuy,
localCurrency,
name,
paymentMethodNames,
paymentMethods,
rate,
},
ref
) => {
const { isMobile } = useDevice();
const labelSize = isMobile ? 'sm' : 'xs';
const valueSize = isMobile ? 'md' : 'sm';
const paymentMethodTypes = paymentMethods?.reduce((acc: Record<string, string>, curr) => {
if (curr.display_name && curr.type) {
acc[curr.display_name] = curr.type;
}
return acc;
}, {});

return (
<div className='p-[1.6rem] lg:px-[2.4rem]'>
<div className='buy-sell-data__details'>
<div className='flex flex-col w-full'>
<Text color='less-prominent' size={labelSize}>
{isBuy ? 'Buyer' : 'Seller'}
</Text>
<Text size={valueSize}>{name}</Text>
return (
<div className='p-[1.6rem] lg:px-[2.4rem]' ref={ref}>
<div className='buy-sell-data__details'>
<div className='flex flex-col w-full'>
<Text color='less-prominent' size={labelSize}>
{isBuy ? 'Buyer' : 'Seller'}
</Text>
<Text size={valueSize}>{name}</Text>
</div>
<div className='flex flex-col w-full'>
<Text color='less-prominent' size={labelSize}>{`Rate (1 ${accountCurrency})`}</Text>
<Text size={valueSize}>
{rate} {localCurrency}
</Text>
</div>
</div>
<div className='flex flex-col w-full'>
<Text color='less-prominent' size={labelSize}>{`Rate (1 ${accountCurrency})`}</Text>
<Text size={valueSize}>
{rate} {localCurrency}
{paymentMethodNames?.length && (
<div className='flex flex-col mb-[1.6rem]'>
<Text className='mb-[0.8rem]' color='less-prominent' size={labelSize}>
<Localize i18n_default_text='Payment methods' />
</Text>
{paymentMethodNames.map(method => (
<PaymentMethodWithIcon
className='mb-[0.8rem]'
key={method}
name={method}
type={paymentMethodTypes?.[method] as TType}
/>
))}
</div>
)}
<div className='flex flex-col mb-[1.6rem]'>
<Text color='less-prominent' size={labelSize}>
{isBuy ? (
<Localize i18n_default_text="Buyer's instructions" />
) : (
<Localize i18n_default_text="Seller's instructions" />
)}
</Text>
<Text size={valueSize}>{instructions}</Text>
</div>
</div>
{paymentMethodNames?.length && (
<div className='flex flex-col mb-[1.6rem]'>
<Text className='mb-[0.8rem]' color='less-prominent' size={labelSize}>
<Localize i18n_default_text='Payment methods' />
<Text color='less-prominent' size={labelSize}>
<Localize i18n_default_text='Orders must be completed in' />
</Text>
{paymentMethodNames.map(method => (
<PaymentMethodWithIcon
className='mb-[0.8rem]'
key={method}
name={method}
type={paymentMethodTypes?.[method] as TType}
/>
))}
<Text size={valueSize}>{formatTime(expiryPeriod)}</Text>
</div>
)}
<div className='flex flex-col mb-[1.6rem]'>
<Text color='less-prominent' size={labelSize}>
{isBuy ? (
<Localize i18n_default_text="Buyer's instructions" />
) : (
<Localize i18n_default_text="Seller's instructions" />
)}
</Text>
<Text size={valueSize}>{instructions}</Text>
</div>
<div className='flex flex-col mb-[1.6rem]'>
<Text color='less-prominent' size={labelSize}>
<Localize i18n_default_text='Orders must be completed in' />
</Text>
<Text size={valueSize}>{formatTime(expiryPeriod)}</Text>
</div>
</div>
);
};
);
}
);

BuySellData.displayName = 'BuySellData';

export default BuySellData;
2 changes: 1 addition & 1 deletion src/components/BuySellForm/BuySellForm.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.buy-sell-form {
width: 44rem;
width: 45.6rem;
height: unset;
border-radius: 8px;

Expand Down
22 changes: 20 additions & 2 deletions src/components/BuySellForm/BuySellForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,12 @@ const BASE_CURRENCY = 'USD';
const BuySellForm = ({ advertId, isModalOpen, onRequestClose }: TBuySellFormProps) => {
const { data: exchangeRatesData, subscribeRates } = useExchangeRates();
const { data: advertInfo } = api.advert.useGet({ id: advertId });
const { data: orderCreatedInfo, isSuccess, mutate } = api.order.useCreate();
const { data: orderCreatedInfo, error, isError, isSuccess, mutate } = api.order.useCreate();
const { data: paymentMethods } = api.paymentMethods.useGet();
const { data: advertiserPaymentMethods, get } = api.advertiserPaymentMethods.useGet();
const { data } = api.advertiser.useGetInfo() || {};
const [errorMessage, setErrorMessage] = useState('');
const scrollRef = useRef<HTMLDivElement>(null);
const {
balance_available = '',
daily_buy = 0,
Expand Down Expand Up @@ -210,6 +212,13 @@ const BuySellForm = ({ advertId, isModalOpen, onRequestClose }: TBuySellFormProp
}
}, [isSuccess, orderCreatedInfo, history, onRequestClose]);

useEffect(() => {
if (isError && error?.error.message) {
setErrorMessage(error?.error.message);
scrollRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' });
}
}, [error?.error.message, isError]);

return (
<form onSubmit={handleSubmit(onSubmit)}>
<BuySellFormDisplayWrapper
Expand All @@ -220,15 +229,23 @@ const BuySellForm = ({ advertId, isModalOpen, onRequestClose }: TBuySellFormProp
onRequestClose={onRequestClose}
onSubmit={onSubmit}
>
{/* TODO: Remove the below banner when implementing real time exchange changes */}
{rate_type === RATE_TYPE.FLOAT && !shouldDisableField && (
<div className='px-[2.4rem] mt-[2.4rem]'>
<InlineMessage variant='info'>
<Text size={isMobile ? 'xs' : '2xs'}>
<Localize i18n_default_text=' If the market rate changes from the rate shown here, we won’t be able to process your order.' />
<Localize i18n_default_text='If the market rate changes from the rate shown here, we won’t be able to process your order.' />
</Text>
</InlineMessage>
</div>
)}
{errorMessage && (
<div className='px-[2.4rem] mt-[2.4rem]'>
<InlineMessage variant='error'>
<Text size={isMobile ? 'xs' : '2xs'}>{errorMessage}</Text>
</InlineMessage>
</div>
)}
<BuySellData
accountCurrency={account_currency as TCurrency}
expiryPeriod={order_expiry_period ?? 3600}
Expand All @@ -239,6 +256,7 @@ const BuySellForm = ({ advertId, isModalOpen, onRequestClose }: TBuySellFormProp
paymentMethodNames={payment_method_names}
paymentMethods={paymentMethods as THooks.PaymentMethods.Get}
rate={displayEffectiveRate}
ref={scrollRef}
/>
<LightDivider />
{isBuy && payment_method_names && payment_method_names?.length > 0 && (
Expand Down
Loading
Loading