Skip to content

Commit

Permalink
feat: add base UI for masp overview (#1144)
Browse files Browse the repository at this point in the history
  • Loading branch information
euharrison authored Sep 27, 2024
1 parent 70971a6 commit 1def6e0
Show file tree
Hide file tree
Showing 11 changed files with 430 additions and 19 deletions.
33 changes: 19 additions & 14 deletions apps/namadillo/src/App/Icons/MASPIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
export const MASPIcon = (): JSX.Element => {
return (
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.25">
<circle
cx="8.3418"
cy="8.46289"
r="6.5"
stroke="white"
strokeWidth="2"
/>
<circle cx="8.51367" cy="5.78711" r="1.39062" fill="white" />
<circle cx="4.74475" cy="8.46252" r="1.28479" fill="white" />
<circle cx="7.69434" cy="10.8086" r="1.23438" fill="white" />
<circle cx="11.6127" cy="8.23474" r="1.34021" fill="white" />
</g>
<svg
height="1em"
width="1em"
viewBox="0 0 16 16"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
>
<circle
cx="8"
cy="8"
r="6.5"
stroke="currentColor"
strokeWidth="2"
fill="none"
/>
<circle cx="8.17187" cy="5.32422" r="1.3" />
<circle cx="4.70295" cy="7.99963" r="1.3" />
<circle cx="7.35254" cy="10.34571" r="1.3" />
<circle cx="11.2709" cy="7.77185" r="1.3" />
</svg>
);
};
8 changes: 3 additions & 5 deletions apps/namadillo/src/App/Layout/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { DISCORD_URL, TWITTER_URL } from "urls";

import IbcRoutes from "App/Ibc/routes";
import StakingRoutes from "App/Staking/routes";
import TransferRoutes from "App/Transfer/routes";
import { applicationFeaturesAtom } from "atoms/settings";

export const Navigation = (): JSX.Element => {
Expand All @@ -35,11 +36,8 @@ export const Navigation = (): JSX.Element => {
},
{
label: "MASP",
icon: (
<i className="w-4">
<MASPIcon />
</i>
),
icon: <MASPIcon />,
url: features.maspEnabled ? TransferRoutes.masp().url : undefined,
},
{
label: "IBC Transfer",
Expand Down
47 changes: 47 additions & 0 deletions apps/namadillo/src/App/Transfer/MaspOverview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Panel } from "@namada/components";
import { ConnectBanner } from "App/Common/ConnectBanner";
import { PageWithSidebar } from "App/Common/PageWithSidebar";
import { ShieldAllBanner } from "App/Sidebars/ShieldAllBanner";
import { namadaExtensionConnectedAtom } from "atoms/settings";
import { useUserHasAccount } from "hooks/useUserHasAccount";
import { useAtomValue } from "jotai";
import { ShieldedBalanceChart } from "./ShieldedBalanceChart";
import { ShieldedNamBalance } from "./ShieldedNamBalance";
import { ShieldedOverviewPanel } from "./ShieldedOverviewPanel";

export const MaspOverview: React.FC = () => {
const hasAccount = useUserHasAccount();
const isConnected = useAtomValue(namadaExtensionConnectedAtom);

return (
<PageWithSidebar>
<div className="flex flex-col gap-2">
{!isConnected && (
<ConnectBanner text="To shield assets please connect your account" />
)}
{isConnected && hasAccount === false && (
<ConnectBanner text="To shield assets please create or import an account using Namada keychain" />
)}
{isConnected && hasAccount && (
<div className="flex flex-col sm:grid sm:grid-cols-[2fr_3fr] gap-2">
<Panel>
<ShieldedBalanceChart />
</Panel>
<Panel>
<ShieldedNamBalance />
</Panel>
</div>
)}
<Panel
className="relative pb-6 border border-yellow"
title="Shielded Overview"
>
<ShieldedOverviewPanel />
</Panel>
</div>
<aside className="w-full mt-2 flex flex-col sm:flex-row lg:mt-0 lg:flex-col gap-2">
<ShieldAllBanner />
</aside>
</PageWithSidebar>
);
};
42 changes: 42 additions & 0 deletions apps/namadillo/src/App/Transfer/ShieldedBalanceChart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Heading, PieChart, SkeletonLoading } from "@namada/components";
import { AtomErrorBoundary } from "App/Common/AtomErrorBoundary";
import { useBalances } from "hooks/useBalances";
import { colors } from "theme";

export const ShieldedBalanceChart = (): JSX.Element => {
const { isLoading, isSuccess } = useBalances();

return (
<AtomErrorBoundary
// TODO shieldedQuery
result={[]}
niceError="Unable to load balance"
>
<div className="flex w-full h-[260px]">
{isLoading && (
<SkeletonLoading
height="auto"
width="80%"
className="rounded-full aspect-square mx-auto border-neutral-800 border-[22px] bg-transparent"
/>
)}
{isSuccess && (
<PieChart
id="balance-chart"
className="xl:max-w-[85%] mx-auto"
data={[{ value: 100, color: colors.shielded }]}
strokeWidth={7}
segmentMargin={0}
>
<div className="flex flex-col gap-1 leading-tight">
<Heading className="text-sm" level="h3">
Shielded Balance
</Heading>
<div className="text-2xl sm:text-3xl">$9999.99</div>
</div>
</PieChart>
)}
</div>
</AtomErrorBoundary>
);
};
150 changes: 150 additions & 0 deletions apps/namadillo/src/App/Transfer/ShieldedFungibleTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import { ActionButton, TableRow } from "@namada/components";
import { formatPercentage } from "@namada/utils";
import { AtomErrorBoundary } from "App/Common/AtomErrorBoundary";
import { NamCurrency } from "App/Common/NamCurrency";
import { TableWithPaginator } from "App/Common/TableWithPaginator";
import BigNumber from "bignumber.js";
import { AtomWithQueryResult } from "jotai-tanstack-query";
import { useEffect, useState } from "react";
import { twMerge } from "tailwind-merge";

type MockedToken = {
name: string;
balance: number;
dollar: number;
ssrRate: number;
};

const mockData = (): AtomWithQueryResult<MockedToken[]> =>
({
data: [
{
name: "NAM",
balance: 9999.99,
dollar: 9999.99,
ssrRate: 0.99,
},
{
name: "ATOM",
balance: 9999.99,
dollar: 9999.99,
ssrRate: 0.99,
},
],
// eslint-disable-next-line @typescript-eslint/no-explicit-any
}) as any;

const resultsPerPage = 100;
const initialPage = 0;

export const ShieldedFungibleTable = (): JSX.Element => {
const [page, setPage] = useState(initialPage);

// TODO
const query = mockData();

const list = query.data ?? [];

const headers = [
"Token",
{
children: "Balance",
className: "text-right",
},
{
children: "SSR Rate",
className: "text-right",
},
];

const renderRow = (token: MockedToken): TableRow => {
return {
cells: [
<div key={`token-${token.name}`} className="flex items-center gap-4">
<div
className={"aspect-square w-8 rounded-full border border-yellow"}
/>
{token.name}
</div>,
<div
key={`balance-${token.name}`}
className="flex flex-col text-right leading-tight"
>
<NamCurrency amount={9999.99} />
<span className="text-neutral-600 text-sm">$9999</span>
</div>,
<div
key={`ssr-rate-${token.name}`}
className="text-right leading-tight"
>
{formatPercentage(new BigNumber(0.99))}
</div>,
<ActionButton
key={`unshield-${token.name}`}
size="xs"
outlineColor="white"
className="w-fit mx-auto"
>
Unshield
</ActionButton>,
<div
key={`my-validator-currency-${token.name}`}
className="text-right leading-tight"
>
<div
className={"aspect-square w-8 rounded-full border border-white"}
/>
</div>,
],
};
};

useEffect(() => {
setPage(0);
}, [list]);

const paginatedItems = list.slice(
page * resultsPerPage,
page * resultsPerPage + resultsPerPage
);

const pageCount = Math.ceil(list.length / resultsPerPage);

return (
<AtomErrorBoundary
result={query}
niceError="Unable to load your validators list"
containerProps={{ className: "pb-16" }}
>
<ActionButton
size="xs"
outlineColor="white"
className="w-fit ml-auto mt-6"
>
Unshield ALL
</ActionButton>
<div className="text-sm font-medium">
<span className="text-yellow">{list.length} </span>
Tokens
</div>
<TableWithPaginator
id={"my-validators"}
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" }}
/>
</AtomErrorBoundary>
);
};
7 changes: 7 additions & 0 deletions apps/namadillo/src/App/Transfer/ShieldedNFTTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const ShieldedNFTTable = (): JSX.Element => {
return (
<div className="text-yellow p-10">
<div>NFT Table (WIP)</div>
</div>
);
};
Loading

1 comment on commit 1def6e0

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.