Merge pull request #301 from blockworks-foundation/redeem-buttons
redeem positive button logic
This commit is contained in:
commit
67804e7bb0
|
@ -1,124 +0,0 @@
|
|||
import { ChevronDownIcon } from '@heroicons/react/solid'
|
||||
import React, { Fragment, useState } from 'react'
|
||||
import {settleAllPnl, settlePosPnl} from 'components/MarketPosition'
|
||||
import Button from 'components/Button'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import Loading from 'components/Loading'
|
||||
import useMangoStore from 'stores/useMangoStore'
|
||||
import { useWallet } from '@solana/wallet-adapter-react'
|
||||
|
||||
const MenuButton: React.FC<{
|
||||
onClick: () => void
|
||||
text: string
|
||||
disabled?: boolean
|
||||
}> = ({ onClick, text, disabled }) => {
|
||||
return (
|
||||
<div
|
||||
className={`default-transition flex items-center justify-end whitespace-nowrap pb-2.5 text-xs tracking-wider hover:cursor-pointer hover:text-th-primary ${
|
||||
disabled ? 'pointer-events-none text-th-fgd-4' : 'text-th-fgd-1'
|
||||
}`}
|
||||
onClick={disabled ? () => null : onClick}
|
||||
>
|
||||
{text}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const RedeemDropdown: React.FC = () => {
|
||||
const { t } = useTranslation('common')
|
||||
const [settling, setSettling] = useState(false)
|
||||
const { wallet } = useWallet()
|
||||
const [settlingPosPnl, setSettlingPosPnl] = useState(false)
|
||||
const [open, setOpen] = useState(false)
|
||||
const unsettledPositions =
|
||||
useMangoStore.getState().selectedMangoAccount.unsettledPerpPositions
|
||||
const unsettledPositivePositions = useMangoStore
|
||||
.getState()
|
||||
.selectedMangoAccount.unsettledPerpPositions?.filter(
|
||||
(p) => p.unsettledPnl > 0
|
||||
)
|
||||
|
||||
const loading = settling || settlingPosPnl
|
||||
|
||||
const handleSettleAll = async () => {
|
||||
if (!wallet) return
|
||||
setOpen(false)
|
||||
setSettling(true)
|
||||
try {
|
||||
await settleAllPnl(unsettledPositions.map((p) => p.perpMarket), t, undefined, wallet)
|
||||
} finally {
|
||||
setSettling(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleSettlePosPnl = async () => {
|
||||
if (!wallet) return
|
||||
setOpen(false)
|
||||
setSettlingPosPnl(true)
|
||||
try {
|
||||
await settlePosPnl(unsettledPositivePositions.map((p) => p.perpMarket), t, undefined, wallet)
|
||||
} finally {
|
||||
setSettlingPosPnl(false)
|
||||
}
|
||||
}
|
||||
|
||||
const buttons = [
|
||||
{ onClick: handleSettleAll, disabled: false, text: t('redeem-all') },
|
||||
{
|
||||
onClick: handleSettlePosPnl,
|
||||
disabled: !unsettledPositivePositions?.length,
|
||||
text: t('redeem-positive'),
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<div
|
||||
className="relative"
|
||||
onMouseOver={() => setOpen(true)}
|
||||
onMouseOut={() => setOpen(false)}
|
||||
>
|
||||
<Button
|
||||
className="flex h-8 w-full items-center justify-center rounded-full bg-th-bkg-button pt-0 pb-0 pl-3 pr-2 text-xs font-bold hover:brightness-[1.1] hover:filter sm:w-auto"
|
||||
disabled={!unsettledPositions?.length}
|
||||
>
|
||||
{loading ? (
|
||||
<Loading />
|
||||
) : (
|
||||
<>
|
||||
{t('redeem-pnl')}
|
||||
<ChevronDownIcon
|
||||
className={`default-transition h-5 w-5 ${
|
||||
open ? 'rotate-180 transform' : 'rotate-360 transform'
|
||||
}`}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
<Transition
|
||||
appear={true}
|
||||
show={open}
|
||||
as={Fragment}
|
||||
enter="transition-all ease-in duration-200"
|
||||
enterFrom="opacity-0 transform scale-75"
|
||||
enterTo="opacity-100 transform scale-100"
|
||||
leave="transition ease-out duration-200"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="absolute right-0 rounded-md bg-th-bkg-3 px-4 pt-2.5">
|
||||
{buttons.map((b) => {
|
||||
return (
|
||||
<MenuButton
|
||||
key={b.text}
|
||||
onClick={b.onClick}
|
||||
text={b.text}
|
||||
disabled={b.disabled}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
export * from './RedeemDropdown'
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useCallback, useEffect, useState } from 'react'
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import Link from 'next/link'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
|
@ -20,7 +20,7 @@ import ShareModal from './ShareModal'
|
|||
import { TwitterIcon } from './icons'
|
||||
import { marketSelector } from '../stores/selectors'
|
||||
import { useWallet } from '@solana/wallet-adapter-react'
|
||||
import { RedeemDropdown } from 'components/PerpPositions'
|
||||
import RedeemButtons from './RedeemButtons'
|
||||
|
||||
const PositionsTable: React.FC = () => {
|
||||
const { t } = useTranslation('common')
|
||||
|
@ -85,17 +85,35 @@ const PositionsTable: React.FC = () => {
|
|||
}
|
||||
}
|
||||
|
||||
const unsettledSum = useMemo(() => {
|
||||
if (unsettledPositions.length > 1) {
|
||||
return unsettledPositions.reduce((a, c) => a + c.unsettledPnl, 0)
|
||||
}
|
||||
return
|
||||
}, [unsettledPositions])
|
||||
|
||||
return (
|
||||
<div className="flex flex-col md:pb-2">
|
||||
{unsettledPositions.length > 0 ? (
|
||||
<div className="mb-6 rounded-lg border border-th-bkg-4 p-4 sm:p-6">
|
||||
<div className="flex items-center justify-between pb-4">
|
||||
<div className="flex items-start justify-between pb-4">
|
||||
<div className="flex items-center">
|
||||
<ExclamationIcon className="mr-1.5 mt-0.5 h-5 w-5 flex-shrink-0 text-th-primary" />
|
||||
<h3>{t('unsettled-positions')}</h3>
|
||||
<ExclamationIcon className="mr-2 h-6 w-6 flex-shrink-0 text-th-primary" />
|
||||
<h3>
|
||||
{t('unsettled-positions')}{' '}
|
||||
{unsettledSum ? (
|
||||
<div
|
||||
className={
|
||||
unsettledSum >= 0 ? 'text-th-green' : 'text-th-red'
|
||||
}
|
||||
>
|
||||
{formatUsdValue(unsettledSum)}
|
||||
</div>
|
||||
) : null}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<RedeemDropdown />
|
||||
<RedeemButtons />
|
||||
</div>
|
||||
<div className="grid grid-flow-row grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3">
|
||||
{unsettledPositions.map((p, index) => {
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
import React, { useMemo, useState } from 'react'
|
||||
import { settleAllPnl, settlePosPnl } from 'components/MarketPosition'
|
||||
import Button from 'components/Button'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import Loading from 'components/Loading'
|
||||
import useMangoStore from 'stores/useMangoStore'
|
||||
import { useWallet } from '@solana/wallet-adapter-react'
|
||||
|
||||
const RedeemButtons: React.FC = () => {
|
||||
const { t } = useTranslation('common')
|
||||
const [settling, setSettling] = useState(false)
|
||||
const { wallet } = useWallet()
|
||||
const [settlingPosPnl, setSettlingPosPnl] = useState(false)
|
||||
const unsettledPositions =
|
||||
useMangoStore.getState().selectedMangoAccount.unsettledPerpPositions
|
||||
const unsettledPositivePositions = useMangoStore
|
||||
.getState()
|
||||
.selectedMangoAccount.unsettledPerpPositions?.filter(
|
||||
(p) => p.unsettledPnl > 0
|
||||
)
|
||||
|
||||
const handleSettleAll = async () => {
|
||||
if (!wallet) return
|
||||
setSettling(true)
|
||||
try {
|
||||
await settleAllPnl(
|
||||
unsettledPositions.map((p) => p.perpMarket),
|
||||
t,
|
||||
undefined,
|
||||
wallet
|
||||
)
|
||||
} finally {
|
||||
setSettling(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleSettlePosPnl = async () => {
|
||||
if (!wallet) return
|
||||
setSettlingPosPnl(true)
|
||||
try {
|
||||
await settlePosPnl(
|
||||
unsettledPositivePositions.map((p) => p.perpMarket),
|
||||
t,
|
||||
undefined,
|
||||
wallet
|
||||
)
|
||||
} finally {
|
||||
setSettlingPosPnl(false)
|
||||
}
|
||||
}
|
||||
|
||||
const showPosOnlyButton = useMemo(() => {
|
||||
return (
|
||||
unsettledPositions.find((pos) => pos.unsettledPnl > 0) &&
|
||||
unsettledPositions.find((pos) => pos.unsettledPnl < 0)
|
||||
)
|
||||
}, [unsettledPositions])
|
||||
|
||||
return unsettledPositions?.length ? (
|
||||
<div className="flex space-x-3">
|
||||
{showPosOnlyButton ? (
|
||||
<Button
|
||||
className="flex h-7 items-center justify-center pt-0 pb-0 pl-3 pr-3 text-xs"
|
||||
onClick={handleSettlePosPnl}
|
||||
>
|
||||
{settlingPosPnl ? <Loading /> : t('redeem-positive')}
|
||||
</Button>
|
||||
) : null}
|
||||
<Button
|
||||
className="flex h-7 items-center justify-center pt-0 pb-0 pl-3 pr-3 text-xs"
|
||||
onClick={handleSettleAll}
|
||||
>
|
||||
{settling ? <Loading /> : t('redeem-all')}
|
||||
</Button>
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
|
||||
export default RedeemButtons
|
|
@ -328,7 +328,7 @@
|
|||
"redeem-all": "Redeem All",
|
||||
"redeem-failure": "Error redeeming MNGO",
|
||||
"redeem-pnl": "Redeem",
|
||||
"redeem-positive": "Redeem positive",
|
||||
"redeem-positive": "Redeem Positive",
|
||||
"redeem-success": "Successfully redeemed MNGO",
|
||||
"referrals": "Referrals",
|
||||
"refresh": "Refresh",
|
||||
|
|
|
@ -328,7 +328,7 @@
|
|||
"redeem-all": "Redeem All",
|
||||
"redeem-failure": "Error al canjear MNGO",
|
||||
"redeem-pnl": "Resolver",
|
||||
"redeem-positive": "Redeem positive",
|
||||
"redeem-positive": "Redeem Positive",
|
||||
"redeem-success": "MNGO canjeado con éxito",
|
||||
"referrals": "Referencias",
|
||||
"refresh": "Actualizar",
|
||||
|
|
Loading…
Reference in New Issue