Skip to content

Commit

Permalink
Wallet coins details (MystenLabs#5568)
Browse files Browse the repository at this point in the history
* coin details wip

* prevent the entire coins details from scrolling

* prevent coin balance standalone component navigative to details view

* rm hover spacing

* hide stake for non sui token

* change names to reflect multple tokens

* update

* rm hover color

* update

* update

* update

* active coin update

* lint fix

* rm comment

* rm css class

* update
  • Loading branch information
Jibz1 authored Oct 27, 2022
1 parent 9cdec4f commit 4b979aa
Show file tree
Hide file tree
Showing 12 changed files with 320 additions and 162 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@
}

.coin-list {
margin-top: 20px;

.selector-content {
margin-top: 25px;
height: 100%;
}

.coin-detail {
margin-top: 20px;
height: 63px;
border-radius: 6px;
display: flex;
Expand All @@ -61,7 +62,6 @@
.coin-label {
@include utils.typography('table/text-lg');

width: 55%;
display: flex;
flex-direction: column;
color: colors.$gray-100;
Expand All @@ -76,7 +76,8 @@
.coin-amount {
@include utils.typography('table/text-lg');

line-height: 17px;
text-align: right;
line-height: 20px;
}

.coin-icon {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { useEffect } from 'react';

import Loading from '_components/loading';
import TransactionCard from '_components/transactions-card';
import { useAppSelector, useAppDispatch } from '_hooks';
import { getTransactionsByAddress } from '_redux/slices/txresults';

import type { TxResultState } from '_redux/slices/txresults';

import st from './TransactionsCard.module.scss';

type Props = {
coinType?: string;
};

function RecentTransactions({ coinType }: Props) {
const dispatch = useAppDispatch();
const txByAddress: TxResultState[] = useAppSelector(({ txresults }) =>
coinType
? txresults.latestTx.filter((tx) => tx.coinType === coinType)
: txresults.latestTx
);

const loading: boolean = useAppSelector(
({ txresults }) => txresults.loading
);

useEffect(() => {
dispatch(getTransactionsByAddress()).unwrap();
}, [dispatch]);

return (
<>
<Loading loading={loading} className={st.centerLoading}>
{txByAddress.map((txn) => (
<TransactionCard txn={txn} key={txn.txId} />
))}
</Loading>
</>
);
}

export default RecentTransactions;
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
justify-content: space-between;
border-bottom: 1px solid colors.$gray-45;
height: auto;
padding: 15px 0;
padding: 10px 0;
cursor: pointer;

.card-icon {
Expand Down Expand Up @@ -190,3 +190,10 @@
color: colors.$gray-65;
font-weight: 400;
}

.center-loading {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
2 changes: 1 addition & 1 deletion apps/wallet/src/ui/app/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const App = () => {
return (
<Routes>
<Route path="/*" element={<HomePage />}>
<Route path="tokens" element={<TokensPage />} />
<Route path="tokens/*" element={<TokensPage />} />
<Route path="nfts" element={<NftsPage />} />
<Route path="apps/*" element={<AppsPage />} />
<Route path="nft-details" element={<NFTDetailsPage />} />
Expand Down
17 changes: 17 additions & 0 deletions apps/wallet/src/ui/app/pages/home/tokens/TokenDetailsPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
import { Navigate, useSearchParams } from 'react-router-dom';

import TokenDetails from './TokensDetails';

function TokenDetailsPage() {
const [searchParams] = useSearchParams();
const coinType = searchParams.get('type');

if (!coinType) {
return <Navigate to="/tokens" replace={true} />;
}
return <TokenDetails coinType={coinType} />;
}

export default TokenDetailsPage;
183 changes: 183 additions & 0 deletions apps/wallet/src/ui/app/pages/home/tokens/TokensDetails.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import cl from 'classnames';
import { useMemo } from 'react';

import CoinBalance from './coin-balance';
import IconLink from './icon-link';
import FaucetMessageInfo from '_app/shared/faucet/message-info';
import FaucetRequestButton from '_app/shared/faucet/request-button';
import PageTitle from '_app/shared/page-title';
import AccountAddress from '_components/account-address';
import Alert from '_components/alert';
import Loading from '_components/loading';
import RecentTransactions from '_components/transactions-card/RecentTransactions';
import { SuiIcons } from '_font-icons/output/sui-icons';
import { useAppSelector, useObjectsState } from '_hooks';
import { accountAggregateBalancesSelector } from '_redux/slices/account';
import { GAS_TYPE_ARG, Coin } from '_redux/slices/sui-objects/Coin';

import st from './TokensPage.module.scss';

type TokenDetailsProps = {
coinType?: string;
};

const emptyWalletDescription = (
<div className={st.emptyWalletDescription}>
To conduct transactions on the Sui network, you need SUI in your wallet.
</div>
);

type TokensProps = {
allCoinTypes: string[];
coinBalance: bigint;
balances: Record<string, bigint>;
loading: boolean;
};

function MyTokens({
allCoinTypes,
coinBalance,
balances,
loading,
}: TokensProps) {
return (
<Loading loading={loading} className={st.othersLoader}>
{allCoinTypes.length ? (
<>
<div className={st.title}>MY COINS</div>
<div className={st.otherCoins}>
{allCoinTypes.map((aCoinType) => (
<CoinBalance
type={aCoinType}
balance={balances[aCoinType] || BigInt(0)}
key={aCoinType}
/>
))}
{coinBalance <= 0 ? (
<div className={st.emptyWallet}>
<FaucetRequestButton />
{emptyWalletDescription}
</div>
) : null}
</div>
</>
) : (
<div className={st.emptyWallet}>
<div className={st.emptyWalletIcon} />
<div className={st.emptyWalletTitle}>
Your wallet contains no SUI.
</div>
{emptyWalletDescription}
<FaucetRequestButton />
</div>
)}
<FaucetMessageInfo className={st.gasRequestInfo} />
</Loading>
);
}

function TokenDetails({ coinType }: TokenDetailsProps) {
const { loading, error, showError } = useObjectsState();
const activeCoinType = coinType || GAS_TYPE_ARG;
const balances = useAppSelector(accountAggregateBalancesSelector);
const tokenBalance = balances[activeCoinType] || BigInt(0);
const allCoinTypes = useMemo(() => Object.keys(balances), [balances]);
const coinTypeWithBalance =
coinType || tokenBalance > 0 ? activeCoinType : allCoinTypes[0];

const coinSymbol = useMemo(
() => Coin.getCoinSymbol(activeCoinType),
[activeCoinType]
);

return (
<>
{coinType && (
<PageTitle
title={coinSymbol}
backLink="/tokens"
hideBackLabel={true}
/>
)}

<div className={st.container}>
{showError && error ? (
<Alert className={st.alert}>
<strong>Sync error (data might be outdated).</strong>{' '}
<small>{error.message}</small>
</Alert>
) : null}
{!coinType && <AccountAddress showLink={false} mode="faded" />}
<div className={st.balanceContainer}>
<Loading loading={loading}>
<CoinBalance
balance={tokenBalance}
type={activeCoinType}
mode="standalone"
/>
</Loading>
</div>
<div className={st.actions}>
<IconLink
icon={SuiIcons.Buy}
to="/"
disabled={true}
text="Buy"
/>
<IconLink
icon={SuiIcons.ArrowLeft}
to={`/send${
coinTypeWithBalance
? `?${new URLSearchParams({
type: coinTypeWithBalance,
}).toString()}`
: ''
}`}
disabled={!coinTypeWithBalance}
text="Send"
/>
<IconLink
icon={SuiIcons.Swap}
to="/"
disabled={true}
text="Swap"
/>
</div>

{activeCoinType === GAS_TYPE_ARG ? (
<div className={st.staking}>
<IconLink
icon={SuiIcons.Union}
to="/stake"
disabled={true}
text="Stake & Earn SUI"
/>
</div>
) : null}

{!coinType ? (
<MyTokens
allCoinTypes={allCoinTypes}
coinBalance={tokenBalance}
balances={balances}
loading={loading}
/>
) : (
<>
<div className={cl([st.title, st.tokenActivities])}>
{coinSymbol} activity
</div>
<div className={st.txContent}>
<RecentTransactions coinType={activeCoinType} />
</div>
</>
)}
</div>
</>
);
}

export default TokenDetails;
21 changes: 16 additions & 5 deletions apps/wallet/src/ui/app/pages/home/tokens/TokensPage.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
.container {
display: flex;
flex-flow: column nowrap;
max-width: 100%;
align-items: center;
height: 100%;
flex-grow: 1;
align-items: center;
overflow-y: scroll;
margin-top: 20px;

@include utils.override-main-padding;
}

.balance-container {
Expand Down Expand Up @@ -35,11 +39,10 @@
margin-bottom: 16px;
}

.other-coins {
.other-coins,
.tx-content {
display: flex;
flex-flow: column nowrap;
max-height: 100%;
overflow-y: auto;
flex-grow: 1;
align-self: stretch;

Expand Down Expand Up @@ -103,3 +106,11 @@
position: sticky;
bottom: 0;
}

.details-page {
overflow-y: hidden;
}

.token-activities {
margin-bottom: 7px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
}
}

.coin-balance-btn {
cursor: pointer;
}

.coin-icon {
display: flex;
align-items: center;
Expand Down
Loading

0 comments on commit 4b979aa

Please sign in to comment.