chore: update fills tab - add tooltip with fees breakdown (#2606)

* chore: update fills tab - add tooltip with fees breakdown

* chore: update fills tab - fix failing unit test

* chore: update fills tab - add unit test

* chore: update fills tab - adjust int test
This commit is contained in:
macqbat 2023-01-13 11:44:01 +01:00 committed by GitHub
parent 6d3795f1f4
commit 2b28ff6c18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 105 additions and 13 deletions

View File

@ -66,7 +66,9 @@ describe('Portfolio page tabs', { tags: '@smoke' }, () => {
it('data should be properly rendered', () => {
cy.get('.ag-center-cols-container .ag-row').should('have.length', 5);
cy.contains('.ag-center-cols-container button', 'tEURO').click();
cy.get('[role="gridcell"][col-id="account-asset"] button')
.contains('tEURO')
.click();
cy.getByTestId('dialog-title').should(
'have.text',
'Asset details - tEURO'

View File

@ -1,4 +1,5 @@
import { act, render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { getDateTimeFormat } from '@vegaprotocol/react-helpers';
import * as Schema from '@vegaprotocol/types';
import type { PartialDeep } from 'type-fest';
@ -57,8 +58,8 @@ describe('FillsTable', () => {
const expectedHeaders = [
'Market',
'Size',
'Value',
'Filled value',
'Price',
'Notional',
'Role',
'Fee',
'Date',
@ -82,7 +83,7 @@ describe('FillsTable', () => {
},
});
render(<FillsTable partyId={partyId} rowData={[buyerFill]} />);
render(<FillsTable partyId={partyId} rowData={[{ ...buyerFill }]} />);
await waitForGridToBeInTheDOM();
await waitForDataToHaveLoaded();
@ -179,4 +180,38 @@ describe('FillsTable', () => {
.find((c) => c.getAttribute('col-id') === 'aggressor')
).toHaveTextContent('Maker');
});
it('should render tooltip over fees', async () => {
const partyId = 'party-id';
const takerFill = generateFill({
seller: {
id: partyId,
},
aggressor: Schema.Side.SIDE_SELL,
});
act(() => {
render(<FillsTable partyId={partyId} rowData={[takerFill]} />);
});
await waitForGridToBeInTheDOM();
await waitForDataToHaveLoaded();
const feeCell = screen
.getAllByRole('gridcell')
.find(
(c) =>
c.getAttribute('col-id') ===
'market.tradableInstrument.instrument.product'
);
await waitFor(() => {
expect(feeCell).toBeInTheDocument();
});
act(() => {
userEvent.hover(feeCell as HTMLElement);
});
await waitFor(() => {
expect(screen.getByTestId('fee-breakdown-tooltip')).toBeInTheDocument();
});
});
});

View File

@ -1,4 +1,9 @@
import type { AgGridReact } from 'ag-grid-react';
import type {
AgGridReact,
AgGridReactProps,
AgReactUiProps,
} from 'ag-grid-react';
import type { ITooltipParams } from 'ag-grid-community';
import {
addDecimal,
addDecimalsFormatNumber,
@ -15,7 +20,6 @@ import type { VegaValueFormatterParams } from '@vegaprotocol/ui-toolkit';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
import { forwardRef } from 'react';
import BigNumber from 'bignumber.js';
import type { AgGridReactProps, AgReactUiProps } from 'ag-grid-react';
import type { Trade } from './fills-data-provider';
export type Props = (AgGridReactProps | AgReactUiProps) & {
@ -31,6 +35,8 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
defaultColDef={{ flex: 1, resizable: true }}
style={{ width: '100%', height: '100%' }}
getRowId={({ data }) => data?.id}
tooltipShowDelay={0}
tooltipHideDelay={2000}
{...props}
>
<AgGridColumn
@ -54,13 +60,13 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
valueFormatter={formatSize(partyId)}
/>
<AgGridColumn
headerName={t('Value')}
headerName={t('Price')}
field="price"
valueFormatter={formatPrice}
type="rightAligned"
/>
<AgGridColumn
headerName={t('Filled value')}
headerName={t('Notional')}
field="price"
valueFormatter={formatTotal}
type="rightAligned"
@ -75,6 +81,9 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
field="market.tradableInstrument.instrument.product"
valueFormatter={formatFee(partyId)}
type="rightAligned"
tooltipField="market.tradableInstrument.instrument.product"
tooltipComponent={FeesBreakdownTooltip}
tooltipComponentParams={{ partyId }}
/>
<AgGridColumn
headerName={t('Date')}
@ -148,16 +157,15 @@ const formatTotal = ({
if (!data?.market || !isNumeric(value)) {
return '-';
}
const asset =
data?.market.tradableInstrument.instrument.product.settlementAsset.symbol;
const { symbol: assetSymbol, decimals: assetDecimals } =
data?.market.tradableInstrument.instrument.product.settlementAsset ?? {};
const size = new BigNumber(
addDecimal(data?.size, data?.market.positionDecimalPlaces)
);
const price = new BigNumber(addDecimal(value, data?.market.decimalPlaces));
const total = size.times(price).toString();
const valueFormatted = formatNumber(total, data?.market.decimalPlaces);
return `${valueFormatted} ${asset}`;
const valueFormatted = formatNumber(total, assetDecimals);
return `${valueFormatted} ${assetSymbol}`;
};
const formatRole = (partyId: string) => {
@ -210,3 +218,50 @@ const formatFee = (partyId: string) => {
return `${totalFees} ${asset.symbol}`;
};
};
const FeesBreakdownTooltip = ({
data,
value,
valueFormatted,
partyId,
}: ITooltipParams & { partyId?: string }) => {
if (!value?.settlementAsset || !data) {
return null;
}
const asset = value.settlementAsset;
let feesObj;
if (data?.buyer.id === partyId) {
feesObj = data?.buyerFee;
} else if (data?.seller.id === partyId) {
feesObj = data?.sellerFee;
} else {
return null;
}
return (
<div
data-testid="fee-breakdown-tooltip"
className="max-w-sm border border-neutral-600 bg-neutral-100 dark:bg-neutral-800 px-4 py-2 z-20 rounded text-sm break-word text-black dark:text-white"
>
<dl className="grid grid-cols-2 gap-x-2">
<dt>{t('Infrastructure fee')}</dt>
<dd className="text-right">
{addDecimalsFormatNumber(feesObj.infrastructureFee, asset.decimals)}{' '}
{asset.symbol}
</dd>
<dt>{t('Liquidity fee')}</dt>
<dd className="text-right">
{addDecimalsFormatNumber(feesObj.liquidityFee, asset.decimals)}{' '}
{asset.symbol}
</dd>
<dt>{t('Maker fee')}</dt>
<dd className="text-right">
{addDecimalsFormatNumber(feesObj.makerFee, asset.decimals)}{' '}
{asset.symbol}
</dd>
<dt>{t('Total fees')}</dt>
<dd className="text-right">{valueFormatted}</dd>
</dl>
</div>
);
};