-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add transparent assets table (#1234)
- Loading branch information
1 parent
ce300c8
commit ed94316
Showing
9 changed files
with
273 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { ActionButton, Panel } from "@namada/components"; | ||
import { FiatCurrency } from "App/Common/FiatCurrency"; | ||
import { routes } from "App/routes"; | ||
import { shieldedTokensAtom } from "atoms/balance/atoms"; | ||
import { getTotalDollar } from "atoms/balance/functions"; | ||
import { useAtomValue } from "jotai"; | ||
import { twMerge } from "tailwind-merge"; | ||
import maspBg from "./assets/masp-bg.png"; | ||
|
||
export const MaspBanner = (): JSX.Element => { | ||
const shieldedTokensQuery = useAtomValue(shieldedTokensAtom); | ||
const total = getTotalDollar(shieldedTokensQuery.data); | ||
|
||
return ( | ||
<Panel | ||
className={twMerge( | ||
"relative p-10 border border-yellow", | ||
"flex items-center flex-wrap gap-10", | ||
"text-yellow" | ||
)} | ||
> | ||
<div className="relative h-[170px] w-[170px] flex items-center justify-center"> | ||
<img src={maspBg} className="absolute" /> | ||
<div className="col-start-1 row-start-1 text-4xl">MASP</div> | ||
</div> | ||
<div className="flex-1"> | ||
{total && total.gt(0) && ( | ||
<> | ||
<div className="text-sm">Total shielded balance</div> | ||
<FiatCurrency className="text-4xl" amount={total} /> | ||
</> | ||
)} | ||
</div> | ||
<ActionButton | ||
size="md" | ||
href={routes.ibcShieldAll} | ||
className="self-end justify-end" | ||
> | ||
Manage your shielded assets | ||
</ActionButton> | ||
</Panel> | ||
); | ||
}; |
197 changes: 197 additions & 0 deletions
197
apps/namadillo/src/App/AccountOverview/TransparentOverviewPanel.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
import { | ||
ActionButton, | ||
Panel, | ||
SkeletonLoading, | ||
TableRow, | ||
} from "@namada/components"; | ||
import { AtomErrorBoundary } from "App/Common/AtomErrorBoundary"; | ||
import { FiatCurrency } from "App/Common/FiatCurrency"; | ||
import { TableWithPaginator } from "App/Common/TableWithPaginator"; | ||
import { TokenCurrency } from "App/Common/TokenCurrency"; | ||
import { routes } from "App/routes"; | ||
import { TokenBalance, transparentTokensAtom } from "atoms/balance/atoms"; | ||
import { getTotalDollar } from "atoms/balance/functions"; | ||
import { getAssetImageUrl } from "integrations/utils"; | ||
import { useAtomValue } from "jotai"; | ||
import { useEffect, useState } from "react"; | ||
import { namadaAsset } from "registry/namadaAsset"; | ||
import { twMerge } from "tailwind-merge"; | ||
|
||
const resultsPerPage = 100; | ||
const initialPage = 0; | ||
|
||
const TransparentTokensTable = ({ | ||
data, | ||
}: { | ||
data: TokenBalance[]; | ||
}): JSX.Element => { | ||
const [page, setPage] = useState(initialPage); | ||
|
||
const headers = ["Token", { children: "Balance", className: "text-right" }]; | ||
|
||
const renderRow = ({ asset, balance, dollar }: TokenBalance): TableRow => { | ||
const display = asset.display; | ||
const icon = getAssetImageUrl(asset); | ||
|
||
return { | ||
cells: [ | ||
<div key={`token-${display}`} className="flex items-center gap-4"> | ||
<div className="aspect-square w-8 h-8"> | ||
{icon ? | ||
<img src={icon} /> | ||
: <div className="rounded-full h-full border border-white" />} | ||
</div> | ||
{asset.symbol} | ||
</div>, | ||
<div | ||
key={`balance-${display}`} | ||
className="flex flex-col text-right leading-tight" | ||
> | ||
<TokenCurrency asset={asset} amount={balance} /> | ||
{dollar && ( | ||
<FiatCurrency | ||
className="text-neutral-600 text-sm" | ||
amount={dollar} | ||
/> | ||
)} | ||
</div>, | ||
<div | ||
key={`buttons-${display}`} | ||
className="flex items-center justify-end gap-1" | ||
> | ||
<ActionButton size="xs" href={routes.maspShield}> | ||
Shield | ||
</ActionButton> | ||
{display === namadaAsset.display && ( | ||
<ActionButton | ||
size="xs" | ||
className="w-fit mx-auto" | ||
backgroundColor="cyan" | ||
href={routes.stakingBondingIncrement} | ||
> | ||
Stake | ||
</ActionButton> | ||
)} | ||
</div>, | ||
], | ||
}; | ||
}; | ||
|
||
useEffect(() => { | ||
setPage(0); | ||
}, [data]); | ||
|
||
const paginatedItems = data.slice( | ||
page * resultsPerPage, | ||
page * resultsPerPage + resultsPerPage | ||
); | ||
|
||
const pageCount = Math.ceil(data.length / resultsPerPage); | ||
|
||
return ( | ||
<> | ||
<div className="text-sm font-medium mt-6"> | ||
<span className="text-yellow">{data.length} </span> | ||
Tokens | ||
</div> | ||
<TableWithPaginator | ||
id="transparent-tokens" | ||
headers={headers.concat("")} | ||
renderRow={renderRow} | ||
itemList={paginatedItems} | ||
page={page} | ||
pageCount={pageCount} | ||
onPageChange={setPage} | ||
tableProps={{ | ||
className: twMerge( | ||
"w-full flex-1 [&_td]:px-1 [&_th]:px-1 [&_td:first-child]:pl-4 [&_td]:h-[64px]", | ||
"[&_td]:font-normal [&_td:last-child]:pr-4 [&_th:first-child]:pl-4 [&_th:last-child]:pr-4", | ||
"[&_td:first-child]:rounded-s-md [&_td:last-child]:rounded-e-md", | ||
"mt-2" | ||
), | ||
}} | ||
headProps={{ className: "text-neutral-500" }} | ||
/> | ||
</> | ||
); | ||
}; | ||
|
||
const PanelContent = ({ data }: { data: TokenBalance[] }): JSX.Element => { | ||
const namBalance = data.find((i) => i.asset.base === namadaAsset.base); | ||
|
||
return ( | ||
<div className="flex flex-col gap-2"> | ||
<div className="grid md:grid-cols-2 gap-2"> | ||
{[ | ||
{ | ||
title: "Total Transparent Asset Balance", | ||
amount: getTotalDollar(data), | ||
button: ( | ||
<ActionButton size="xs" href={routes.ibcShieldAll}> | ||
Shield All | ||
</ActionButton> | ||
), | ||
}, | ||
{ | ||
title: "Transparent NAM Balance", | ||
amount: namBalance?.dollar, | ||
namAmount: namBalance?.balance, | ||
button: ( | ||
<ActionButton | ||
size="xs" | ||
backgroundColor="cyan" | ||
href={routes.stakingBondingIncrement} | ||
> | ||
Stake | ||
</ActionButton> | ||
), | ||
}, | ||
].map(({ title, amount, namAmount, button }) => ( | ||
<div key={title} className="bg-gray px-6 py-3 rounded-sm flex gap-6"> | ||
<div className="flex-1 overflow-auto"> | ||
<div className="text-sm">{title}</div> | ||
<div className="text-2xl sm:text-3xl whitespace-nowrap overflow-auto"> | ||
{amount ? | ||
<FiatCurrency amount={amount} /> | ||
: "N/A"} | ||
</div> | ||
{namAmount && namBalance && ( | ||
<TokenCurrency | ||
amount={namAmount} | ||
asset={namBalance.asset} | ||
className="text-neutral-400 text-sm" | ||
/> | ||
)} | ||
</div> | ||
<div className="self-center">{button}</div> | ||
</div> | ||
))} | ||
</div> | ||
<TransparentTokensTable data={data} /> | ||
</div> | ||
); | ||
}; | ||
|
||
export const TransparentOverviewPanel = (): JSX.Element => { | ||
const transparentTokensQuery = useAtomValue(transparentTokensAtom); | ||
|
||
return ( | ||
<Panel className="min-h-[300px] flex flex-col" title="Transparent Overview"> | ||
{transparentTokensQuery.isPending ? | ||
<SkeletonLoading height="100%" width="100%" /> | ||
: <AtomErrorBoundary | ||
result={transparentTokensQuery} | ||
niceError="Unable to load your transparent balance" | ||
containerProps={{ className: "pb-16" }} | ||
> | ||
{transparentTokensQuery.data?.length ? | ||
<PanelContent data={transparentTokensQuery.data} /> | ||
: <div className="bg-neutral-900 p-6 rounded-sm text-center font-medium my-14"> | ||
You currently hold no assets in your unshielded account | ||
</div> | ||
} | ||
</AtomErrorBoundary> | ||
} | ||
</Panel> | ||
); | ||
}; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,22 @@ | ||
import { Currency, CurrencyProps } from "@namada/components"; | ||
import BigNumber from "bignumber.js"; | ||
|
||
type FiatCurrencyProps = Omit<CurrencyProps, "currency">; | ||
|
||
export const FiatCurrency = (props: FiatCurrencyProps): JSX.Element => { | ||
return <Currency currency={{ symbol: "$", fraction: "cents" }} {...props} />; | ||
let amount = new BigNumber(props.amount); | ||
if (amount.lt(0.01)) { | ||
amount = new BigNumber(amount.toPrecision(2)); | ||
} else { | ||
amount = amount.decimalPlaces(2); | ||
} | ||
|
||
return ( | ||
<Currency | ||
{...props} | ||
currency={{ symbol: "$", fraction: "cents" }} | ||
amount={amount} | ||
decimalPlaces={amount.decimalPlaces() === 1 ? 2 : undefined} | ||
/> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ed94316
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉 Published on https://namada-interface-dev.netlify.app as production
🚀 Deployed on https://672e5aabb051111005667454--namada-interface-dev.netlify.app