Compare commits

..
Author SHA1 Message Date
Bill He b26106ba20 Fix status empty bug 2023-11-09 14:07:46 -08:00
10 changed files with 96 additions and 163 deletions
+1 -7
View File
@@ -1,4 +1,4 @@
import { useEffect, useRef, useState } from 'react'; import { useState } from 'react';
import styled, { type AnyStyledComponent, css } from 'styled-components'; import styled, { type AnyStyledComponent, css } from 'styled-components';
import { layoutMixins } from '@/styles/layoutMixins'; import { layoutMixins } from '@/styles/layoutMixins';
@@ -22,11 +22,6 @@ export const SearchInput = ({
}: SearchInputProps) => { }: SearchInputProps) => {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [value, setValue] = useState(''); const [value, setValue] = useState('');
const inputRef = useRef<HTMLInputElement | null>(null);
useEffect(() => {
if (isOpen) inputRef?.current?.focus();
}, [inputRef, isOpen]);
return ( return (
<Styled.Search> <Styled.Search>
@@ -46,7 +41,6 @@ export const SearchInput = ({
/> />
<Styled.Input <Styled.Input
autoFocus autoFocus
ref={inputRef}
value={value} value={value}
isOpen={isOpen} isOpen={isOpen}
type={type} type={type}
+8 -12
View File
@@ -831,7 +831,6 @@ Styled.SortArrow = styled.span<{ sortDirection: 'ascending' | 'descending' }>`
Styled.Thead = styled.thead<StyleProps>` Styled.Thead = styled.thead<StyleProps>`
${layoutMixins.stickyHeader} ${layoutMixins.stickyHeader}
scroll-snap-align: none; scroll-snap-align: none;
font: var(--font-mini-book);
> * { > * {
height: var(--stickyArea-topHeight); height: var(--stickyArea-topHeight);
@@ -840,17 +839,18 @@ Styled.Thead = styled.thead<StyleProps>`
color: var(--tableHeader-textColor); color: var(--tableHeader-textColor);
background-color: var(--tableHeader-backgroundColor); background-color: var(--tableHeader-backgroundColor);
${({ withInnerBorders, withGradientCardRows }) => @media ${breakpoints.notTablet} {
withInnerBorders && ${({ withInnerBorders, withGradientCardRows }) =>
!withGradientCardRows && withInnerBorders &&
css` !withGradientCardRows &&
${layoutMixins.withInnerHorizontalBorders} css`
`} ${layoutMixins.withInnerHorizontalBorders}
`}
}
`; `;
Styled.Tbody = styled.tbody<StyleProps>` Styled.Tbody = styled.tbody<StyleProps>`
${layoutMixins.stickyArea2} ${layoutMixins.stickyArea2}
font: var(--font-small-book);
// If <table> height is fixed with not enough rows to overflow, vertically center the rows // If <table> height is fixed with not enough rows to overflow, vertically center the rows
&:before, &:before,
@@ -869,10 +869,6 @@ Styled.Tbody = styled.tbody<StyleProps>`
--stickyArea2-paddingBottom: var(--border-width); --stickyArea2-paddingBottom: var(--border-width);
--stickyArea2-paddingLeft: var(--border-width); --stickyArea2-paddingLeft: var(--border-width);
--stickyArea2-paddingRight: var(--border-width); --stickyArea2-paddingRight: var(--border-width);
tr:first-of-type {
box-shadow: none;
}
`} `}
${({ withGradientCardRows }) => ${({ withGradientCardRows }) =>
+2 -2
View File
@@ -136,8 +136,8 @@ const useAccountsContext = () => {
getSubaccounts: async ({ dydxAddress }: { dydxAddress: DydxAddress }) => { getSubaccounts: async ({ dydxAddress }: { dydxAddress: DydxAddress }) => {
try { try {
const response = await compositeClient?.indexerClient.account.getSubaccounts(dydxAddress); const response = await compositeClient?.indexerClient.account.getSubaccounts(dydxAddress);
setDydxSubaccounts(response?.subaccounts); setDydxSubaccounts(response.subaccounts);
return response?.subaccounts ?? []; return response.subaccounts;
} catch (error) { } catch (error) {
// 404 is expected if the user has no subaccounts // 404 is expected if the user has no subaccounts
if (error.status === 404) { if (error.status === 404) {
+4
View File
@@ -304,6 +304,10 @@ Styled.FeeTable = styled(Table)`
@media ${breakpoints.notTablet} { @media ${breakpoints.notTablet} {
--tableHeader-backgroundColor: var(--color-layer-1); --tableHeader-backgroundColor: var(--color-layer-1);
thead tr {
--border-width: 0;
}
} }
`; `;
+42 -104
View File
@@ -1,13 +1,11 @@
import { shallowEqual, useDispatch, useSelector } from 'react-redux'; import { useEffect } from 'react';
import styled, { type AnyStyledComponent } from 'styled-components'; import styled, { type AnyStyledComponent } from 'styled-components';
import { Navigate, Route, Routes } from 'react-router-dom'; import { Navigate, Route, Routes } from 'react-router-dom';
import { OnboardingState } from '@/constants/account';
import { DialogTypes } from '@/constants/dialogs';
import { STRING_KEYS } from '@/constants/localization'; import { STRING_KEYS } from '@/constants/localization';
import { HistoryRoute, PortfolioRoute } from '@/constants/routes'; import { HistoryRoute, PortfolioRoute } from '@/constants/routes';
import { useAccountBalance, useBreakpoints, useDocumentTitle, useStringGetter } from '@/hooks'; import { useBreakpoints, useDocumentTitle, useStringGetter } from '@/hooks';
import { FillsTable, FillsTableColumnKey } from '@/views/tables/FillsTable'; import { FillsTable, FillsTableColumnKey } from '@/views/tables/FillsTable';
import { FundingPaymentsTable } from '@/views/tables/FundingPaymentsTable'; import { FundingPaymentsTable } from '@/views/tables/FundingPaymentsTable';
@@ -16,9 +14,6 @@ import { Icon, IconName } from '@/components/Icon';
import { NavigationMenu } from '@/components/NavigationMenu'; import { NavigationMenu } from '@/components/NavigationMenu';
import { WithSidebar } from '@/components/WithSidebar'; import { WithSidebar } from '@/components/WithSidebar';
import { getOnboardingState, getSubaccount } from '@/state/accountSelectors';
import { openDialog } from '@/state/dialogs';
import { PortfolioNavMobile } from './PortfolioNavMobile'; import { PortfolioNavMobile } from './PortfolioNavMobile';
import { Overview } from './Overview'; import { Overview } from './Overview';
import { Positions } from './Positions'; import { Positions } from './Positions';
@@ -27,20 +22,11 @@ import { Fees } from './Fees';
import { History } from './History'; import { History } from './History';
import { layoutMixins } from '@/styles/layoutMixins'; import { layoutMixins } from '@/styles/layoutMixins';
import { Button } from '@/components/Button';
import { ButtonAction } from '@/constants/buttons';
export default () => { export default () => {
const dispatch = useDispatch();
const stringGetter = useStringGetter(); const stringGetter = useStringGetter();
const { isTablet, isNotTablet } = useBreakpoints(); const { isTablet, isNotTablet } = useBreakpoints();
const onboardingState = useSelector(getOnboardingState);
const { freeCollateral } = useSelector(getSubaccount, shallowEqual) || {};
const { nativeTokenBalance } = useAccountBalance();
const usdcBalance = freeCollateral?.current || 0;
useDocumentTitle(stringGetter({ key: STRING_KEYS.PORTFOLIO })); useDocumentTitle(stringGetter({ key: STRING_KEYS.PORTFOLIO }));
const routesComponent = ( const routesComponent = (
@@ -98,74 +84,46 @@ export default () => {
<WithSidebar <WithSidebar
sidebar={ sidebar={
isTablet ? null : ( isTablet ? null : (
<Styled.SideBar> <Styled.NavigationMenu
<Styled.NavigationMenu items={[
items={[ {
{ group: 'views',
group: 'views', groupLabel: stringGetter({ key: STRING_KEYS.VIEWS }),
groupLabel: stringGetter({ key: STRING_KEYS.VIEWS }), items: [
items: [ {
{ value: PortfolioRoute.Overview,
value: PortfolioRoute.Overview, slotBefore: <Styled.Icon iconName={IconName.Overview} />,
slotBefore: <Styled.Icon iconName={IconName.Overview} />, label: stringGetter({ key: STRING_KEYS.OVERVIEW }),
label: stringGetter({ key: STRING_KEYS.OVERVIEW }), href: PortfolioRoute.Overview,
href: PortfolioRoute.Overview, },
}, {
{ value: PortfolioRoute.Positions,
value: PortfolioRoute.Positions, slotBefore: <Styled.Icon iconName={IconName.Cube} />,
slotBefore: <Styled.Icon iconName={IconName.Cube} />, label: stringGetter({ key: STRING_KEYS.POSITIONS }),
label: stringGetter({ key: STRING_KEYS.POSITIONS }), href: PortfolioRoute.Positions,
href: PortfolioRoute.Positions, },
}, {
{ value: PortfolioRoute.Orders,
value: PortfolioRoute.Orders, slotBefore: <Styled.Icon iconName={IconName.OrderPending} />,
slotBefore: <Styled.Icon iconName={IconName.OrderPending} />, label: stringGetter({ key: STRING_KEYS.ORDERS }),
label: stringGetter({ key: STRING_KEYS.ORDERS }), href: PortfolioRoute.Orders,
href: PortfolioRoute.Orders, },
}, {
{ value: PortfolioRoute.Fees,
value: PortfolioRoute.Fees, slotBefore: <Styled.Icon iconName={IconName.Calculator} />,
slotBefore: <Styled.Icon iconName={IconName.Calculator} />, label: stringGetter({ key: STRING_KEYS.FEES }),
label: stringGetter({ key: STRING_KEYS.FEES }), href: PortfolioRoute.Fees,
href: PortfolioRoute.Fees, },
}, {
{ value: PortfolioRoute.History,
value: PortfolioRoute.History, slotBefore: <Styled.Icon iconName={IconName.History} />,
slotBefore: <Styled.Icon iconName={IconName.History} />, label: stringGetter({ key: STRING_KEYS.HISTORY }),
label: stringGetter({ key: STRING_KEYS.HISTORY }), href: PortfolioRoute.History,
href: PortfolioRoute.History, },
}, ],
], },
}, ]}
]} />
/>
{onboardingState === OnboardingState.AccountConnected && (
<Styled.Footer>
<Button
action={ButtonAction.Primary}
onClick={() => dispatch(openDialog({ type: DialogTypes.Deposit }))}
>
{stringGetter({ key: STRING_KEYS.DEPOSIT })}
</Button>
{usdcBalance > 0 && (
<Button
action={ButtonAction.Base}
onClick={() => dispatch(openDialog({ type: DialogTypes.Withdraw }))}
>
{stringGetter({ key: STRING_KEYS.WITHDRAW })}
</Button>
)}
{(usdcBalance > 0 || nativeTokenBalance.gt(0)) && (
<Button
action={ButtonAction.Base}
onClick={() => dispatch(openDialog({ type: DialogTypes.Transfer }))}
>
{stringGetter({ key: STRING_KEYS.TRANSFER })}
</Button>
)}
</Styled.Footer>
)}
</Styled.SideBar>
) )
} }
> >
@@ -181,26 +139,6 @@ Styled.PortfolioMobile = styled.div`
${layoutMixins.expandingColumnWithHeader} ${layoutMixins.expandingColumnWithHeader}
`; `;
Styled.SideBar = styled.div`
${layoutMixins.flexColumn}
justify-content: space-between;
height: 100%;
`;
Styled.Footer = styled.div`
${layoutMixins.row}
flex-wrap: wrap;
padding: 1rem;
gap: 0.5rem;
> button {
flex-grow: 1;
}
`;
Styled.NavigationMenu = styled(NavigationMenu)` Styled.NavigationMenu = styled(NavigationMenu)`
padding: 0.5rem; padding: 0.5rem;
padding-top: 0; padding-top: 0;
+17 -8
View File
@@ -43,14 +43,23 @@ export const DYDXBalancePanel = () => {
{!canAccountTrade ? ( {!canAccountTrade ? (
<OnboardingTriggerButton size={ButtonSize.Small} /> <OnboardingTriggerButton size={ButtonSize.Small} />
) : ( ) : (
<Button <>
slotLeft={<Icon iconName={IconName.Send} />} <Styled.ReceiveButton
size={ButtonSize.Small} slotLeft={<Icon iconName={IconName.Qr} />}
action={ButtonAction.Primary} size={ButtonSize.Small}
onClick={() => dispatch(openDialog({ type: DialogTypes.Transfer }))} onClick={() => dispatch(openDialog({ type: DialogTypes.Receive }))}
> >
{stringGetter({ key: STRING_KEYS.TRANSFER })} {stringGetter({ key: STRING_KEYS.RECEIVE })}
</Button> </Styled.ReceiveButton>
<Button
slotLeft={<Icon iconName={IconName.Send} />}
size={ButtonSize.Small}
action={ButtonAction.Primary}
onClick={() => dispatch(openDialog({ type: DialogTypes.Transfer }))}
>
{stringGetter({ key: STRING_KEYS.TRANSFER })}
</Button>
</>
)} )}
</Styled.ReceiveAndTransferButtons> </Styled.ReceiveAndTransferButtons>
</Styled.Header> </Styled.Header>
+4
View File
@@ -18,5 +18,9 @@ export const tradeViewMixins: Record<
tbody { tbody {
font: var(--font-small-book); font: var(--font-small-book);
} }
thead tr {
box-shadow: none;
}
`, `,
}; };
+5 -5
View File
@@ -82,18 +82,18 @@ const MarketsDropdownContent = ({ onRowAction }: { onRowAction?: (market: string
), ),
}, },
{ {
columnKey: 'priceChange24HPercent', columnKey: 'priceChange24H',
getCellValue: (row) => row.priceChange24HPercent, getCellValue: (row) => row.priceChange24H,
label: stringGetter({ key: STRING_KEYS._24H }), label: stringGetter({ key: STRING_KEYS._24H }),
renderCell: ({ priceChange24HPercent }) => ( renderCell: ({ priceChange24H, priceChange24HPercent }) => (
<Styled.InlineRow> <Styled.InlineRow>
{!priceChange24HPercent ? ( {!priceChange24H ? (
<Styled.Output type={OutputType.Text} value={null} /> <Styled.Output type={OutputType.Text} value={null} />
) : ( ) : (
<Styled.PriceChangeOutput <Styled.PriceChangeOutput
type={OutputType.Percent} type={OutputType.Percent}
value={priceChange24HPercent} value={priceChange24HPercent}
isNegative={MustBigNumber(priceChange24HPercent).isNegative()} isNegative={MustBigNumber(priceChange24H).isNegative()}
/> />
)} )}
</Styled.InlineRow> </Styled.InlineRow>
+2 -7
View File
@@ -45,12 +45,7 @@ export const TransferStatusSteps = ({ status, type }: ElementProps) => {
type === 'deposit' ? STRING_KEYS.INITIATED_DEPOSIT : STRING_KEYS.INITIATED_WITHDRAWAL, type === 'deposit' ? STRING_KEYS.INITIATED_DEPOSIT : STRING_KEYS.INITIATED_WITHDRAWAL,
}), }),
step: TransferStatusStep.FromChain, step: TransferStatusStep.FromChain,
link: link: status?.fromChain?.transactionUrl,
type === 'deposit'
? status?.fromChain?.transactionUrl
: routeStatus?.[0]?.chainId === dydxChainId && routeStatus[0].txHash
? `${mintscanTxUrl?.replace('{tx_hash}', routeStatus[0].txHash.replace('0x', ''))}`
: undefined,
}, },
{ {
label: stringGetter({ key: STRING_KEYS.BRIDGING_TOKENS }), label: stringGetter({ key: STRING_KEYS.BRIDGING_TOKENS }),
@@ -69,7 +64,7 @@ export const TransferStatusSteps = ({ status, type }: ElementProps) => {
type === 'withdrawal' type === 'withdrawal'
? status?.toChain?.transactionUrl ? status?.toChain?.transactionUrl
: currentStatus?.chainId === dydxChainId && currentStatus?.txHash : currentStatus?.chainId === dydxChainId && currentStatus?.txHash
? `${mintscanTxUrl?.replace('{tx_hash}', currentStatus.txHash.replace('0x', ''))}` ? `${mintscanTxUrl?.replace('{tx_hash}', currentStatus.txHash)}`
: undefined, : undefined,
}, },
]; ];
+11 -18
View File
@@ -3,7 +3,6 @@ import styled, { AnyStyledComponent, css } from 'styled-components';
import { AnalyticsEvent } from '@/constants/analytics'; import { AnalyticsEvent } from '@/constants/analytics';
import { STRING_KEYS } from '@/constants/localization'; import { STRING_KEYS } from '@/constants/localization';
import { isMainnet } from '@/constants/networks';
import { EvmDerivedAccountStatus, OnboardingSteps } from '@/constants/account'; import { EvmDerivedAccountStatus, OnboardingSteps } from '@/constants/account';
import { wallets } from '@/constants/wallets'; import { wallets } from '@/constants/wallets';
@@ -27,7 +26,6 @@ import { track } from '@/lib/analytics';
import { AcknowledgeTerms } from './OnboardingDialog/AcknowledgeTerms'; import { AcknowledgeTerms } from './OnboardingDialog/AcknowledgeTerms';
import { ChooseWallet } from './OnboardingDialog/ChooseWallet'; import { ChooseWallet } from './OnboardingDialog/ChooseWallet';
import { GenerateKeys } from './OnboardingDialog/GenerateKeys'; import { GenerateKeys } from './OnboardingDialog/GenerateKeys';
import { DepositForm } from '../forms/AccountManagementForms/DepositForm';
type ElementProps = { type ElementProps = {
setIsOpen?: (open: boolean) => void; setIsOpen?: (open: boolean) => void;
@@ -52,7 +50,7 @@ export const OnboardingDialog = ({ setIsOpen }: ElementProps) => {
disconnect(); disconnect();
} }
setIsOpen?.(open); setIsOpen?.(open);
}; }
return ( return (
<Styled.Dialog <Styled.Dialog
@@ -84,7 +82,10 @@ export const OnboardingDialog = ({ setIsOpen }: ElementProps) => {
description: stringGetter({ key: STRING_KEYS.SIGNATURE_CREATES_COSMOS_WALLET }), description: stringGetter({ key: STRING_KEYS.SIGNATURE_CREATES_COSMOS_WALLET }),
children: ( children: (
<Styled.Content> <Styled.Content>
<GenerateKeys status={derivationStatus} setStatus={setDerivationStatus} /> <GenerateKeys
status={derivationStatus}
setStatus={setDerivationStatus}
/>
</Styled.Content> </Styled.Content>
), ),
width: '23rem', width: '23rem',
@@ -100,22 +101,14 @@ export const OnboardingDialog = ({ setIsOpen }: ElementProps) => {
}, },
[OnboardingSteps.DepositFunds]: { [OnboardingSteps.DepositFunds]: {
title: stringGetter({ key: STRING_KEYS.DEPOSIT }), title: stringGetter({ key: STRING_KEYS.DEPOSIT }),
description: !isMainnet && 'Test funds will be sent directly to your dYdX account.', description: 'Test funds will be sent directly to your dYdX account.',
children: ( children: (
<Styled.Content> <Styled.Content>
{isMainnet ? ( <TestnetDepositForm
<DepositForm onDeposit={() => {
onDeposit={() => { track(AnalyticsEvent.TransferFaucet);
track(AnalyticsEvent.TransferDeposit); }}
}} />
/>
) : (
<TestnetDepositForm
onDeposit={() => {
track(AnalyticsEvent.TransferFaucet);
}}
/>
)}
</Styled.Content> </Styled.Content>
), ),
}, },