Skip to content

Commit 197c6d9

Browse files
feat: add MASP calculator popup component on Claims card (#2072)
Co-authored-by: Harrison Mendonça <harrisonmendonca@gmail.com>
1 parent ee17c3e commit 197c6d9

File tree

11 files changed

+208
-139
lines changed

11 files changed

+208
-139
lines changed

apps/namadillo/src/App/AccountOverview/AssetsOverviewPanel.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ export const AssetsOverviewPanel = (): JSX.Element => {
2020
onChangeActiveTab={setCurrentTab}
2121
containerClassname="flex-1"
2222
className={clsx(
23-
"mt-2 transition-colors border-solid border border-transparent",
23+
"mt-2 transition-colors border-solid border border-transparent border-b-neutral-950",
2424
"duration-0",
25-
"[&[aria-selected='true']]:z-20 [&[aria-selected='true']]:!border-b-neutral-950",
25+
shieldedPanelSelected && "[&[aria-selected='false']]:border-b-yellow",
2626
shieldedPanelSelected &&
27-
"[&[aria-selected='true']]:text-yellow [&[aria-selected='true']]:border-yellow"
27+
"[&[aria-selected='true']]:text-yellow [&[aria-selected='true']]:border-x-yellow [&[aria-selected='true']]:border-t-yellow"
2828
)}
2929
tabs={[
3030
{
Lines changed: 74 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,86 @@
1+
import { Modal, Tooltip } from "@namada/components";
2+
import { ModalContainer } from "App/Common/ModalContainer";
13
import { NamCurrency } from "App/Common/NamCurrency";
4+
import { MaspRewardCalculator } from "App/Sidebars/MaspRewardCalculator";
25
import { cachedShieldedRewardsAtom } from "atoms/balance";
6+
import { applicationFeaturesAtom } from "atoms/settings";
37
import clsx from "clsx";
48
import { useAtomValue } from "jotai";
9+
import { useState } from "react";
10+
import { FaCalculator } from "react-icons/fa6";
511

612
export const EstimateShieldingRewardsCard = (): JSX.Element => {
713
const shieldedRewards = useAtomValue(cachedShieldedRewardsAtom);
14+
const [isModalOpen, setIsModalOpen] = useState(false);
15+
const features = useAtomValue(applicationFeaturesAtom);
16+
17+
const handleCloseModal = (): void => {
18+
setIsModalOpen(false);
19+
};
20+
21+
const handleOpenModal = (): void => {
22+
setIsModalOpen(true);
23+
};
824

925
return (
10-
<div
11-
className={clsx(
12-
"flex items-center gap-12 text-sm text-yellow bg-neutral-900 rounded-sm px-6 mr-3",
13-
"py-4"
14-
)}
15-
>
16-
<span className="max-w-[15ch] text-center leading-tight">
17-
Your Est. Shielding rewards per 24hrs
18-
</span>
19-
<span className="text-3xl text-center leading-7 relative top-1">
20-
{shieldedRewards.amount === undefined ?
21-
<span>
22-
--<i className="block text-sm not-italic">NAM</i>
23-
</span>
24-
: <div className="flex flex-col items-center">
25-
<NamCurrency
26-
amount={shieldedRewards.amount}
27-
currencySymbolClassName="text-xs block"
28-
decimalPlaces={2}
29-
/>
26+
<>
27+
<div
28+
className={clsx(
29+
"flex items-center gap-12 text-sm text-yellow bg-neutral-900 rounded-sm px-6 mr-3",
30+
"py-4"
31+
)}
32+
>
33+
<span className="max-w-[15ch] text-center leading-tight">
34+
Your Est. Shielding rewards per 24hrs
35+
</span>
36+
<span className="text-3xl text-center leading-7 relative top-1">
37+
{shieldedRewards.amount === undefined ?
38+
<span>
39+
--<i className="block text-sm not-italic">NAM</i>
40+
</span>
41+
: <div className="flex flex-col items-center">
42+
<NamCurrency
43+
amount={shieldedRewards.amount}
44+
currencySymbolClassName="text-xs block"
45+
decimalPlaces={2}
46+
/>
47+
</div>
48+
}
49+
</span>
50+
{features.shieldingRewardsEnabled && (
51+
<div
52+
className="group group/tooltip relative p-2 bg-black border border-yellow rounded-full cursor-pointer hover:bg-yellow hover:border-yellow transition-colors"
53+
onClick={handleOpenModal}
54+
>
55+
<Tooltip position="top" className="w-[120px] text-center -mt-1">
56+
Masp Rewards Calculator
57+
</Tooltip>
58+
59+
<FaCalculator className="text-3xl text-yellow group-hover:text-black p-1 transition-colors" />
3060
</div>
31-
}
32-
</span>
33-
</div>
61+
)}
62+
</div>
63+
64+
{isModalOpen && (
65+
<Modal onClose={handleCloseModal}>
66+
<ModalContainer
67+
header="MASP Rewards Calculator"
68+
headerProps={{
69+
className: "text-left",
70+
}}
71+
onClose={handleCloseModal}
72+
containerProps={{
73+
className:
74+
"!w-[380px] !h-[auto] bg-black border border-neutral-600 overflow-visible",
75+
}}
76+
contentProps={{
77+
className: "overflow-visible",
78+
}}
79+
>
80+
<MaspRewardCalculator />
81+
</ModalContainer>
82+
</Modal>
83+
)}
84+
</>
3485
);
3586
};

apps/namadillo/src/App/AccountOverview/ShieldedAssetsOverview.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const ShieldedAssetsOverview = (): JSX.Element => {
1414
const requiresNewShieldedSync = useRequiresNewShieldedSync();
1515

1616
return (
17-
<Panel className="relative z-10 px-6 border border-yellow rounded-t-none -mt-px h-full">
17+
<Panel className="relative px-6 border-x border-b border-yellow rounded-t-none h-full">
1818
<div className="flex justify-between gap-16 mt-4">
1919
<TotalBalanceCard
2020
balanceInFiat={shieldedAmountInFiat}

apps/namadillo/src/App/AccountOverview/UnshieldedAssetsOverview.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export const UnshieldedAssetsOverview = (): JSX.Element => {
1919
!transparentTokensQuery.isFetched);
2020

2121
return (
22-
<Panel className="relative z-10 px-6 rounded-t-none -mt-px h-full">
22+
<Panel className="relative px-6 rounded-t-none h-full">
2323
<div className="flex justify-between items-center gap-16 mt-4">
2424
<TotalBalanceCard
2525
balanceInFiat={unshieldedAmountInFiat}
Lines changed: 4 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,6 @@
1-
import { chainTokensAtom } from "atoms/chain/atoms";
2-
import {
3-
getDenomFromIbcTrace,
4-
ibcChannelsFamily,
5-
searchChainByDenom,
6-
} from "atoms/integrations";
7-
import { useAtomValue } from "jotai";
8-
9-
const Warning = ({
10-
trace,
11-
denom,
12-
}: {
13-
trace: string;
14-
denom: string;
15-
}): JSX.Element => {
16-
const chainName = searchChainByDenom(denom)?.chain_name ?? "";
17-
const { data: ibcChannels } = useAtomValue(ibcChannelsFamily(chainName));
18-
19-
// skip the warning if it's the current open channel
20-
if (
21-
!ibcChannels?.namadaChannel ||
22-
trace.includes(ibcChannels.namadaChannel)
23-
) {
24-
return <></>;
25-
}
1+
import { useIsChannelInactive } from "hooks/useIsChannelInactive";
262

3+
const Warning = ({ trace }: { trace: string }): JSX.Element => {
274
return <div className="text-xs text-neutral-500">inactive: {trace}</div>;
285
};
296

@@ -32,26 +9,7 @@ export const InactiveChannelWarning = ({
329
}: {
3310
address: string;
3411
}): JSX.Element => {
35-
const chainTokens = useAtomValue(chainTokensAtom).data ?? [];
36-
37-
const token = chainTokens.find((i) => i.address === address);
38-
if (!token || !("trace" in token)) {
39-
return <></>;
40-
}
41-
42-
const denom = getDenomFromIbcTrace(token.trace);
43-
44-
// search for other tokens that contains the same denom
45-
// if find one, but with different address, shows the warning
46-
for (let i = 0; i < chainTokens.length; i++) {
47-
const otherToken = chainTokens[i];
48-
if ("trace" in otherToken) {
49-
const otherDenom = getDenomFromIbcTrace(otherToken.trace);
50-
if (denom === otherDenom && token.address !== otherToken.address) {
51-
return <Warning trace={token.trace} denom={denom} />;
52-
}
53-
}
54-
}
55-
12+
const { isInactive, trace } = useIsChannelInactive(address);
13+
if (isInactive) return <Warning trace={trace} />;
5614
return <></>;
5715
};

apps/namadillo/src/App/Common/ModalContainer.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ type ModalContainerProps = {
1010
children: React.ReactNode;
1111
containerProps?: HTMLMotionProps<"div">;
1212
contentProps?: React.ComponentPropsWithoutRef<"div">;
13+
headerProps?: React.ComponentPropsWithoutRef<"header">;
1314
};
1415

1516
export const ModalContainer = ({
@@ -18,6 +19,7 @@ export const ModalContainer = ({
1819
children,
1920
contentProps = {},
2021
containerProps = {},
22+
headerProps = {},
2123
}: ModalContainerProps): JSX.Element => {
2224
const { className: containerClassName, ...otherProps } = containerProps;
2325
const { className: contentClassName, ...otherContentProps } = contentProps;
@@ -39,7 +41,10 @@ export const ModalContainer = ({
3941
>
4042
<IoClose />
4143
</i>
42-
<header className="flex w-full justify-center items-center relative mb-0 text-lg text-medium">
44+
<header
45+
className="flex w-full justify-center items-center relative mb-0 text-lg text-medium"
46+
{...headerProps}
47+
>
4348
{header}
4449
</header>
4550
<div

0 commit comments

Comments
 (0)