form validation
This commit is contained in:
parent
8ed973a063
commit
6337b696e7
|
@ -59,7 +59,11 @@ const fetchFundingTotals = async (mangoAccountPk: string) => {
|
|||
|
||||
const stats: TotalAccountFundingItem[] = entries
|
||||
.map(([key, value]) => {
|
||||
return { ...value, market: key }
|
||||
return {
|
||||
long_funding: value.long_funding * -1,
|
||||
short_funding: value.short_funding * -1,
|
||||
market: key,
|
||||
}
|
||||
})
|
||||
.filter((x) => x)
|
||||
|
||||
|
@ -208,7 +212,7 @@ const AccountPage = () => {
|
|||
const interestTotalValue = useMemo(() => {
|
||||
if (totalInterestData.length) {
|
||||
return totalInterestData.reduce(
|
||||
(a, c) => a + c.borrow_interest_usd + c.deposit_interest_usd,
|
||||
(a, c) => a + (c.borrow_interest_usd * -1 + c.deposit_interest_usd),
|
||||
0
|
||||
)
|
||||
}
|
||||
|
|
|
@ -2,20 +2,21 @@ import ButtonGroup from '@components/forms/ButtonGroup'
|
|||
import Checkbox from '@components/forms/Checkbox'
|
||||
import Input from '@components/forms/Input'
|
||||
import Label from '@components/forms/Label'
|
||||
import Button, { LinkButton } from '@components/shared/Button'
|
||||
import Button, { IconButton, LinkButton } from '@components/shared/Button'
|
||||
import InlineNotification from '@components/shared/InlineNotification'
|
||||
import Modal from '@components/shared/Modal'
|
||||
import { Table, Td, Th, TrBody, TrHead } from '@components/shared/TableElements'
|
||||
import Tooltip from '@components/shared/Tooltip'
|
||||
import { KeyIcon } from '@heroicons/react/20/solid'
|
||||
import { KeyIcon, TrashIcon } from '@heroicons/react/20/solid'
|
||||
import useLocalStorageState from 'hooks/useLocalStorageState'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { useState } from 'react'
|
||||
import { ModalProps } from 'types/modal'
|
||||
import { HOT_KEYS_KEY } from 'utils/constants'
|
||||
|
||||
export type HotKey = {
|
||||
ioc: boolean
|
||||
keySequence: string
|
||||
// market: string
|
||||
margin: boolean
|
||||
orderSide: 'buy' | 'sell'
|
||||
orderSizeType: 'percentage' | 'notional'
|
||||
|
@ -28,25 +29,96 @@ export type HotKey = {
|
|||
|
||||
const HotKeysSettings = () => {
|
||||
const { t } = useTranslation('settings')
|
||||
const [hotKeys] = useLocalStorageState(HOT_KEYS_KEY, [])
|
||||
const [hotKeys, setHotKeys] = useLocalStorageState(HOT_KEYS_KEY, [])
|
||||
const [showHotKeyModal, setShowHotKeyModal] = useState(false)
|
||||
|
||||
const handleDeleteKey = (key: string) => {
|
||||
const newKeys = hotKeys.filter((hk: HotKey) => hk.keySequence !== key)
|
||||
setHotKeys([...newKeys])
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="mb-1 text-base">{t('hot-keys')}</h2>
|
||||
<LinkButton onClick={() => setShowHotKeyModal(true)}>
|
||||
Create New Hot Key
|
||||
</LinkButton>
|
||||
{hotKeys.length ? (
|
||||
<LinkButton onClick={() => setShowHotKeyModal(true)}>
|
||||
{t('create-new-key')}
|
||||
</LinkButton>
|
||||
) : null}
|
||||
</div>
|
||||
<p className="mb-4">{t('hot-keys-desc')}</p>
|
||||
{hotKeys.length ? (
|
||||
hotKeys.map((k: HotKey) => (
|
||||
<div key={k.keySequence}>
|
||||
<p>{k.keySequence}</p>
|
||||
</div>
|
||||
))
|
||||
<Table>
|
||||
<thead>
|
||||
<TrHead>
|
||||
<Th className="text-left">{t('key')}</Th>
|
||||
<Th className="text-right">{t('order-type')}</Th>
|
||||
<Th className="text-right">{t('side')}</Th>
|
||||
<Th className="text-right">{t('size')}</Th>
|
||||
<Th className="text-right">{t('price')}</Th>
|
||||
<Th className="text-right">{t('options')}</Th>
|
||||
<Th />
|
||||
</TrHead>
|
||||
</thead>
|
||||
<tbody>
|
||||
{hotKeys.map((hk: HotKey) => {
|
||||
const {
|
||||
keySequence,
|
||||
orderSide,
|
||||
orderPrice,
|
||||
orderSize,
|
||||
orderSizeType,
|
||||
orderType,
|
||||
ioc,
|
||||
margin,
|
||||
reduceOnly,
|
||||
postOnly,
|
||||
} = hk
|
||||
const size =
|
||||
orderSizeType === 'percentage'
|
||||
? `${orderSize}% of max`
|
||||
: `$${orderSize}`
|
||||
const price = orderPrice ? `${orderPrice}% from oracle` : 'market'
|
||||
|
||||
const options = {
|
||||
margin: margin,
|
||||
IOC: ioc,
|
||||
post: postOnly,
|
||||
reduce: reduceOnly,
|
||||
}
|
||||
|
||||
return (
|
||||
<TrBody key={keySequence} className="text-right">
|
||||
<Td className="text-left">{keySequence}</Td>
|
||||
<Td className="text-right">{orderType}</Td>
|
||||
<Td className="text-right">{orderSide}</Td>
|
||||
<Td className="text-right">{size}</Td>
|
||||
<Td className="text-right">{price}</Td>
|
||||
<Td className="text-right">
|
||||
{Object.entries(options).map((e) => {
|
||||
return e[1]
|
||||
? `${e[0] !== 'margin' ? ', ' : ''}${e[0]}`
|
||||
: ''
|
||||
})}
|
||||
</Td>
|
||||
<Td>
|
||||
<div className="flex justify-end">
|
||||
<IconButton
|
||||
onClick={() => handleDeleteKey(keySequence)}
|
||||
size="small"
|
||||
>
|
||||
<TrashIcon className="h-4 w-4" />
|
||||
</IconButton>
|
||||
</div>
|
||||
</Td>
|
||||
</TrBody>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</Table>
|
||||
) : (
|
||||
<div className="mb-8 rounded-lg border border-th-bkg-3 p-6">
|
||||
<div className="rounded-lg border border-th-bkg-3 p-6">
|
||||
<div className="flex flex-col items-center">
|
||||
<KeyIcon className="mb-2 h-6 w-6 text-th-fgd-4" />
|
||||
<p className="mb-4">{t('no-hot-keys')}</p>
|
||||
|
@ -68,151 +140,243 @@ const HotKeysSettings = () => {
|
|||
|
||||
export default HotKeysSettings
|
||||
|
||||
// add ioc, postOnly and reduceOnly checkboxes
|
||||
type FormErrors = Partial<Record<keyof HotKeyForm, string>>
|
||||
|
||||
type HotKeyForm = {
|
||||
baseKey: string
|
||||
triggerKey: string
|
||||
price: string
|
||||
side: 'buy' | 'sell'
|
||||
size: string
|
||||
sizeType: 'percentage' | 'notional'
|
||||
orderType: 'limit' | 'market'
|
||||
ioc: boolean
|
||||
post: boolean
|
||||
margin: boolean
|
||||
reduce: boolean
|
||||
}
|
||||
|
||||
const DEFAULT_FORM_VALUES: HotKeyForm = {
|
||||
baseKey: 'shift',
|
||||
triggerKey: '',
|
||||
price: '',
|
||||
side: 'buy',
|
||||
size: '',
|
||||
sizeType: 'percentage',
|
||||
orderType: 'limit',
|
||||
ioc: false,
|
||||
post: false,
|
||||
margin: false,
|
||||
reduce: false,
|
||||
}
|
||||
|
||||
const HotKeyModal = ({ isOpen, onClose }: ModalProps) => {
|
||||
const { t } = useTranslation(['settings', 'trade'])
|
||||
const [hotKeys, setHotKeys] = useLocalStorageState<HotKey[]>(HOT_KEYS_KEY, [])
|
||||
// const perpMarkets = mangoStore((s) => s.perpMarkets)
|
||||
// const serumMarkets = mangoStore((s) => s.serumMarkets)
|
||||
// const allMarkets =
|
||||
// perpMarkets.length && serumMarkets.length
|
||||
// ? [
|
||||
// 'All',
|
||||
// ...perpMarkets.map((m) => m.name),
|
||||
// ...serumMarkets.map((m) => m.name),
|
||||
// ]
|
||||
// : ['All']
|
||||
const [keySequence, setKeySequence] = useState('')
|
||||
// const [market, setMarket] = useState('All')
|
||||
const [orderPrice, setOrderPrice] = useState('')
|
||||
const [orderSide, setOrderSide] = useState('buy')
|
||||
const [orderSizeType, setOrderSizeType] = useState('percentage')
|
||||
const [orderSize, setOrderSize] = useState('')
|
||||
const [orderType, setOrderType] = useState('limit')
|
||||
const [postOnly, setPostOnly] = useState(false)
|
||||
const [ioc, setIoc] = useState(false)
|
||||
const [margin, setMargin] = useState(false)
|
||||
const [reduceOnly, setReduceOnly] = useState(false)
|
||||
const [hotKeyForm, setHotKeyForm] = useState<HotKeyForm>({
|
||||
...DEFAULT_FORM_VALUES,
|
||||
})
|
||||
const [formErrors, setFormErrors] = useState<FormErrors>({})
|
||||
|
||||
const handlePostOnlyChange = useCallback(
|
||||
(postOnly: boolean) => {
|
||||
let updatedIoc = ioc
|
||||
if (postOnly) {
|
||||
updatedIoc = !postOnly
|
||||
}
|
||||
setPostOnly(postOnly)
|
||||
setIoc(updatedIoc)
|
||||
},
|
||||
[ioc]
|
||||
)
|
||||
const handleSetForm = (propertyName: string, value: string | boolean) => {
|
||||
setFormErrors({})
|
||||
setHotKeyForm((prevState) => ({ ...prevState, [propertyName]: value }))
|
||||
}
|
||||
|
||||
const handleIocChange = useCallback(
|
||||
(ioc: boolean) => {
|
||||
let updatedPostOnly = postOnly
|
||||
if (ioc) {
|
||||
updatedPostOnly = !ioc
|
||||
const handlePostOnlyChange = (postOnly: boolean) => {
|
||||
if (postOnly) {
|
||||
handleSetForm('ioc', !postOnly)
|
||||
}
|
||||
handleSetForm('post', postOnly)
|
||||
}
|
||||
|
||||
const handleIocChange = (ioc: boolean) => {
|
||||
if (ioc) {
|
||||
handleSetForm('post', !ioc)
|
||||
}
|
||||
handleSetForm('ioc', ioc)
|
||||
}
|
||||
|
||||
const isFormValid = (form: HotKeyForm) => {
|
||||
const invalidFields: FormErrors = {}
|
||||
setFormErrors({})
|
||||
const triggerKey: (keyof HotKeyForm)[] = ['triggerKey']
|
||||
const requiredFields: (keyof HotKeyForm)[] = ['size', 'price', 'triggerKey']
|
||||
const numberFields: (keyof HotKeyForm)[] = ['size', 'price']
|
||||
const alphanumericRegex = /^[a-zA-Z0-9]+$/
|
||||
for (const key of triggerKey) {
|
||||
const value = form[key] as string
|
||||
if (value.length > 1) {
|
||||
invalidFields[key] = t('error-too-many-characters')
|
||||
}
|
||||
setPostOnly(updatedPostOnly)
|
||||
setIoc(ioc)
|
||||
},
|
||||
[postOnly]
|
||||
)
|
||||
if (!alphanumericRegex.test(value)) {
|
||||
invalidFields[key] = t('error-alphanumeric-only')
|
||||
}
|
||||
}
|
||||
for (const key of requiredFields) {
|
||||
const value = form[key] as string
|
||||
if (!value) {
|
||||
if (hotKeyForm.orderType === 'market') {
|
||||
console.log(key, invalidFields[key])
|
||||
if (key !== 'price') {
|
||||
invalidFields[key] = t('error-required-field')
|
||||
}
|
||||
} else {
|
||||
invalidFields[key] = t('error-required-field')
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const key of numberFields) {
|
||||
const value = form[key] as string
|
||||
if (value) {
|
||||
if (isNaN(parseFloat(value))) {
|
||||
invalidFields[key] = t('error-must-be-number')
|
||||
}
|
||||
if (parseFloat(value) < 0) {
|
||||
invalidFields[key] = t('error-must-be-above-zero')
|
||||
}
|
||||
if (parseFloat(value) > 100) {
|
||||
if (key === 'price') {
|
||||
invalidFields[key] = t('error-must-be-below-100')
|
||||
} else {
|
||||
if (hotKeyForm.sizeType === 'percentage') {
|
||||
invalidFields[key] = t('error-must-be-below-100')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Object.keys(invalidFields).length) {
|
||||
setFormErrors(invalidFields)
|
||||
}
|
||||
return invalidFields
|
||||
}
|
||||
|
||||
const handleSave = () => {
|
||||
const invalidFields = isFormValid(hotKeyForm)
|
||||
if (Object.keys(invalidFields).length) {
|
||||
return
|
||||
}
|
||||
const newHotKey = {
|
||||
keySequence: keySequence,
|
||||
// market: market,
|
||||
orderSide: orderSide,
|
||||
orderSizeType: orderSizeType,
|
||||
orderSize: orderSize,
|
||||
orderType: orderType,
|
||||
orderPrice: orderPrice,
|
||||
ioc,
|
||||
margin,
|
||||
postOnly,
|
||||
reduceOnly,
|
||||
keySequence: `${hotKeyForm.baseKey}+${hotKeyForm.triggerKey}`,
|
||||
orderSide: hotKeyForm.side,
|
||||
orderSizeType: hotKeyForm.sizeType,
|
||||
orderSize: hotKeyForm.size,
|
||||
orderType: hotKeyForm.orderType,
|
||||
orderPrice: hotKeyForm.price,
|
||||
ioc: hotKeyForm.ioc,
|
||||
margin: hotKeyForm.margin,
|
||||
postOnly: hotKeyForm.post,
|
||||
reduceOnly: hotKeyForm.reduce,
|
||||
}
|
||||
setHotKeys([...hotKeys, newHotKey])
|
||||
onClose()
|
||||
}
|
||||
|
||||
const disabled =
|
||||
!keySequence || (orderType === 'limit' && !orderPrice) || !orderSize
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClose}>
|
||||
<>
|
||||
<h2 className="mb-4 text-center">{t('create-hot-key')}</h2>
|
||||
<div className="mb-4">
|
||||
<Label text={t('key-sequence')} />
|
||||
<Input
|
||||
type="text"
|
||||
value={keySequence}
|
||||
onChange={(e) => setKeySequence(e.target.value)}
|
||||
<Label text={t('base-key')} />
|
||||
<ButtonGroup
|
||||
activeValue={hotKeyForm.baseKey}
|
||||
onChange={(key) => handleSetForm('baseKey', key)}
|
||||
values={['shift', 'ctrl', 'option']}
|
||||
/>
|
||||
</div>
|
||||
{/* <div className="mb-4">
|
||||
<Label text={t('market')} />
|
||||
<Select
|
||||
value={market}
|
||||
onChange={(market) => setMarket(market)}
|
||||
className="w-full"
|
||||
>
|
||||
{allMarkets.map((market) => (
|
||||
<Select.Option key={market} value={market}>
|
||||
<div className="w-full">{market}</div>
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</div> */}
|
||||
<div className="mb-4">
|
||||
<Label text={t('trigger-key')} />
|
||||
<Input
|
||||
hasError={formErrors.triggerKey !== undefined}
|
||||
type="text"
|
||||
value={hotKeyForm.triggerKey}
|
||||
onChange={(e) => handleSetForm('triggerKey', e.target.value)}
|
||||
/>
|
||||
{formErrors.triggerKey ? (
|
||||
<div className="mt-1">
|
||||
<InlineNotification
|
||||
type="error"
|
||||
desc={formErrors.triggerKey}
|
||||
hideBorder
|
||||
hidePadding
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<Label text={t('order-side')} />
|
||||
<ButtonGroup
|
||||
activeValue={orderSide}
|
||||
onChange={(side) => setOrderSide(side)}
|
||||
activeValue={hotKeyForm.side}
|
||||
onChange={(side) => handleSetForm('side', side)}
|
||||
values={['buy', 'sell']}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<Label text={t('order-type')} />
|
||||
<ButtonGroup
|
||||
activeValue={orderType}
|
||||
onChange={(type) => setOrderType(type)}
|
||||
activeValue={hotKeyForm.orderType}
|
||||
onChange={(type) => handleSetForm('orderType', type)}
|
||||
values={['limit', 'market']}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<Label text={t('order-size-type')} />
|
||||
<ButtonGroup
|
||||
activeValue={orderSizeType}
|
||||
onChange={(type) => setOrderSizeType(type)}
|
||||
activeValue={hotKeyForm.sizeType}
|
||||
onChange={(type) => handleSetForm('sizeType', type)}
|
||||
values={['percentage', 'notional']}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label text={t('size')} />
|
||||
<Input
|
||||
type="text"
|
||||
value={orderSize}
|
||||
onChange={(e) => setOrderSize(e.target.value)}
|
||||
suffix={orderSizeType === 'percentage' ? '%' : 'USD'}
|
||||
/>
|
||||
</div>
|
||||
{orderType === 'limit' ? (
|
||||
<div className="mt-4">
|
||||
<Tooltip content="Set a price as a percentage change from the oracle price">
|
||||
<Label className="tooltip-underline" text={t('price')} />
|
||||
</Tooltip>
|
||||
<div className="flex items-start space-x-4">
|
||||
<div className="w-full">
|
||||
<Label text={t('size')} />
|
||||
<Input
|
||||
hasError={formErrors.size !== undefined}
|
||||
type="text"
|
||||
value={orderPrice}
|
||||
onChange={(e) => setOrderPrice(e.target.value)}
|
||||
placeholder="e.g. 1%"
|
||||
suffix="%"
|
||||
value={hotKeyForm.size}
|
||||
onChange={(e) => handleSetForm('size', e.target.value)}
|
||||
suffix={hotKeyForm.sizeType === 'percentage' ? '%' : 'USD'}
|
||||
/>
|
||||
{formErrors.size ? (
|
||||
<div className="mt-1">
|
||||
<InlineNotification
|
||||
type="error"
|
||||
desc={formErrors.size}
|
||||
hideBorder
|
||||
hidePadding
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
{hotKeyForm.orderType === 'limit' ? (
|
||||
<div className="w-full">
|
||||
<Tooltip content="Set a price as a percentage change from the oracle price">
|
||||
<Label className="tooltip-underline" text={t('price')} />
|
||||
</Tooltip>
|
||||
<Input
|
||||
hasError={formErrors.price !== undefined}
|
||||
type="text"
|
||||
value={hotKeyForm.price}
|
||||
onChange={(e) => handleSetForm('price', e.target.value)}
|
||||
placeholder="e.g. 1%"
|
||||
suffix="%"
|
||||
/>
|
||||
{formErrors.price ? (
|
||||
<div className="mt-1">
|
||||
<InlineNotification
|
||||
type="error"
|
||||
desc={formErrors.price}
|
||||
hideBorder
|
||||
hidePadding
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="flex flex-wrap md:flex-nowrap">
|
||||
{orderType === 'limit' ? (
|
||||
{hotKeyForm.orderType === 'limit' ? (
|
||||
<div className="flex">
|
||||
<div className="mr-3 mt-4" id="trade-step-six">
|
||||
<Tooltip
|
||||
|
@ -221,7 +385,7 @@ const HotKeyModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
content={t('trade:tooltip-post')}
|
||||
>
|
||||
<Checkbox
|
||||
checked={postOnly}
|
||||
checked={hotKeyForm.post}
|
||||
onChange={(e) => handlePostOnlyChange(e.target.checked)}
|
||||
>
|
||||
{t('trade:post')}
|
||||
|
@ -236,7 +400,7 @@ const HotKeyModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
>
|
||||
<div className="flex items-center text-xs text-th-fgd-3">
|
||||
<Checkbox
|
||||
checked={ioc}
|
||||
checked={hotKeyForm.ioc}
|
||||
onChange={(e) => handleIocChange(e.target.checked)}
|
||||
>
|
||||
IOC
|
||||
|
@ -253,8 +417,8 @@ const HotKeyModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
content={t('trade:tooltip-enable-margin')}
|
||||
>
|
||||
<Checkbox
|
||||
checked={margin}
|
||||
onChange={(e) => setMargin(e.target.checked)}
|
||||
checked={hotKeyForm.margin}
|
||||
onChange={(e) => handleSetForm('margin', e.target.checked)}
|
||||
>
|
||||
{t('trade:margin')}
|
||||
</Checkbox>
|
||||
|
@ -270,8 +434,8 @@ const HotKeyModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
>
|
||||
<div className="flex items-center text-xs text-th-fgd-3">
|
||||
<Checkbox
|
||||
checked={reduceOnly}
|
||||
onChange={(e) => setReduceOnly(e.target.checked)}
|
||||
checked={hotKeyForm.reduce}
|
||||
onChange={(e) => handleSetForm('reduce', e.target.checked)}
|
||||
>
|
||||
{t('trade:reduce-only')}
|
||||
</Checkbox>
|
||||
|
@ -279,11 +443,7 @@ const HotKeyModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
className="mt-6 w-full"
|
||||
disabled={disabled}
|
||||
onClick={handleSave}
|
||||
>
|
||||
<Button className="mt-6 w-full" onClick={handleSave}>
|
||||
{t('save-hot-key')}
|
||||
</Button>
|
||||
</>
|
||||
|
|
|
@ -42,7 +42,7 @@ const NotificationSettings = () => {
|
|||
<h2 className="text-base">{t('settings:notifications')}</h2>
|
||||
</div>
|
||||
{isAuth ? (
|
||||
<div className="flex items-center justify-between border-t border-th-bkg-3 p-4">
|
||||
<div className="flex items-center justify-between border-y border-th-bkg-3 p-4">
|
||||
<p>{t('settings:limit-order-filled')}</p>
|
||||
<Switch
|
||||
checked={!!data?.fillsNotifications}
|
||||
|
@ -55,7 +55,7 @@ const NotificationSettings = () => {
|
|||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="mb-8 rounded-lg border border-th-bkg-3 p-6">
|
||||
<div className="rounded-lg border border-th-bkg-3 p-6">
|
||||
{connected ? (
|
||||
<div className="flex flex-col items-center">
|
||||
<BellIcon className="mb-2 h-6 w-6 text-th-fgd-4" />
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { useViewport } from 'hooks/useViewport'
|
||||
import AnimationSettings from './AnimationSettings'
|
||||
import DisplaySettings from './DisplaySettings'
|
||||
import HotKeysSettings from './HotKeysSettings'
|
||||
|
@ -5,8 +6,11 @@ import NotificationSettings from './NotificationSettings'
|
|||
import PreferredExplorerSettings from './PreferredExplorerSettings'
|
||||
import RpcSettings from './RpcSettings'
|
||||
import SoundSettings from './SoundSettings'
|
||||
import { breakpoints } from 'utils/theme'
|
||||
|
||||
const SettingsPage = () => {
|
||||
const { width } = useViewport()
|
||||
const isMobile = width ? width < breakpoints.lg : false
|
||||
return (
|
||||
<div className="grid grid-cols-12">
|
||||
<div className="col-span-12 border-b border-th-bkg-3 lg:col-span-10 lg:col-start-2 xl:col-span-8 xl:col-start-3">
|
||||
|
@ -15,12 +19,14 @@ const SettingsPage = () => {
|
|||
<div className="col-span-12 border-b border-th-bkg-3 pt-8 lg:col-span-10 lg:col-start-2 xl:col-span-8 xl:col-start-3">
|
||||
<DisplaySettings />
|
||||
</div>
|
||||
<div className="col-span-12 border-b border-th-bkg-3 pt-8 lg:col-span-10 lg:col-start-2 xl:col-span-8 xl:col-start-3">
|
||||
<div className="col-span-12 pt-8 lg:col-span-10 lg:col-start-2 xl:col-span-8 xl:col-start-3">
|
||||
<NotificationSettings />
|
||||
</div>
|
||||
<div className="col-span-12 border-b border-th-bkg-3 pt-8 lg:col-span-10 lg:col-start-2 xl:col-span-8 xl:col-start-3">
|
||||
<HotKeysSettings />
|
||||
</div>
|
||||
{!isMobile ? (
|
||||
<div className="col-span-12 pt-8 lg:col-span-10 lg:col-start-2 xl:col-span-8 xl:col-start-3">
|
||||
<HotKeysSettings />
|
||||
</div>
|
||||
) : null}
|
||||
<div className="col-span-12 border-b border-th-bkg-3 pt-8 lg:col-span-10 lg:col-start-2 xl:col-span-8 xl:col-start-3">
|
||||
<AnimationSettings />
|
||||
</div>
|
||||
|
|
|
@ -25,6 +25,7 @@ import { useSpotMarketMax } from './SpotSlider'
|
|||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import { Market } from '@project-serum/serum'
|
||||
import { useRouter } from 'next/router'
|
||||
import useUnownedAccount from 'hooks/useUnownedAccount'
|
||||
|
||||
const set = mangoStore.getState().set
|
||||
|
||||
|
@ -90,7 +91,8 @@ const TradeHotKeys = ({ children }: { children: ReactNode }) => {
|
|||
selectedMarket,
|
||||
serumOrPerpMarket,
|
||||
} = useSelectedMarket()
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const { mangoAccount, mangoAccountAddress } = useMangoAccount()
|
||||
const { isUnownedAccount } = useUnownedAccount()
|
||||
const { asPath } = useRouter()
|
||||
const [hotKeys] = useLocalStorageState(HOT_KEYS_KEY, [])
|
||||
const [placingOrder, setPlacingOrder] = useState(false)
|
||||
|
@ -139,7 +141,6 @@ const TradeHotKeys = ({ children }: { children: ReactNode }) => {
|
|||
const client = mangoStore.getState().client
|
||||
const group = mangoStore.getState().group
|
||||
const mangoAccount = mangoStore.getState().mangoAccount.current
|
||||
// const tradeForm = mangoStore.getState().tradeForm
|
||||
const actions = mangoStore.getState().actions
|
||||
const selectedMarket = mangoStore.getState().selectedMarket.current
|
||||
const { ioc, orderPrice, orderSide, orderType, postOnly, reduceOnly } =
|
||||
|
@ -303,7 +304,13 @@ const TradeHotKeys = ({ children }: { children: ReactNode }) => {
|
|||
}
|
||||
}, [placingOrder])
|
||||
|
||||
return hotKeys.length && asPath.includes('/trade') ? (
|
||||
const showHotKeys =
|
||||
hotKeys.length &&
|
||||
asPath.includes('/trade') &&
|
||||
mangoAccountAddress &&
|
||||
!isUnownedAccount
|
||||
|
||||
return showHotKeys ? (
|
||||
<Hotkeys
|
||||
keyName={hotKeys.map((k: HotKey) => k.keySequence).toString()}
|
||||
onKeyDown={onKeyDown}
|
||||
|
|
Loading…
Reference in New Issue