add swipeable tabs
This commit is contained in:
parent
a3e06cdee0
commit
924b9b279d
|
@ -14,11 +14,16 @@ import { useRouter } from 'next/router'
|
||||||
import { AreaChart, Area, XAxis, YAxis } from 'recharts'
|
import { AreaChart, Area, XAxis, YAxis } from 'recharts'
|
||||||
import { useTheme } from 'next-themes'
|
import { useTheme } from 'next-themes'
|
||||||
|
|
||||||
const MarketsTable = ({ isPerpMarket }) => {
|
const MarketsTable = ({
|
||||||
|
isPerpMarket,
|
||||||
|
markets,
|
||||||
|
}: {
|
||||||
|
isPerpMarket?: boolean
|
||||||
|
markets: any[]
|
||||||
|
}) => {
|
||||||
const { t } = useTranslation('common')
|
const { t } = useTranslation('common')
|
||||||
const { width } = useViewport()
|
const { width } = useViewport()
|
||||||
const isMobile = width ? width < breakpoints.md : false
|
const isMobile = width ? width < breakpoints.md : false
|
||||||
const marketsInfo = useMangoStore((s) => s.marketsInfo)
|
|
||||||
const actions = useMangoStore((s) => s.actions)
|
const actions = useMangoStore((s) => s.actions)
|
||||||
const coingeckoPrices = useMangoStore((s) => s.coingeckoPrices.data)
|
const coingeckoPrices = useMangoStore((s) => s.coingeckoPrices.data)
|
||||||
const loadingCoingeckoPrices = useMangoStore((s) => s.coingeckoPrices.loading)
|
const loadingCoingeckoPrices = useMangoStore((s) => s.coingeckoPrices.loading)
|
||||||
|
@ -31,28 +36,9 @@ const MarketsTable = ({ isPerpMarket }) => {
|
||||||
}
|
}
|
||||||
}, [coingeckoPrices])
|
}, [coingeckoPrices])
|
||||||
|
|
||||||
const perpMarketsInfo = useMemo(
|
const { items, requestSort, sortConfig } = useSortableData(markets)
|
||||||
() =>
|
|
||||||
marketsInfo
|
|
||||||
.filter((mkt) => mkt?.name.includes('PERP'))
|
|
||||||
.sort((a, b) => b.volumeUsd24h - a.volumeUsd24h),
|
|
||||||
[marketsInfo]
|
|
||||||
)
|
|
||||||
|
|
||||||
const spotMarketsInfo = useMemo(
|
return !isMobile ? (
|
||||||
() =>
|
|
||||||
marketsInfo
|
|
||||||
.filter((mkt) => mkt?.name.includes('USDC'))
|
|
||||||
.sort((a, b) => b.volumeUsd24h - a.volumeUsd24h),
|
|
||||||
[marketsInfo]
|
|
||||||
)
|
|
||||||
|
|
||||||
const { items, requestSort, sortConfig } = useSortableData(
|
|
||||||
isPerpMarket ? perpMarketsInfo : spotMarketsInfo
|
|
||||||
)
|
|
||||||
|
|
||||||
return items.length > 0 ? (
|
|
||||||
!isMobile ? (
|
|
||||||
<Table>
|
<Table>
|
||||||
<thead>
|
<thead>
|
||||||
<TrHead>
|
<TrHead>
|
||||||
|
@ -191,9 +177,7 @@ const MarketsTable = ({ isPerpMarket }) => {
|
||||||
openInterestUsd,
|
openInterestUsd,
|
||||||
volumeUsd24h,
|
volumeUsd24h,
|
||||||
} = market
|
} = market
|
||||||
const fundingApr = funding1h
|
const fundingApr = funding1h ? (funding1h * 24 * 365).toFixed(2) : '-'
|
||||||
? (funding1h * 24 * 365).toFixed(2)
|
|
||||||
: '-'
|
|
||||||
const coingeckoData = coingeckoPrices.find(
|
const coingeckoData = coingeckoPrices.find(
|
||||||
(asset) => asset.symbol === baseSymbol
|
(asset) => asset.symbol === baseSymbol
|
||||||
)
|
)
|
||||||
|
@ -276,9 +260,7 @@ const MarketsTable = ({ isPerpMarket }) => {
|
||||||
<span className="text-xs text-th-fgd-3">{`(${fundingApr}% APR)`}</span>
|
<span className="text-xs text-th-fgd-3">{`(${fundingApr}% APR)`}</span>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-th-fgd-4">
|
<span className="text-th-fgd-4">{t('unavailable')}</span>
|
||||||
{t('unavailable')}
|
|
||||||
</span>
|
|
||||||
)}
|
)}
|
||||||
</Td>
|
</Td>
|
||||||
<Td>
|
<Td>
|
||||||
|
@ -296,9 +278,7 @@ const MarketsTable = ({ isPerpMarket }) => {
|
||||||
) : null}
|
) : null}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-th-fgd-4">
|
<span className="text-th-fgd-4">{t('unavailable')}</span>
|
||||||
{t('unavailable')}
|
|
||||||
</span>
|
|
||||||
)}
|
)}
|
||||||
</Td>
|
</Td>
|
||||||
</>
|
</>
|
||||||
|
@ -314,7 +294,8 @@ const MarketsTable = ({ isPerpMarket }) => {
|
||||||
</tbody>
|
</tbody>
|
||||||
</Table>
|
</Table>
|
||||||
) : (
|
) : (
|
||||||
items.map((market) => {
|
<>
|
||||||
|
{items.map((market) => {
|
||||||
const { baseSymbol, change24h, funding1h, last, name } = market
|
const { baseSymbol, change24h, funding1h, last, name } = market
|
||||||
const fundingApr = funding1h ? (funding1h * 24 * 365).toFixed(2) : '-'
|
const fundingApr = funding1h ? (funding1h * 24 * 365).toFixed(2) : '-'
|
||||||
const coingeckoData = coingeckoPrices.find(
|
const coingeckoData = coingeckoPrices.find(
|
||||||
|
@ -332,7 +313,7 @@ const MarketsTable = ({ isPerpMarket }) => {
|
||||||
return (
|
return (
|
||||||
<Link href={`/?name=${name}`} shallow={true} key={name}>
|
<Link href={`/?name=${name}`} shallow={true} key={name}>
|
||||||
<a
|
<a
|
||||||
className="mb-2.5 block w-full rounded-lg bg-th-bkg-3 p-4 pb-2.5"
|
className="mb-2 block w-full rounded-lg bg-th-bkg-3 p-4 pb-2.5"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
router.push(`/?name=${name}`, undefined, {
|
router.push(`/?name=${name}`, undefined, {
|
||||||
shallow: true,
|
shallow: true,
|
||||||
|
@ -405,13 +386,11 @@ const MarketsTable = ({ isPerpMarket }) => {
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
})
|
})}
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
) : null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MarketsTable as any
|
|
||||||
|
|
||||||
const PriceChart = ({ data, width, height, color }) => (
|
const PriceChart = ({ data, width, height, color }) => (
|
||||||
<AreaChart width={width} height={height} data={data}>
|
<AreaChart width={width} height={height} data={data}>
|
||||||
<defs>
|
<defs>
|
||||||
|
@ -431,3 +410,29 @@ const PriceChart = ({ data, width, height, color }) => (
|
||||||
<YAxis domain={['dataMin', 'dataMax']} dataKey="1" hide />
|
<YAxis domain={['dataMin', 'dataMax']} dataKey="1" hide />
|
||||||
</AreaChart>
|
</AreaChart>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const SpotMarketsTable = () => {
|
||||||
|
const marketsInfo = useMangoStore((s) => s.marketsInfo)
|
||||||
|
|
||||||
|
const spotMarketsInfo = useMemo(
|
||||||
|
() =>
|
||||||
|
marketsInfo
|
||||||
|
.filter((mkt) => mkt?.name.includes('USDC'))
|
||||||
|
.sort((a, b) => b.volumeUsd24h - a.volumeUsd24h),
|
||||||
|
[marketsInfo]
|
||||||
|
)
|
||||||
|
return <MarketsTable markets={spotMarketsInfo} />
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PerpMarketsTable = () => {
|
||||||
|
const marketsInfo = useMangoStore((s) => s.marketsInfo)
|
||||||
|
const perpMarketsInfo = useMemo(
|
||||||
|
() =>
|
||||||
|
marketsInfo
|
||||||
|
.filter((mkt) => mkt?.name.includes('PERP'))
|
||||||
|
.sort((a, b) => b.volumeUsd24h - a.volumeUsd24h),
|
||||||
|
[marketsInfo]
|
||||||
|
)
|
||||||
|
|
||||||
|
return <MarketsTable isPerpMarket markets={perpMarketsInfo} />
|
||||||
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ const BottomBar = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="default-transition grid grid-cols-5 grid-rows-1 bg-th-bkg-3 py-2.5">
|
<div className="default-transition grid grid-cols-5 grid-rows-1 bg-th-bkg-4 py-2.5">
|
||||||
<Link
|
<Link
|
||||||
href={{
|
href={{
|
||||||
pathname: '/markets',
|
pathname: '/markets',
|
||||||
|
|
|
@ -6,6 +6,7 @@ import useMangoStore from '../../stores/useMangoStore'
|
||||||
import { getWeights, PerpMarket } from '@blockworks-foundation/mango-client'
|
import { getWeights, PerpMarket } from '@blockworks-foundation/mango-client'
|
||||||
import { CandlesIcon } from '../icons'
|
import { CandlesIcon } from '../icons'
|
||||||
import SwipeableTabs from './SwipeableTabs'
|
import SwipeableTabs from './SwipeableTabs'
|
||||||
|
import Swipeable from './Swipeable'
|
||||||
import AdvancedTradeForm from '../trade_form/AdvancedTradeForm'
|
import AdvancedTradeForm from '../trade_form/AdvancedTradeForm'
|
||||||
import Orderbook from '../Orderbook'
|
import Orderbook from '../Orderbook'
|
||||||
import MarketBalances from '../MarketBalances'
|
import MarketBalances from '../MarketBalances'
|
||||||
|
@ -14,7 +15,6 @@ import MarketPosition from '../MarketPosition'
|
||||||
import OpenOrdersTable from '../OpenOrdersTable'
|
import OpenOrdersTable from '../OpenOrdersTable'
|
||||||
import RecentMarketTrades from '../RecentMarketTrades'
|
import RecentMarketTrades from '../RecentMarketTrades'
|
||||||
import FloatingElement from '../FloatingElement'
|
import FloatingElement from '../FloatingElement'
|
||||||
import Swipeable from './Swipeable'
|
|
||||||
import { useTranslation } from 'next-i18next'
|
import { useTranslation } from 'next-i18next'
|
||||||
import { useWallet } from '@solana/wallet-adapter-react'
|
import { useWallet } from '@solana/wallet-adapter-react'
|
||||||
import SwitchMarketDropdown from 'components/SwitchMarketDropdown'
|
import SwitchMarketDropdown from 'components/SwitchMarketDropdown'
|
||||||
|
|
|
@ -3,8 +3,12 @@ import PageBodyContainer from '../components/PageBodyContainer'
|
||||||
import TopBar from '../components/TopBar'
|
import TopBar from '../components/TopBar'
|
||||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||||
import { useTranslation } from 'next-i18next'
|
import { useTranslation } from 'next-i18next'
|
||||||
import MarketsTable from '../components/MarketsTable'
|
import { PerpMarketsTable, SpotMarketsTable } from '../components/MarketsTable'
|
||||||
import Tabs from '../components/Tabs'
|
import Tabs from '../components/Tabs'
|
||||||
|
import SwipeableTabs from '../components/mobile/SwipeableTabs'
|
||||||
|
import Swipeable from '../components/mobile/Swipeable'
|
||||||
|
import { useViewport } from '../hooks/useViewport'
|
||||||
|
import { breakpoints } from '../components/TradePageGrid'
|
||||||
|
|
||||||
const TABS = ['futures', 'spot']
|
const TABS = ['futures', 'spot']
|
||||||
|
|
||||||
|
@ -19,12 +23,19 @@ export async function getStaticProps({ locale }) {
|
||||||
|
|
||||||
export default function Markets() {
|
export default function Markets() {
|
||||||
const [activeTab, setActiveTab] = useState('futures')
|
const [activeTab, setActiveTab] = useState('futures')
|
||||||
|
const [viewIndex, setViewIndex] = useState(0)
|
||||||
const { t } = useTranslation(['common'])
|
const { t } = useTranslation(['common'])
|
||||||
|
const { width } = useViewport()
|
||||||
|
const isMobile = width ? width < breakpoints.sm : false
|
||||||
|
|
||||||
const handleTabChange = (tabName) => {
|
const handleTabChange = (tabName) => {
|
||||||
setActiveTab(tabName)
|
setActiveTab(tabName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleChangeViewIndex = (index) => {
|
||||||
|
setViewIndex(index)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`bg-th-bkg-1 text-th-fgd-1 transition-all`}>
|
<div className={`bg-th-bkg-1 text-th-fgd-1 transition-all`}>
|
||||||
<TopBar />
|
<TopBar />
|
||||||
|
@ -34,13 +45,36 @@ export default function Markets() {
|
||||||
</div>
|
</div>
|
||||||
<div className="md:rounded-lg md:bg-th-bkg-2 md:p-6">
|
<div className="md:rounded-lg md:bg-th-bkg-2 md:p-6">
|
||||||
<div className="mb-0 sm:mb-6">
|
<div className="mb-0 sm:mb-6">
|
||||||
|
{!isMobile ? (
|
||||||
<Tabs
|
<Tabs
|
||||||
activeTab={activeTab}
|
activeTab={activeTab}
|
||||||
onChange={handleTabChange}
|
onChange={handleTabChange}
|
||||||
tabs={TABS}
|
tabs={TABS}
|
||||||
/>
|
/>
|
||||||
|
) : (
|
||||||
|
<SwipeableTabs
|
||||||
|
onChange={handleChangeViewIndex}
|
||||||
|
tabs={TABS}
|
||||||
|
tabIndex={viewIndex}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<MarketsTable isPerpMarket={activeTab === 'futures'} />
|
{!isMobile ? (
|
||||||
|
activeTab === 'futures' ? (
|
||||||
|
<PerpMarketsTable />
|
||||||
|
) : (
|
||||||
|
<SpotMarketsTable />
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<Swipeable index={viewIndex} onChangeIndex={handleChangeViewIndex}>
|
||||||
|
<div className="px-1">
|
||||||
|
<PerpMarketsTable />
|
||||||
|
</div>
|
||||||
|
<div className="px-1">
|
||||||
|
<SpotMarketsTable />
|
||||||
|
</div>
|
||||||
|
</Swipeable>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</PageBodyContainer>
|
</PageBodyContainer>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue