Skip to content

Commit

Permalink
Merge pull request #146 from nada-deriv/nada/P2PS-2639/order-expiry-p…
Browse files Browse the repository at this point in the history
…eriod

Nada/P2PS-2639/fix: use expiry period from BE
  • Loading branch information
farrah-deriv authored Jun 26, 2024
2 parents ab42dda + 969e1bc commit 30bfef8
Show file tree
Hide file tree
Showing 18 changed files with 147 additions and 68 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"@chakra-ui/react": "^2.8.2",
"@deriv-com/api-hooks": "^1.2.1",
"@deriv-com/translations": "^1.2.4",
"@deriv-com/ui": "^1.28.3",
"@deriv-com/ui": "^1.29.0",
"@deriv-com/utils": "^0.0.26",
"@deriv/deriv-api": "^1.0.15",
"@deriv/quill-design": "^1.2.24",
Expand Down
5 changes: 3 additions & 2 deletions src/components/BuySellForm/BuySellData/BuySellData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { forwardRef } from 'react';
import { THooks } from 'types';
import { PaymentMethodWithIcon } from '@/components';
import { formatTime } from '@/utils';
import { Localize } from '@deriv-com/translations';
import { Localize, useTranslations } from '@deriv-com/translations';
import { Text, useDevice } from '@deriv-com/ui';
import './BuySellData.scss';

Expand Down Expand Up @@ -34,6 +34,7 @@ const BuySellData = forwardRef<HTMLDivElement, TBuySellDataProps>(
},
ref
) => {
const { localize } = useTranslations();
const { isMobile } = useDevice();
const labelSize = isMobile ? 'sm' : 'xs';
const valueSize = isMobile ? 'md' : 'sm';
Expand Down Expand Up @@ -89,7 +90,7 @@ const BuySellData = forwardRef<HTMLDivElement, TBuySellDataProps>(
<Text color='less-prominent' size={labelSize}>
<Localize i18n_default_text='Orders must be completed in' />
</Text>
<Text size={valueSize}>{formatTime(expiryPeriod)}</Text>
<Text size={valueSize}>{formatTime(expiryPeriod, localize)}</Text>
</div>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/CopyAdForm/CopyAdForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ const CopyAdForm = ({ formValues, isModalOpen, onClickCancel, onFormSubmit, ...r
<Text color='less-prominent' size={labelSize}>
<Localize i18n_default_text='Order must be completed in' />
</Text>
<Text size={valueSize}>{formatTime(orderExpiryPeriod ?? 3600)}</Text>
<Text size={valueSize}>{formatTime(orderExpiryPeriod ?? 3600, localize)}</Text>
</div>
<div className='flex flex-col w-full mt-[1.6rem]'>
<Text color='less-prominent' size={labelSize}>
Expand Down
21 changes: 0 additions & 21 deletions src/constants/orders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,5 @@ export const ORDERS_STATUS = {
TIMED_OUT: 'timed-out',
} as const;

//TODO: Below constant to be removed once list is fetched from API
export const getOrderTimeCompletionList = (localize: TLocalize) =>
[
{
text: localize('1 hour'),
value: '3600',
},
{
text: localize('45 minutes'),
value: '2700',
},
{
text: localize('30 minutes'),
value: '1800',
},
{
text: localize('15 minutes'),
value: '900',
},
] as const;

export const getOrderTimeInfoMessage = (localize: TLocalize) =>
localize('Orders will expire if they aren’t completed within this time.');
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { MouseEventHandler, useState } from 'react';
import { useFormContext } from 'react-hook-form';
import { TCurrency } from 'types';
import { TCurrency, TOrderExpiryOptions } from 'types';
import { BUY_SELL } from '@/constants';
import { AdFormController } from '../AdFormController';
import { AdPaymentSelection } from '../AdPaymentSelection';
Expand All @@ -14,10 +14,17 @@ type TAdPaymentDetailsSection = {
goToNextStep: MouseEventHandler<HTMLButtonElement>;
goToPreviousStep: () => void;
localCurrency?: TCurrency;
orderExpiryOptions: TOrderExpiryOptions;
rateType: string;
};

const AdPaymentDetailsSection = ({ currency, localCurrency, rateType, ...props }: TAdPaymentDetailsSection) => {
const AdPaymentDetailsSection = ({
currency,
localCurrency,
orderExpiryOptions,
rateType,
...props
}: TAdPaymentDetailsSection) => {
const {
formState: { errors, isValid },
getValues,
Expand Down Expand Up @@ -51,7 +58,7 @@ const AdPaymentDetailsSection = ({ currency, localCurrency, rateType, ...props }
rateType={rateType}
type={getValues('ad-type')}
/>
<OrderTimeSelection />
<OrderTimeSelection orderExpiryOptions={orderExpiryOptions} />
<AdPaymentSelection
isSellAdvert={isSellAdvert}
onSelectPaymentMethod={onSelectPaymentMethod}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ const mockProps = {
goToNextStep: jest.fn(),
goToPreviousStep: jest.fn(),
localCurrency: 'IDR' as TCurrency,
orderExpiryOptions: [900, 1800],
rateType: 'fixed',
};

Expand Down
7 changes: 4 additions & 3 deletions src/pages/my-ads/components/AdWizard/AdWizard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from 'react';
import { TCountryListItem, TCurrency, TStep } from 'types';
import { TCountryListItem, TCurrency, TOrderExpiryOptions, TStep } from 'types';
import { FormProgress, Wizard } from '@/components';
import { LabelPairedXmarkLgBoldIcon } from '@deriv/quill-icons';
import { Localize } from '@deriv-com/translations';
Expand All @@ -15,11 +15,12 @@ type TAdWizardNav = {
currency: TCurrency;
localCurrency?: TCurrency;
onCancel: () => void;
orderExpiryOptions: TOrderExpiryOptions;
rateType: string;
steps: TStep[];
};

const AdWizard = ({ countryList, onCancel, steps, ...rest }: TAdWizardNav) => {
const AdWizard = ({ countryList, onCancel, orderExpiryOptions, steps, ...rest }: TAdWizardNav) => {
const { isDesktop } = useDevice();
const [currentStep, setCurrentStep] = useState(0);
const wizardProps = {
Expand Down Expand Up @@ -69,7 +70,7 @@ const AdWizard = ({ countryList, onCancel, steps, ...rest }: TAdWizardNav) => {
onStepChange={step => setCurrentStep(step.activeStep - 1)}
>
<AdTypeSection onCancel={onCancel} {...wizardProps} {...rest} />
<AdPaymentDetailsSection {...wizardProps} {...rest} />
<AdPaymentDetailsSection {...wizardProps} {...rest} orderExpiryOptions={orderExpiryOptions} />
<AdConditionsSection {...wizardProps} countryList={countryList} {...rest} />
</Wizard>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const mockProps = {
currency: 'usd' as TCurrency,
localCurrency: 'usd' as TCurrency,
onCancel: jest.fn(),
orderExpiryOptions: [900, 1800],
rateType: 'float',
steps: [{ header: { title: 'step 1' } }, { header: { title: 'step 2' } }, { header: { title: 'step 3' } }],
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ComponentProps } from 'react';
import { LabelPairedCirclePlusCaptionRegularIcon } from '@deriv/quill-icons';
import { useTranslations } from '@deriv-com/translations';
import { Dropdown } from '@deriv-com/ui';
import './BuyPaymentMethodsList.scss';

Expand All @@ -9,19 +10,21 @@ type TBuyPaymentMethodsList = {
};

const BuyPaymentMethodsList = ({ list, onSelectPaymentMethod }: TBuyPaymentMethodsList) => {
const { localize } = useTranslations();
return (
<div className='buy-payment-methods-list'>
<Dropdown
className='buy-payment-methods-list__dropdown'
data-testid='dt_buy_payment_methods_list'
dropdownIcon={<div />}
emptyResultMessage={localize('No results found')}
icon={<LabelPairedCirclePlusCaptionRegularIcon />}
isFullWidth
label={localize('Add')}
list={list}
name='payment-method-list'
onSelect={value => onSelectPaymentMethod(value as string)}
// @ts-expect-error - Dropdown component does not have a value prop
placeholder='Add'
shouldClearValue
value=''
variant='prompt'
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,49 @@
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { Controller, useFormContext } from 'react-hook-form';
import { MutableOption } from 'types';
import { TOrderExpiryOptions } from 'types';
import { OrderTimeTooltipModal } from '@/components/Modals';
import { TooltipMenuIcon } from '@/components/TooltipMenuIcon';
import { getOrderTimeCompletionList, getOrderTimeInfoMessage } from '@/constants';
import { getOrderTimeInfoMessage } from '@/constants';
import { formatTime, getOrderTimeCompletionList } from '@/utils';
import { LabelPairedChevronDownMdRegularIcon, LabelPairedCircleInfoCaptionRegularIcon } from '@deriv/quill-icons';
import { Localize, useTranslations } from '@deriv-com/translations';
import { Dropdown, Text, useDevice } from '@deriv-com/ui';
import './OrderTimeSelection.scss';

const OrderTimeSelection = () => {
const { control } = useFormContext();
const OrderTimeSelection = ({ orderExpiryOptions }: { orderExpiryOptions: TOrderExpiryOptions }) => {
const { control, getValues, setValue } = useFormContext();
const [isModalOpen, setIsModalOpen] = useState(false);
const { isMobile } = useDevice();
const { localize } = useTranslations();

// remove the existing selection from input field if the existing value is not present in the dropdown
useEffect(() => {
if (
orderExpiryOptions &&
!orderExpiryOptions.find(option => option === Number(getValues('order-completion-time'))) &&
getValues('form-type') !== 'edit'
) {
setValue('order-completion-time', `${Math.max(...(orderExpiryOptions as number[]))}`);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [orderExpiryOptions]);

const getOptions = () => {
const options = getOrderTimeCompletionList(localize, orderExpiryOptions);
if (
getValues('form-type') === 'edit' &&
!options.some(option => option.value === getValues('order-completion-time'))
)
return [
{
text: formatTime(Number(getValues('order-completion-time')), localize),
value: getValues('order-completion-time'),
},
...options,
];
return options;
};

return (
<div className='order-time-selection'>
<div className='flex items-center gap-[0.8rem]'>
Expand Down Expand Up @@ -44,9 +73,10 @@ const OrderTimeSelection = () => {
<Dropdown
className='items-center h-16'
dropdownIcon={<LabelPairedChevronDownMdRegularIcon />}
list={getOrderTimeCompletionList(localize) as unknown as MutableOption[]}
list={getOptions()}
name='order-completion-time'
onSelect={onChange}
shouldClearValue
value={value}
variant='comboBox'
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,31 @@ jest.mock('react-hook-form', () => ({
}),
useFormContext: () => ({
control: 'mockedControl',
getValues: jest.fn(),
setValue: jest.fn(),
}),
}));

const mockProps = { orderExpiryOptions: [900, 1800, 3600] };
describe('OrderTimeSelection', () => {
it('should render the order time selection component', () => {
render(<OrderTimeSelection />);
render(<OrderTimeSelection {...mockProps} />);
expect(screen.getByText('Orders must be completed in')).toBeInTheDocument();
});
it('should handle the dropdown click', async () => {
render(<OrderTimeSelection />);
render(<OrderTimeSelection {...mockProps} />);
await userEvent.click(screen.getByRole('combobox'));
expect(screen.getByRole('listbox')).toBeInTheDocument();
expect(screen.getByText('1 hour')).toBeInTheDocument();
});
it('should not do anything on clicking info icon in desktop view', async () => {
render(<OrderTimeSelection />);
render(<OrderTimeSelection {...mockProps} />);
await userEvent.click(screen.getByTestId('dt_order_info_icon'));
expect(screen.queryByRole('button', { name: 'Ok' })).not.toBeInTheDocument();
});
it('should handle the modal open in mobile view', async () => {
mockUseDevice.mockReturnValue({ isMobile: true });
render(<OrderTimeSelection />);
render(<OrderTimeSelection {...mockProps} />);
await userEvent.click(screen.getByTestId('dt_order_info_icon'));
const okButton = screen.getByRole('button', { name: 'Ok' });
expect(okButton).toBeInTheDocument();
Expand Down
Loading

0 comments on commit 30bfef8

Please sign in to comment.