f377e07996
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
165 lines
4.4 KiB
TypeScript
165 lines
4.4 KiB
TypeScript
import type { PinnedAsset } from '@vegaprotocol/accounts';
|
|
import type { Market } from '@vegaprotocol/markets';
|
|
import { OracleBanner } from '@vegaprotocol/markets';
|
|
import type { TradingView } from './trade-views';
|
|
import { TradingViews } from './trade-views';
|
|
import { useState } from 'react';
|
|
import AutoSizer from 'react-virtualized-auto-sizer';
|
|
import classNames from 'classnames';
|
|
import {
|
|
MarketSuccessorBanner,
|
|
MarketSuccessorProposalBanner,
|
|
MarketTerminationBanner,
|
|
} from '../../components/market-banner';
|
|
import { FLAGS } from '@vegaprotocol/environment';
|
|
import { useT } from '../../lib/use-t';
|
|
import { Splash } from '@vegaprotocol/ui-toolkit';
|
|
|
|
interface TradePanelsProps {
|
|
market: Market | null;
|
|
pinnedAsset?: PinnedAsset;
|
|
}
|
|
|
|
export const TradePanels = ({ market, pinnedAsset }: TradePanelsProps) => {
|
|
const [view, setView] = useState<TradingView>('candles');
|
|
|
|
const renderView = () => {
|
|
const Component = TradingViews[view].component;
|
|
|
|
if (!Component) {
|
|
throw new Error(`No component for view: ${view}`);
|
|
}
|
|
|
|
if (!market) return <NoMarketSplash />;
|
|
|
|
// Watch out here, we don't know what component is being rendered
|
|
// so watch out for clashes in props
|
|
return <Component marketId={market?.id} pinnedAsset={pinnedAsset} />;
|
|
};
|
|
|
|
const renderMenu = () => {
|
|
const viewCfg = TradingViews[view];
|
|
|
|
if ('menu' in viewCfg) {
|
|
const Menu = viewCfg.menu;
|
|
|
|
return (
|
|
<div className="flex gap-1 p-1 bg-vega-clight-800 dark:bg-vega-cdark-800 border-b border-default">
|
|
<Menu />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
return (
|
|
<div className="h-full grid grid-rows-[min-content_min-content_1fr_min-content]">
|
|
<div>
|
|
{FLAGS.SUCCESSOR_MARKETS && (
|
|
<>
|
|
<MarketSuccessorBanner market={market} />
|
|
<MarketSuccessorProposalBanner marketId={market?.id} />
|
|
</>
|
|
)}
|
|
<MarketTerminationBanner market={market} />
|
|
<OracleBanner marketId={market?.id || ''} />
|
|
</div>
|
|
<div>{renderMenu()}</div>
|
|
<div className="h-full">
|
|
<AutoSizer>
|
|
{({ width, height }) => (
|
|
<div style={{ width, height }} className="overflow-auto">
|
|
{renderView()}
|
|
</div>
|
|
)}
|
|
</AutoSizer>
|
|
</div>
|
|
<div className="flex flex-nowrap overflow-x-auto max-w-full border-t border-default">
|
|
{Object.keys(TradingViews)
|
|
// filter to control available views for the current market
|
|
// eg only perps should get the funding views
|
|
.filter((_key) => {
|
|
const key = _key as TradingView;
|
|
const perpOnlyViews = ['funding', 'fundingPayments'];
|
|
|
|
if (
|
|
market?.tradableInstrument.instrument.product.__typename ===
|
|
'Perpetual'
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
if (perpOnlyViews.includes(key)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
})
|
|
.map((_key) => {
|
|
const key = _key as TradingView;
|
|
const isActive = view === key;
|
|
return (
|
|
<ViewButton
|
|
key={key}
|
|
view={key}
|
|
isActive={isActive}
|
|
onClick={() => setView(key)}
|
|
/>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const NoMarketSplash = () => {
|
|
const t = useT();
|
|
return <Splash>{t('No market')}</Splash>;
|
|
};
|
|
|
|
const ViewButton = ({
|
|
view,
|
|
isActive,
|
|
onClick,
|
|
}: {
|
|
view: TradingView;
|
|
isActive: boolean;
|
|
onClick: () => void;
|
|
}) => {
|
|
const label = useViewLabel(view);
|
|
const className = classNames('py-2 px-4 min-w-[100px] capitalize text-sm', {
|
|
'bg-vega-clight-500 dark:bg-vega-cdark-500': isActive,
|
|
});
|
|
|
|
return (
|
|
<button data-testid={view} onClick={onClick} className={className}>
|
|
{label}
|
|
</button>
|
|
);
|
|
};
|
|
|
|
const useViewLabel = (view: TradingView) => {
|
|
const t = useT();
|
|
|
|
const labels = {
|
|
candles: t('Candles'),
|
|
depth: t('Depth'),
|
|
liquidity: t('Liquidity'),
|
|
funding: t('Funding'),
|
|
fundingPayments: t('Funding Payments'),
|
|
orderbook: t('Orderbook'),
|
|
trades: t('Trades'),
|
|
positions: t('Positions'),
|
|
activeOrders: t('Active'),
|
|
closedOrders: t('Closed'),
|
|
rejectedOrders: t('Rejected'),
|
|
orders: t('All'),
|
|
stopOrders: t('Stop'),
|
|
collateral: t('Collateral'),
|
|
fills: t('Fills'),
|
|
};
|
|
|
|
return labels[view];
|
|
};
|