import React, { useCallback, useEffect, useMemo, useState } from 'react'; import debounce from 'lodash/debounce'; import { addDecimalsFormatNumber, t, titlefy, useDataProvider, useThrottledDataProvider, } from '@vegaprotocol/react-helpers'; import { AsyncRenderer, ExternalLink, Splash } from '@vegaprotocol/ui-toolkit'; import type { SingleMarketFieldsFragment, MarketData, Candle, MarketDataUpdateFieldsFragment, } from '@vegaprotocol/market-list'; import { marketProvider, marketDataProvider } from '@vegaprotocol/market-list'; import { useGlobalStore, usePageTitleStore } from '../../stores'; import { TradeGrid, TradePanels } from './trade-grid'; import { useNavigate, useParams } from 'react-router-dom'; import { Links, Routes } from '../../pages/client-router'; const calculatePrice = (markPrice?: string, decimalPlaces?: number) => { return markPrice && decimalPlaces ? addDecimalsFormatNumber(markPrice, decimalPlaces) : '-'; }; export interface SingleMarketData extends SingleMarketFieldsFragment { candles: Candle[]; data: MarketData; } const TitleUpdater = ({ marketId, marketName, decimalPlaces, }: { marketId?: string; marketName?: string; decimalPlaces?: number; }) => { const pageTitle = usePageTitleStore((store) => store.pageTitle); const updateTitle = usePageTitleStore((store) => store.updateTitle); const { data: marketData } = useThrottledDataProvider< MarketData, MarketDataUpdateFieldsFragment >( { dataProvider: marketDataProvider, variables: useMemo(() => ({ marketId }), [marketId]), skip: !marketId, }, 1000 ); useEffect(() => { const marketPrice = calculatePrice(marketData?.markPrice, decimalPlaces); if (marketName) { const newPageTitle = titlefy([marketName, marketPrice]); if (pageTitle !== newPageTitle) { updateTitle(newPageTitle); } } }, [ decimalPlaces, marketName, marketData?.markPrice, pageTitle, updateTitle, ]); return null; }; export const MarketPage = () => { const { marketId } = useParams(); const navigate = useNavigate(); const { w } = useWindowSize(); const update = useGlobalStore((store) => store.update); const lastMarketId = useGlobalStore((store) => store.marketId); const onSelect = useCallback( (id: string) => { if (id && id !== marketId) { navigate(Links[Routes.MARKET](id)); } }, [marketId, navigate] ); const { data, error, loading } = useDataProvider< SingleMarketFieldsFragment, never >({ dataProvider: marketProvider, variables: useMemo(() => ({ marketId: marketId || '' }), [marketId]), skip: !marketId, }); useEffect(() => { if (data?.id && data.id !== lastMarketId) { update({ marketId: data.id }); } }, [update, lastMarketId, data?.id]); const tradeView = useMemo(() => { if (w > 960) { return ; } return ; }, [w, data, onSelect]); if (!data && marketId) { return (

{t('This market URL is not available anymore.')}

{t(`Please choose another market from the`)}{' '} navigate(Links[Routes.MARKETS]())}> market list

); } return ( loading={loading} error={error} data={data || undefined} noDataCondition={(data) => false} > {tradeView} ); }; const useWindowSize = () => { const [windowSize, setWindowSize] = useState(() => { if (typeof window !== 'undefined') { return { w: window.innerWidth, h: window.innerHeight, }; } // Something sensible for server rendered page return { w: 1200, h: 900, }; }); useEffect(() => { const handleResize = debounce(({ target }) => { setWindowSize({ w: target.innerWidth, h: target.innerHeight, }); }, 300); window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); }; }, []); return windowSize; };