feat: [console-lite] - trading - direction selector (#812)

* feat: [console-lite] - trading - direction selector

* feat: [console-lite] - trading - direction selector - add int tests

* feat: [console-lite] - trading - direction selector - fixes after review feedback

* feat: [console-lite] - trading - direction selector - fix accidentaly failling int test

* feat: [console-lite] - trading - direction selector - fix accidentaly failling int test

Co-authored-by: maciek <maciek@vegaprotocol.io>
This commit is contained in:
macqbat 2022-07-20 13:23:15 +02:00 committed by GitHub
parent 556be89bfd
commit d5c8892406
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 1291 additions and 12 deletions

View File

@ -9,14 +9,14 @@ describe('market selector', () => {
});
cy.visit('/markets');
cy.wait('@gqlSimpleMarketsQuery').then((response) => {
if (response.response?.body?.data?.markets?.length) {
markets = response.response?.body?.data?.markets;
if (response.response.body.data?.markets?.length) {
markets = response.response.body.data.markets;
}
});
});
it('should be properly rendered', () => {
if (markets) {
if (markets?.length) {
cy.visit(`/trading/${markets[0].id}`);
cy.get('input[placeholder="Search"]').should(
'have.value',
@ -34,7 +34,7 @@ describe('market selector', () => {
});
it('typing should change list', () => {
if (markets) {
if (markets?.length) {
cy.visit(`/trading/${markets[0].id}`);
cy.get('input[placeholder="Search"]').type('{backspace}');
cy.getByTestId('market-pane')
@ -65,7 +65,7 @@ describe('market selector', () => {
});
it('mobile view', () => {
if (markets) {
if (markets?.length) {
cy.viewport('iphone-xr');
cy.visit(`/trading/${markets[0].id}`);
cy.get('[role="dialog"]').should('not.exist');

View File

@ -0,0 +1,67 @@
import { aliasQuery } from '@vegaprotocol/cypress';
import { generateSimpleMarkets } from '../support/mocks/generate-markets';
import { generateDealTicket } from '../support/mocks/generate-deal-ticket';
describe('Market trade', () => {
let markets;
beforeEach(() => {
cy.mockGQL((req) => {
aliasQuery(req, 'SimpleMarkets', generateSimpleMarkets());
aliasQuery(req, 'DealTicketQuery', generateDealTicket());
});
cy.visit('/markets');
cy.wait('@SimpleMarkets').then((response) => {
if (response.response.body.data?.markets?.length) {
markets = response.response.body.data.markets;
}
});
});
it('side selector should work well', () => {
if (markets?.length) {
cy.visit(`/trading/${markets[0].id}`);
cy.get('#step-1-control [aria-label^="Selected value"]').should(
'have.text',
'Long'
);
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();
cy.get('#step-2-control').click();
cy.get('#step-1-control [aria-label^="Selected value"]').should(
'have.text',
'Short'
);
}
});
it('mobile view should work well', () => {
if (markets?.length) {
cy.viewport('iphone-xr');
cy.visit(`/trading/${markets[0].id}`);
cy.getByTestId('next-button').scrollIntoView().click();
cy.get('button[aria-label="Open long position"]').should(
'have.class',
'selected'
);
cy.get('button[aria-label="Open short position"]').should(
'not.have.class',
'selected'
);
cy.get('button[aria-label="Open short position"]').click();
cy.get('button[aria-label="Open long position"]').should(
'not.have.class',
'selected'
);
cy.get('button[aria-label="Open short position"]').should(
'have.class',
'selected'
);
cy.getByTestId('next-button').scrollIntoView().click();
cy.get('#step-1-control').should(
'contain.html',
'aria-label="Selected value Short"'
);
}
});
});

View File

@ -0,0 +1,33 @@
export const generateDealTicket = () => {
return {
market: {
id: 'first-btcusd-id',
name: 'AAVEDAI Monthly (30 Jun 2022)',
decimalPlaces: 5,
positionDecimalPlaces: 0,
state: 'Active',
tradingMode: 'Continuous',
tradableInstrument: {
instrument: {
product: {
quoteName: 'DAI',
settlementAsset: {
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
symbol: 'tDAI',
name: 'tDAI TEST',
__typename: 'Asset',
},
__typename: 'Future',
},
__typename: 'Instrument',
},
__typename: 'TradableInstrument',
},
depth: {
lastTrade: { price: '9893006', __typename: 'Trade' },
__typename: 'MarketDepth',
},
__typename: 'Market',
},
};
};

File diff suppressed because it is too large Load Diff

View File

@ -3,11 +3,7 @@ import { useForm, Controller } from 'react-hook-form';
import { Stepper } from '../stepper';
import type { DealTicketQuery_market } from '@vegaprotocol/deal-ticket';
import { Button, InputError } from '@vegaprotocol/ui-toolkit';
import {
SideSelector,
DealTicketAmount,
MarketSelector,
} from '@vegaprotocol/deal-ticket';
import { DealTicketAmount, MarketSelector } from '@vegaprotocol/deal-ticket';
import type { Order } from '@vegaprotocol/orders';
import { VegaTxStatus } from '@vegaprotocol/wallet';
import { t, addDecimal, toDecimal } from '@vegaprotocol/react-helpers';
@ -19,6 +15,7 @@ import {
import { useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import MarketNameRenderer from '../simple-market-list/simple-market-renderer';
import SideSelector, { SIDE_NAMES } from './side-selector';
interface DealTicketMarketProps {
market: DealTicketQuery_market;
@ -47,6 +44,7 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
const step = toDecimal(market.positionDecimalPlaces);
const orderType = watch('type');
const orderTimeInForce = watch('timeInForce');
const orderSide = watch('side');
const { message: invalidText, isDisabled } = useOrderValidation({
step,
@ -96,6 +94,7 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
)}
/>
),
value: SIDE_NAMES[orderSide] || '',
},
{
label: t('Choose Position Size'),

View File

@ -0,0 +1,58 @@
import React from 'react';
import classNames from 'classnames';
import { FormGroup, Button } from '@vegaprotocol/ui-toolkit';
import { VegaWalletOrderSide } from '@vegaprotocol/wallet';
import { t } from '@vegaprotocol/react-helpers';
interface SideSelectorProps {
value: VegaWalletOrderSide;
onSelect: (side: VegaWalletOrderSide) => void;
}
export const SIDE_NAMES: Record<VegaWalletOrderSide, string> = {
[VegaWalletOrderSide.Buy]: t('Long'),
[VegaWalletOrderSide.Sell]: t('Short'),
};
export default ({ value, onSelect }: SideSelectorProps) => {
return (
<FormGroup
label={t('Direction')}
labelFor="order-side-toggle"
labelClassName="sr-only"
>
<fieldset
className="w-full grid md:grid-cols-2 gap-20"
id="order-side-toggle"
>
<Button
variant="inline-link"
aria-label={t('Open long position')}
className={classNames(
'buyButton hover:buyButton dark:buyButtonDark dark:hover:buyButtonDark',
{ selected: value === VegaWalletOrderSide.Buy }
)}
onClick={() => onSelect(VegaWalletOrderSide.Buy)}
>
{t('Long')}
</Button>
<Button
variant="inline-link"
aria-label={t('Open short position')}
className={classNames(
'sellButton hover:sellButton dark:sellButtonDark dark:hover:sellButtonDark',
{ selected: value === VegaWalletOrderSide.Sell }
)}
onClick={() => onSelect(VegaWalletOrderSide.Sell)}
>
{t('Short')}
</Button>
<div className="md:col-span-2 text-black dark:text-white text-ui-small">
{t(
'Trading derivatives allows you to make a profit or loss regardless of whether the market you are trading goes up or down. If you open a "long" position, you will make a profit if the price of your chosen market goes up, and you will make a profit for "short" positions when the price goes down.'
)}
</div>
</fieldset>
</FormGroup>
);
};

View File

@ -66,7 +66,7 @@ const SimpleMarketList = () => {
);
const handleOnGridReady = useCallback(() => {
gridRef.current?.api.sizeColumnsToFit();
gridRef.current?.api?.sizeColumnsToFit();
}, [gridRef]);
useEffect(() => {

View File

@ -146,6 +146,7 @@ export const Stepper = ({ steps }: StepperProps) => {
variant="secondary"
onClick={handleNext}
disabled={steps[activeStep].disabled}
data-testid="next-button"
>
{t('Next')}
</Button>

View File

@ -203,7 +203,7 @@ export const MarketSelector = ({ market, setMarket, ItemRenderer }: Props) => {
/>
</Button>
</div>
<hr className="md:hidden mb-5" />
<hr className="mb-5" />
<div
className={classNames(
'md:absolute z-20 flex flex-col top-[30px] z-10 md:drop-shadow-md md:border-1 md:border-black md:dark:border-white bg-white dark:bg-black text-black dark:text-white min-w-full md:max-h-[200px] overflow-y-auto',

View File

@ -39,6 +39,58 @@ const vegaCustomClassesLite = plugin(function ({ addUtilities }) {
marginTop: '10px',
marginRight: '5px',
},
'.buyButton': {
textTransform: 'uppercase',
textDecoration: 'none',
backgroundColor: 'rgba(0, 143, 74, 0.1)',
border: `1px solid ${theme.colors.darkerGreen}`,
color: theme.colors.darkerGreen,
paddingTop: '0.5rem',
paddingBottom: '0.5rem',
'&:hover': {
backgroundColor: theme.colors.darkerGreen,
color: theme.colors.white.DEFAULT,
},
'&.selected': {
backgroundColor: theme.colors.darkerGreen,
color: theme.colors.white.DEFAULT,
},
},
'.buyButtonDark': {
color: theme.colors.darkerGreen,
'&:hover': {
color: theme.colors.black.DEFAULT,
},
'&.selected': {
color: theme.colors.black.DEFAULT,
},
},
'.sellButton': {
textTransform: 'uppercase',
textDecoration: 'none',
paddingTop: '0.5rem',
paddingBottom: '0.5rem',
backgroundColor: 'rgba(255, 8, 126, 0.1)',
border: `1px solid ${theme.colors.pink}`,
color: theme.colors.pink,
'&:hover': {
color: theme.colors.white.DEFAULT,
backgroundColor: theme.colors.pink,
},
'&.selected': {
backgroundColor: theme.colors.pink,
color: theme.colors.white.DEFAULT,
},
},
'.sellButtonDark': {
color: theme.colors.pink,
'&:hover': {
color: theme.colors.black.DEFAULT,
},
'&.selected': {
color: theme.colors.black.DEFAULT,
},
},
});
});