import { useCallback, useState } from 'react' import { useRouter } from 'next/router' import Link from 'next/link' import useMangoStore from '../stores/useMangoStore' import { ExclamationIcon } from '@heroicons/react/outline' import Button from '../components/Button' import { useViewport } from '../hooks/useViewport' import { breakpoints } from './TradePageGrid' import { Table, Td, Th, TrBody, TrHead } from './TableElements' import { formatUsdValue } from '../utils' import Loading from './Loading' import usePerpPositions from '../hooks/usePerpPositions' import MarketCloseModal from './MarketCloseModal' import { ExpandableRow } from './TableElements' import PerpSideBadge from './PerpSideBadge' import PnlText from './PnlText' import { settlePnl } from './MarketPosition' import { useTranslation } from 'next-i18next' const PositionsTable = () => { const { t } = useTranslation('common') const { reloadMangoAccount } = useMangoStore((s) => s.actions) const [settling, setSettling] = useState(false) const selectedMarket = useMangoStore((s) => s.selectedMarket.current) const selectedMarketConfig = useMangoStore((s) => s.selectedMarket.config) const price = useMangoStore((s) => s.tradeForm.price) const [showMarketCloseModal, setShowMarketCloseModal] = useState(false) const setMangoStore = useMangoStore((s) => s.set) const { openPositions, unsettledPositions } = usePerpPositions() const { width } = useViewport() const isMobile = width ? width < breakpoints.md : false const { asPath } = useRouter() const handleCloseWarning = useCallback(() => { setShowMarketCloseModal(false) }, []) const handleSizeClick = (size, side, indexPrice) => { const step = selectedMarket.minOrderSize const priceOrDefault = price ? price : indexPrice const roundedSize = Math.round(size / step) * step const quoteSize = roundedSize * priceOrDefault setMangoStore((state) => { state.tradeForm.baseSize = roundedSize state.tradeForm.quoteSize = quoteSize.toFixed(2) state.tradeForm.side = side === 'buy' ? 'sell' : 'buy' }) } const handleSettleAll = async () => { setSettling(true) await Promise.all( unsettledPositions.map((p) => settlePnl(p.perpMarket, p.perpAccount, t)) ) await reloadMangoAccount() setSettling(false) } return (
{unsettledPositions.length > 0 ? (
{t('unsettled-positions')}
{unsettledPositions.map((p) => { return (
{p.marketConfig.name}
) })}
) : null}
{openPositions.length ? ( !isMobile ? ( {openPositions.map( ( { marketIndex, marketConfig, perpMarket, perpAccount, basePosition, notionalSize, indexPrice, avgEntryPrice, breakEvenPrice, unrealizedPnl, }, index ) => { return ( {showMarketCloseModal ? ( ) : null} ) } )}
{t('market')} {t('side')} {t('position-size')} {t('notional-size')} {t('average-entry')} {t('break-even')} {t('unrealized-pnl')}
{asPath.includes( `perp/${marketConfig.baseSymbol}` ) ? ( {marketConfig.name} ) : ( {marketConfig.name} )}
{basePosition && selectedMarketConfig.kind === 'perp' && asPath.includes(marketConfig.baseSymbol) ? ( handleSizeClick( Math.abs(basePosition), basePosition > 0 ? 'buy' : 'sell', indexPrice ) } > {`${Math.abs(basePosition)} ${ marketConfig.baseSymbol }`} ) : ( {`${Math.abs(basePosition)} ${ marketConfig.baseSymbol }`} )} {formatUsdValue(Math.abs(notionalSize))} {avgEntryPrice ? formatUsdValue(avgEntryPrice) : '--'} {breakEvenPrice ? formatUsdValue(breakEvenPrice) : '--'}
) : ( openPositions.map( ( { marketConfig, basePosition, notionalSize, avgEntryPrice, breakEvenPrice, unrealizedPnl, }, index ) => { return (
{marketConfig.name}
0 ? 'text-th-green' : 'text-th-red' }`} > {basePosition > 0 ? t('long').toUpperCase() : t('short').toUpperCase()} {Math.abs(basePosition)}
} key={`${index}`} index={index} panelTemplate={ <>
{t('average-entry')}
{avgEntryPrice ? formatUsdValue(avgEntryPrice) : '--'}
{t('notional-size')}
{formatUsdValue(notionalSize)}
{t('break-even')}
{breakEvenPrice ? formatUsdValue(breakEvenPrice) : '--'}
{t('unrealized-pnl')}
} /> ) } ) ) ) : (
{t('no-perp')}
)}
) } export default PositionsTable