-
Notifications
You must be signed in to change notification settings - Fork 10
[WIP] feat: refactor token pages #246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: preview
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| import ButtonConnectWalletMobile from "../../components/v1/Buttons/ConnectWalletMobile"; | ||
| import Footer from "../../uikit/layout/Footer"; | ||
| import BackgroundGradient from "../ethrisePage/component/BackgroundGradient"; | ||
| import LeveragedTokenBackingCard from "../ethrisePage/component/LeveragedTokenBackingCard"; | ||
| import LeveragedTokenInfoCard from "../ethrisePage/component/LeveragedTokenInfoCard"; | ||
| import TabsContentGrid from "../ethrisePage/component/TabsContentGrid"; | ||
| import VaultInfoCard from "../ethrisePage/component/VaultInfoCard"; | ||
| import { Root as TabsRoot } from "@radix-ui/react-tabs"; | ||
| import PriceInfoCard from "./component/PriceInfoCard"; | ||
| import { useTokenStore } from "./store/tokenStore"; | ||
| import TabsList from "../ethrisePage/component/TabsList"; | ||
| import MyAssetsCardContainer from "./component/MyAssetCard"; | ||
|
|
||
| const MainContent = () => { | ||
| const { state } = useTokenStore(); | ||
| if (state.status === "loaded") { | ||
| const { tokenId: tokenAddress } = state; | ||
| return ( | ||
| <TabsRoot defaultValue="leverage" className="px-4 outline-0 sm:mx-auto"> | ||
| <TabsList /> | ||
| {/* Leverage Tab */} | ||
| <TabsContentGrid value="leverage"> | ||
| {/* Left Column */} | ||
| <PriceInfoCard /> | ||
| {/* Right Column */} | ||
| <div className="flex max-w-[540px] flex-col space-y-6"> | ||
| <MyAssetsCardContainer /> | ||
| <LeveragedTokenInfoCard address={tokenAddress} /> | ||
| <LeveragedTokenBackingCard address={tokenAddress} /> | ||
| </div> | ||
| </TabsContentGrid> | ||
| {/* Lend Tab */} | ||
| <TabsContentGrid value="lend"> | ||
| {/* Left Column */} | ||
| <PriceInfoCard isVault /> | ||
|
|
||
| {/* RightColumn */} | ||
| <div className="max-w-[540px] flex-col space-y-6"> | ||
| <MyAssetsCardContainer isVault={true} /> | ||
| <VaultInfoCard address={tokenAddress} /> | ||
| </div> | ||
| </TabsContentGrid> | ||
| </TabsRoot> | ||
| ); | ||
| } else return <div>loading...</div>; // TODO: loading view ?? | ||
| }; | ||
|
|
||
| function TokenContainer() { | ||
| return ( | ||
| <> | ||
| <div className="mb-20 mt-[76px] flex flex-grow flex-col sm:z-10 sm:mb-0 sm:mt-[120px]"> | ||
| <MainContent /> | ||
| </div> | ||
| <div className="hidden sm:mt-20 sm:inline-block"> | ||
| <Footer /> | ||
| </div> | ||
| <BackgroundGradient /> | ||
| <div className="sm:hidden"> | ||
| <ButtonConnectWalletMobile /> | ||
| </div> | ||
| </> | ||
| ); | ||
| } | ||
|
|
||
| export { TokenContainer }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| import Button from "../../../uikit/buttonV2/Button"; | ||
| import { tokenBalanceFormatter } from "../../../utils/formatters"; | ||
| import { useAssetStore } from "../../tokenPage/store/assetStore"; | ||
|
|
||
| type AssetsItemProps = { | ||
| variant: AssetItemsVariant; | ||
| }; | ||
|
|
||
| const mapper = { | ||
| token: { | ||
| title: "Token Balance", | ||
| image: "/markets/tokenBalanceIcon.svg", | ||
| }, | ||
| value: { | ||
| title: "Value (USDC)", | ||
| image: "/markets/valueIcon.svg", | ||
| }, | ||
| return: { | ||
| title: "Return", | ||
| image: "/markets/returnIcon.svg", | ||
| }, | ||
| returnDollar: { | ||
| title: "Return (USDC)", | ||
| image: "/markets/returnDollarIcon.svg", | ||
| }, | ||
| }; | ||
|
|
||
| type AssetItemsVariant = keyof typeof mapper; | ||
|
|
||
| const AssetsItem = ({ variant }: AssetsItemProps) => { | ||
| const { state } = useAssetStore(); | ||
|
|
||
| const RenderData = () => { | ||
| switch (state.status) { | ||
| case "loading": | ||
| return <p className="h-[16px] w-[100px] animate-pulse rounded-[8px] bg-gray-light-3 dark:bg-gray-dark-3"></p>; | ||
| case "loaded": | ||
| let renderedValue; | ||
| switch (variant) { | ||
| case "value": | ||
| renderedValue = tokenBalanceFormatter.format(state.nav * state.balance); | ||
| break; | ||
| case "token": | ||
| renderedValue = tokenBalanceFormatter.format(state.balance); | ||
| break; | ||
| default: | ||
| renderedValue = "-"; | ||
| } | ||
| return <p className="font-ibm text-sm font-semibold leading-4 tracking-[-.02em] text-gray-light-12 dark:text-gray-dark-12">{renderedValue}</p>; | ||
| case "error": | ||
| return null; | ||
| } | ||
| }; | ||
|
|
||
| return ( | ||
| <div className="flex flex-row"> | ||
| <div className="mr-3 h-8 w-8 rounded-full bg-gray-light-4 text-center leading-9 dark:bg-gray-800 "> | ||
| <img className="mx-auto mt-2" width={16} height={16} src={mapper[variant].image} alt={mapper[variant].image} /> | ||
| </div> | ||
| <div> | ||
| <p className="mb-1 text-sm leading-4 text-gray-light-10 dark:text-gray-dark-10">{mapper[variant].title}</p> | ||
| <RenderData /> | ||
| </div> | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export { AssetsItem }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| import { FunctionComponent, useEffect } from "react"; | ||
| import { useLeveragedTokenNAV } from "../../../components/v1/swr/useLeveragedTokenNAV"; | ||
| import { useTokenBalance } from "../../../components/v1/swr/useTokenBalance"; | ||
| import { useVaultExchangeRate } from "../../../components/v1/swr/useVaultExchangeRate"; | ||
| import { useWalletContext } from "../../../components/v1/Wallet"; | ||
| import ButtonTertiary from "../../../uikit/button/ButtonTertiary"; | ||
| import Button from "../../../uikit/buttonV2/Button"; | ||
| import InformationCard from "../../../uikit/card/InformationCard"; | ||
| import { addTokenToMetamask, tokenType } from "../../../utils/addTokenToMetamask"; | ||
| import { useAssetStore } from "../store/assetStore"; | ||
| import { LoadedData, useTokenStore } from "../store/tokenStore"; | ||
| import { AssetsItem } from "./AssetItem"; | ||
|
|
||
| type MyAssetsCardProps = { | ||
| isVault?: boolean; | ||
| }; | ||
|
|
||
| const MyAssetsCard = ({ state, isVault }: { state: LoadedData; isVault: boolean }) => { | ||
| const { chainId, token: metadata, tokenId } = state; | ||
| const { setValue, setError, state: assetState, setLoading } = useAssetStore(); | ||
|
|
||
| const { account, provider } = useWalletContext(); | ||
| const navResponse = useLeveragedTokenNAV({ token: tokenId, vault: metadata.vaultAddress, provider: provider }, { isPaused: () => !tokenId || !metadata || !provider }); | ||
| const latestVaultExchangeRateResponse = useVaultExchangeRate({ vault: metadata.vaultAddress, provider: provider }, { isPaused: () => !metadata || !provider }); | ||
| const balanceResponse = useTokenBalance({ account: account, token: isVault ? metadata.vaultAddress : tokenId, provider: provider }, { isPaused: () => !tokenId || !metadata || !account }); | ||
|
|
||
| const refetchData = () => { | ||
| setLoading(); | ||
| navResponse.mutate(); | ||
| latestVaultExchangeRateResponse.mutate(); | ||
| balanceResponse.mutate(); | ||
| }; | ||
|
|
||
| useEffect(() => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why we have multiples
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. because it's specific usage. |
||
| if (!account) { | ||
| setError("No account"); | ||
| return; | ||
| } | ||
| }, [account]); | ||
|
|
||
| useEffect(() => { | ||
| if (navResponse.data && latestVaultExchangeRateResponse.data && balanceResponse.data) { | ||
| setValue(navResponse.data, latestVaultExchangeRateResponse.data, balanceResponse.data, metadata); | ||
| } | ||
| }, [navResponse.data, latestVaultExchangeRateResponse.data, balanceResponse.data]); | ||
|
|
||
| useEffect(() => { | ||
| if (navResponse.error || latestVaultExchangeRateResponse.error) { | ||
| setError("Something went wrong"); | ||
| } | ||
| }, [navResponse.error, latestVaultExchangeRateResponse.error]); | ||
|
|
||
| if (assetState.status === "error" && assetState.error === "No account") { | ||
| return null; | ||
| } | ||
| if (assetState.status === "loaded" && assetState.balance === 0) { | ||
| return null; | ||
| } | ||
|
|
||
| return ( | ||
| <InformationCard> | ||
| <div className="pt-4"> | ||
| <h2 className="text-base font-bold leading-4 text-gray-light-12 dark:text-gray-dark-12">My Asset</h2> | ||
| </div> | ||
| {assetState.status !== "error" ? ( | ||
| <> | ||
| <div className="grid grid-cols-2 gap-4"> | ||
| <AssetsItem variant="token" /> | ||
| <AssetsItem variant="value" /> | ||
| <AssetsItem variant="return" /> | ||
| <AssetsItem variant="returnDollar" /> | ||
| </div> | ||
| <ButtonTertiary full onClick={async () => await addTokenToMetamask({ token: tokenType.ETHRISE, chainID: chainId, isVaultToken: isVault })}> | ||
| Add {isVault ? metadata.vaultTitle : metadata.title} to Wallet | ||
| </ButtonTertiary> | ||
| </> | ||
| ) : ( | ||
| <div className="mx-auto text-center text-red-light-10"> | ||
| <p>{assetState.error}</p> | ||
| <Button className="mx-auto mt-2" onClick={refetchData}> | ||
| Retry | ||
| </Button> | ||
| </div> | ||
| )} | ||
| </InformationCard> | ||
| ); | ||
| }; | ||
|
|
||
| const MyAssetsCardContainer: FunctionComponent<MyAssetsCardProps> = ({ isVault = false }) => { | ||
| const { state } = useTokenStore(); | ||
|
|
||
| switch (state.status) { | ||
| case "loaded": | ||
| return <MyAssetsCard state={state} isVault={isVault} />; | ||
| case "loading": | ||
| return null; | ||
| case "error": | ||
| return <Button>Refresh</Button>; | ||
| } | ||
| }; | ||
|
|
||
| export default MyAssetsCardContainer; | ||
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.
Why we need
mutate?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.
because i want to re-fetch data when error appears