ui for swap limit orders
This commit is contained in:
parent
2e4852e965
commit
b548e7f61e
|
@ -7,6 +7,7 @@ interface SelectProps {
|
|||
onChange: (x: string) => void
|
||||
children: ReactNode
|
||||
className?: string
|
||||
buttonClassName?: string
|
||||
dropdownPanelClassName?: string
|
||||
placeholder?: string
|
||||
disabled?: boolean
|
||||
|
@ -17,6 +18,7 @@ const Select = ({
|
|||
onChange,
|
||||
children,
|
||||
className,
|
||||
buttonClassName,
|
||||
dropdownPanelClassName,
|
||||
placeholder = 'Select',
|
||||
disabled = false,
|
||||
|
@ -27,7 +29,7 @@ const Select = ({
|
|||
{({ open }) => (
|
||||
<>
|
||||
<Listbox.Button
|
||||
className={`h-full w-full rounded-md bg-th-input-bkg py-2.5 font-normal ring-1 ring-inset ring-th-input-border focus:outline-none focus-visible:ring-th-fgd-4 md:hover:ring-th-input-border-hover`}
|
||||
className={`h-full w-full rounded-md bg-th-input-bkg py-2.5 font-normal ring-1 ring-inset ring-th-input-border focus:outline-none focus-visible:ring-th-fgd-4 md:hover:ring-th-input-border-hover ${buttonClassName}`}
|
||||
>
|
||||
<div
|
||||
className={`flex items-center justify-between space-x-2 px-3 text-th-fgd-1`}
|
||||
|
|
|
@ -48,6 +48,8 @@ import SwapSettings from './SwapSettings'
|
|||
import InlineNotification from '@components/shared/InlineNotification'
|
||||
import useUnownedAccount from 'hooks/useUnownedAccount'
|
||||
import Tooltip from '@components/shared/Tooltip'
|
||||
import TabUnderline from '@components/shared/TabUnderline'
|
||||
import Select from '@components/forms/Select'
|
||||
|
||||
const MAX_DIGITS = 11
|
||||
export const withValueLimit = (values: NumberFormatValues): boolean => {
|
||||
|
@ -57,10 +59,16 @@ export const withValueLimit = (values: NumberFormatValues): boolean => {
|
|||
}
|
||||
|
||||
const NUMBER_FORMAT_CLASSNAMES =
|
||||
'w-full rounded-lg rounded-l-none border border-th-input-border bg-th-input-bkg p-3 text-right font-mono text-xl text-th-fgd-1 focus:border-th-fgd-4 focus:outline-none md:hover:border-th-input-border-hover md:hover:focus-visible:border-th-fgd-4'
|
||||
'w-full rounded-lg rounded-l-none h-[54px] border-l border-th-bkg-2 bg-th-input-bkg p-3 text-right font-mono text-xl text-th-fgd-1 focus:outline-none md:hover:border-th-input-border-hover focus-visible:bg-th-bkg-3'
|
||||
|
||||
const set = mangoStore.getState().set
|
||||
|
||||
export const ORDER_TYPES = [
|
||||
'trade:limit',
|
||||
'trade:stop-market',
|
||||
'trade:stop-limit',
|
||||
]
|
||||
|
||||
const SwapForm = () => {
|
||||
const { t } = useTranslation(['common', 'swap', 'trade'])
|
||||
//initial state is undefined null is returned on error
|
||||
|
@ -69,6 +77,8 @@ const SwapForm = () => {
|
|||
const [showTokenSelect, setShowTokenSelect] = useState<'input' | 'output'>()
|
||||
const [showSettings, setShowSettings] = useState(false)
|
||||
const [showConfirm, setShowConfirm] = useState(false)
|
||||
const [orderType, setOrderType] = useState(ORDER_TYPES[0])
|
||||
const [activeTab, setActiveTab] = useState('swap')
|
||||
const { group } = useMangoGroup()
|
||||
const [swapFormSizeUi] = useLocalStorageState(SIZE_INPUT_UI_KEY, 'slider')
|
||||
const { ipAllowed, ipCountry } = useIpAddress()
|
||||
|
@ -277,7 +287,7 @@ const SwapForm = () => {
|
|||
return (
|
||||
<ContentBox
|
||||
hidePadding
|
||||
className="relative overflow-hidden border-x-0 md:border-l md:border-r-0 md:border-t-0 md:border-b-0"
|
||||
className="relative overflow-hidden border-x-0 bg-th-bkg-1 md:border-l md:border-r-0 md:border-t-0 md:border-b-0"
|
||||
>
|
||||
<div>
|
||||
<Transition
|
||||
|
@ -320,7 +330,14 @@ const SwapForm = () => {
|
|||
>
|
||||
<SwapSettings onClose={() => setShowSettings(false)} />
|
||||
</EnterBottomExitBottom>
|
||||
<div className="relative p-6 pt-10">
|
||||
<div className="relative p-6">
|
||||
<div className="mb-6">
|
||||
<TabUnderline
|
||||
activeValue={activeTab}
|
||||
values={['swap', 'trade:limit']}
|
||||
onChange={(v) => setActiveTab(v)}
|
||||
/>
|
||||
</div>
|
||||
<div className="absolute right-4 top-4">
|
||||
<IconButton
|
||||
className="text-th-fgd-3"
|
||||
|
@ -330,16 +347,21 @@ const SwapForm = () => {
|
|||
<Cog8ToothIcon className="h-5 w-5" />
|
||||
</IconButton>
|
||||
</div>
|
||||
<div className="mb-2 flex items-end justify-between">
|
||||
<p className="text-th-fgd-2 lg:text-base">{t('swap:pay')}</p>
|
||||
{!isUnownedAccount ? (
|
||||
<MaxSwapAmount
|
||||
useMargin={useMargin}
|
||||
setAmountIn={(v) => setAmountInFormValue(v, true)}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="mb-3 grid grid-cols-2" id="swap-step-two">
|
||||
<div
|
||||
className={`grid grid-cols-2 ${
|
||||
activeTab === 'trade:limit' ? 'rounded-t-xl' : 'rounded-xl'
|
||||
} bg-th-bkg-2 p-3`}
|
||||
id="swap-step-two"
|
||||
>
|
||||
<div className="col-span-2 mb-2 flex items-center justify-between">
|
||||
<p className="text-th-fgd-2">{t('sell')}</p>
|
||||
{!isUnownedAccount ? (
|
||||
<MaxSwapAmount
|
||||
useMargin={useMargin}
|
||||
setAmountIn={(v) => setAmountInFormValue(v, true)}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="col-span-1">
|
||||
<TokenSelect
|
||||
bank={
|
||||
|
@ -350,7 +372,7 @@ const SwapForm = () => {
|
|||
type="input"
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-1 flex h-[54px]">
|
||||
<div className="col-span-1">
|
||||
<NumberFormat
|
||||
inputMode="decimal"
|
||||
thousandSeparator=","
|
||||
|
@ -367,9 +389,73 @@ const SwapForm = () => {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="-mb-2 flex justify-center">
|
||||
{activeTab === 'trade:limit' ? (
|
||||
<div
|
||||
className={`grid ${
|
||||
orderType === 'trade:stop-limit' ? 'grid-cols-3' : 'grid-cols-2'
|
||||
} gap-2 rounded-b-xl bg-th-bkg-2 p-3 pt-1`}
|
||||
id="swap-step-two"
|
||||
>
|
||||
<div className="col-span-1">
|
||||
<p className="mb-2 text-th-fgd-2">{t('trade:order-type')}</p>
|
||||
<Select
|
||||
value={t(orderType)}
|
||||
onChange={(type) => setOrderType(type)}
|
||||
className="w-full"
|
||||
buttonClassName="ring-0 rounded-t-lg rounded-b-lg"
|
||||
>
|
||||
{ORDER_TYPES.map((type) => (
|
||||
<Select.Option key={type} value={type}>
|
||||
{t(type)}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
<div className="col-span-1">
|
||||
<p className="mb-2 text-th-fgd-2">
|
||||
{orderType === 'trade:limit'
|
||||
? t('trade:limit-price')
|
||||
: t('trade:trigger-price')}
|
||||
</p>
|
||||
<NumberFormat
|
||||
inputMode="decimal"
|
||||
thousandSeparator=","
|
||||
allowNegative={false}
|
||||
isNumericString={true}
|
||||
decimalScale={inputBank?.mintDecimals || 6}
|
||||
name="amountIn"
|
||||
id="amountIn"
|
||||
className="h-10 w-full rounded-lg bg-th-input-bkg p-3 text-right font-mono text-sm text-th-fgd-1 focus:border-th-fgd-4 focus:outline-none md:hover:border-th-input-border-hover md:hover:focus-visible:bg-th-bkg-3"
|
||||
placeholder="0.00"
|
||||
value={amountInFormValue}
|
||||
onValueChange={handleAmountInChange}
|
||||
isAllowed={withValueLimit}
|
||||
/>
|
||||
</div>
|
||||
{orderType === 'trade:stop-limit' ? (
|
||||
<div className="col-span-1">
|
||||
<p className="mb-2 text-th-fgd-2">{t('trade:limit-price')}</p>
|
||||
<NumberFormat
|
||||
inputMode="decimal"
|
||||
thousandSeparator=","
|
||||
allowNegative={false}
|
||||
isNumericString={true}
|
||||
decimalScale={inputBank?.mintDecimals || 6}
|
||||
name="amountIn"
|
||||
id="amountIn"
|
||||
className="h-10 w-full rounded-lg bg-th-input-bkg p-3 text-right font-mono text-sm text-th-fgd-1 focus:border-th-fgd-4 focus:outline-none md:hover:border-th-input-border-hover md:hover:focus-visible:bg-th-bkg-3"
|
||||
placeholder="0.00"
|
||||
value={amountInFormValue}
|
||||
onValueChange={handleAmountInChange}
|
||||
isAllowed={withValueLimit}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
<div className="my-2 flex justify-center">
|
||||
<button
|
||||
className="rounded-full border border-th-bkg-4 p-1.5 text-th-fgd-3 focus-visible:border-th-fgd-4 md:hover:text-th-active"
|
||||
className="rounded-full border border-th-fgd-4 p-1.5 text-th-fgd-3 focus-visible:border-th-active md:hover:border-th-active md:hover:text-th-active"
|
||||
onClick={handleSwitchTokens}
|
||||
>
|
||||
<ArrowDownIcon
|
||||
|
@ -382,8 +468,11 @@ const SwapForm = () => {
|
|||
/>
|
||||
</button>
|
||||
</div>
|
||||
<p className="mb-2 text-th-fgd-2 lg:text-base">{t('swap:receive')}</p>
|
||||
<div id="swap-step-three" className="mb-3 grid grid-cols-2">
|
||||
<div
|
||||
id="swap-step-three"
|
||||
className="mb-3 grid grid-cols-2 rounded-xl bg-th-bkg-2 p-3"
|
||||
>
|
||||
<p className="col-span-2 mb-2 text-th-fgd-2">{t('buy')}</p>
|
||||
<div className="col-span-1">
|
||||
<TokenSelect
|
||||
bank={
|
||||
|
@ -394,7 +483,7 @@ const SwapForm = () => {
|
|||
type="output"
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-1 flex h-[54px]">
|
||||
<div className="col-span-1">
|
||||
{loadingSwapDetails ? (
|
||||
<div className="flex w-full items-center justify-center rounded-l-none rounded-r-lg border border-th-input-border bg-th-bkg-2">
|
||||
<Loading />
|
||||
|
|
|
@ -390,7 +390,7 @@ const SwapTokenChart = () => {
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-2 h-40 w-auto md:h-72">
|
||||
<div className="mt-2 h-40 w-auto md:h-96">
|
||||
<div className="absolute top-[2px] right-0 -mb-2 flex items-center justify-end space-x-4">
|
||||
<Tooltip
|
||||
content={
|
||||
|
|
|
@ -31,7 +31,7 @@ const TokenSelect = ({ bank, showTokenList, type }: TokenSelectProps) => {
|
|||
return (
|
||||
<button
|
||||
onClick={() => showTokenList(type)}
|
||||
className="flex h-full w-full items-center rounded-lg rounded-r-none border border-r-0 border-th-input-border bg-th-input-bkg py-2 px-3 text-th-fgd-2 focus-visible:bg-th-bkg-2 md:hover:cursor-pointer md:hover:bg-th-bkg-2 md:hover:text-th-fgd-1"
|
||||
className="flex h-[54px] w-full items-center rounded-lg rounded-r-none bg-th-input-bkg py-2 px-3 text-th-fgd-2 focus-visible:bg-th-bkg-3 md:hover:cursor-pointer md:hover:bg-th-bkg-1 md:hover:text-th-fgd-1"
|
||||
>
|
||||
<div className="mr-2.5 flex min-w-[24px] items-center">
|
||||
{logoURI ? (
|
||||
|
|
|
@ -74,6 +74,8 @@
|
|||
"size": "Size",
|
||||
"spread": "Spread",
|
||||
"stable-price": "Stable Price",
|
||||
"stop-limit": "Stop Limit",
|
||||
"stop-market": "Stop Market",
|
||||
"taker": "Taker",
|
||||
"taker-fee": "Taker Fee",
|
||||
"tick-size": "Tick Size",
|
||||
|
@ -88,6 +90,7 @@
|
|||
"tooltip-stable-price": "Stable price is used in a safety mechanism that limits a user's ability to enter risky positions when the oracle price is changing rapidly",
|
||||
"trade-sounds-tooltip": "Play a sound alert for every new trade",
|
||||
"trades": "Trades",
|
||||
"trigger-price": "Trigger Price",
|
||||
"tweet-position": "Share to Twitter",
|
||||
"unsettled": "Unsettled",
|
||||
"volume-alert": "Volume Alert",
|
||||
|
|
|
@ -74,6 +74,8 @@
|
|||
"size": "Size",
|
||||
"spread": "Spread",
|
||||
"stable-price": "Stable Price",
|
||||
"stop-limit": "Stop Limit",
|
||||
"stop-market": "Stop Market",
|
||||
"taker": "Taker",
|
||||
"taker-fee": "Taker Fee",
|
||||
"tick-size": "Tick Size",
|
||||
|
@ -88,6 +90,7 @@
|
|||
"tooltip-stable-price": "Stable price is used in a safety mechanism that limits a user's ability to enter risky positions when the oracle price is changing rapidly",
|
||||
"trade-sounds-tooltip": "Play a sound alert for every new trade",
|
||||
"trades": "Trades",
|
||||
"trigger-price": "Trigger Price",
|
||||
"tweet-position": "Share to Twitter",
|
||||
"unsettled": "Unsettled",
|
||||
"volume-alert": "Volume Alert",
|
||||
|
|
|
@ -74,6 +74,8 @@
|
|||
"size": "Size",
|
||||
"spread": "Spread",
|
||||
"stable-price": "Stable Price",
|
||||
"stop-limit": "Stop Limit",
|
||||
"stop-market": "Stop Market",
|
||||
"taker": "Taker",
|
||||
"taker-fee": "Taker Fee",
|
||||
"tick-size": "Tick Size",
|
||||
|
@ -88,6 +90,7 @@
|
|||
"tooltip-stable-price": "Stable price is used in a safety mechanism that limits a user's ability to enter risky positions when the oracle price is changing rapidly",
|
||||
"trade-sounds-tooltip": "Play a sound alert for every new trade",
|
||||
"trades": "Trades",
|
||||
"trigger-price": "Trigger Price",
|
||||
"tweet-position": "Share to Twitter",
|
||||
"unsettled": "Unsettled",
|
||||
"volume-alert": "Volume Alert",
|
||||
|
|
|
@ -73,6 +73,8 @@
|
|||
"size": "數量",
|
||||
"spread": "差價",
|
||||
"stable-price": "穩定價格",
|
||||
"stop-limit": "Stop Limit",
|
||||
"stop-market": "Stop Market",
|
||||
"taker": "吃單者",
|
||||
"tick-size": "波動單位",
|
||||
"tooltip-borrow-balance": "You'll use your {{balance}} {{token}} balance and borrow {{borrowAmount}} {{token}} to execute this trade. The current {{token}} variable borrow rate is {{rate}}%",
|
||||
|
@ -87,6 +89,7 @@
|
|||
"trade-sounds-tooltip": "為每筆新交易播放警報聲音",
|
||||
"trades": "交易",
|
||||
"tweet-position": "分享至Twitter",
|
||||
"trigger-price": "Trigger Price",
|
||||
"unsettled": "未結清",
|
||||
"volume-alert": "交易量警報",
|
||||
"volume-alert-desc": "交易量超過警報設定時播放聲音"
|
||||
|
|
|
@ -74,6 +74,8 @@
|
|||
"size": "數量",
|
||||
"spread": "差價",
|
||||
"stable-price": "穩定價格",
|
||||
"stop-limit": "Stop Limit",
|
||||
"stop-market": "Stop Market",
|
||||
"taker": "吃單者",
|
||||
"taker-fee": "吃單者 Fee",
|
||||
"tick-size": "波動單位",
|
||||
|
@ -88,6 +90,7 @@
|
|||
"tooltip-volume-alert": "交易量警報設定",
|
||||
"trade-sounds-tooltip": "為每筆新交易播放警報聲音",
|
||||
"trades": "交易",
|
||||
"trigger-price": "Trigger Price",
|
||||
"tweet-position": "分享至Twitter",
|
||||
"unsettled": "未結清",
|
||||
"volume-alert": "交易量警報",
|
||||
|
|
Loading…
Reference in New Issue