diff --git a/src/constants/routing.ts b/src/constants/routing.ts index f17b39fd0c..0f56af2e61 100644 --- a/src/constants/routing.ts +++ b/src/constants/routing.ts @@ -1,5 +1,5 @@ export enum Subdirectory { - DASHBOARD = '/', + DASHBOARD = '', ACCOUNT = '/account', XVS = '/xvs', CORE_POOL = '/core-pool', diff --git a/src/containers/Layout/Breadcrumbs/__snapshots__/index.spec.tsx.snap b/src/containers/Layout/Breadcrumbs/__tests__/__snapshots__/index.spec.tsx.snap similarity index 83% rename from src/containers/Layout/Breadcrumbs/__snapshots__/index.spec.tsx.snap rename to src/containers/Layout/Breadcrumbs/__tests__/__snapshots__/index.spec.tsx.snap index 5d417145f4..4909380e59 100644 --- a/src/containers/Layout/Breadcrumbs/__snapshots__/index.spec.tsx.snap +++ b/src/containers/Layout/Breadcrumbs/__tests__/__snapshots__/index.spec.tsx.snap @@ -1,9 +1,11 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`component/Layout/Header/Breadcrumbs > outputs the right DOM based on the current path: / 1`] = `"Dashboard"`; +exports[`component/Layout/Header/Breadcrumbs > outputs the right DOM based on the current path: 1`] = `"Dashboard"`; exports[`component/Layout/Header/Breadcrumbs > outputs the right DOM based on the current path: /account 1`] = `"Account"`; +exports[`component/Layout/Header/Breadcrumbs > outputs the right DOM based on the current path: /account/prime-simulator 1`] = `"Account/Prime simulator"`; + exports[`component/Layout/Header/Breadcrumbs > outputs the right DOM based on the current path: /convert-vrt 1`] = `"Convert VRT"`; exports[`component/Layout/Header/Breadcrumbs > outputs the right DOM based on the current path: /core-pool 1`] = `"Core pool"`; @@ -26,10 +28,14 @@ exports[`component/Layout/Header/Breadcrumbs > outputs the right DOM based on th exports[`component/Layout/Header/Breadcrumbs > outputs the right DOM based on the current path: /isolated-pools/pool/0x3d759121234cd36F8124C21aFe1c6852d2bEd848/market/0x6d6F697e34145Bb95c54E77482d97cc261Dc237E 1`] = `"Isolated pools/Venus/XVS"`; +exports[`component/Layout/Header/Breadcrumbs > outputs the right DOM based on the current path: /prime-simulator 1`] = `"Dashboard/Prime simulator"`; + exports[`component/Layout/Header/Breadcrumbs > outputs the right DOM based on the current path: /swap 1`] = `"Swap"`; exports[`component/Layout/Header/Breadcrumbs > outputs the right DOM based on the current path: /vai 1`] = `"VAI"`; exports[`component/Layout/Header/Breadcrumbs > outputs the right DOM based on the current path: /vaults 1`] = `"Vaults"`; +exports[`component/Layout/Header/Breadcrumbs > outputs the right DOM based on the current path: /vaults/prime-simulator 1`] = `"Vaults/Prime simulator"`; + exports[`component/Layout/Header/Breadcrumbs > outputs the right DOM based on the current path: /xvs 1`] = `"XVS"`; diff --git a/src/containers/Layout/Breadcrumbs/index.spec.tsx b/src/containers/Layout/Breadcrumbs/__tests__/index.spec.tsx similarity index 89% rename from src/containers/Layout/Breadcrumbs/index.spec.tsx rename to src/containers/Layout/Breadcrumbs/__tests__/index.spec.tsx index 0ad75fb8b3..2f512e6368 100644 --- a/src/containers/Layout/Breadcrumbs/index.spec.tsx +++ b/src/containers/Layout/Breadcrumbs/__tests__/index.spec.tsx @@ -8,7 +8,7 @@ import { renderComponent } from 'testUtils/render'; import { useGetPool, useGetVTokens } from 'clients/api'; import { routes } from 'constants/routing'; -import { Breadcrumbs } from '.'; +import { Breadcrumbs } from '..'; describe('component/Layout/Header/Breadcrumbs', () => { beforeEach(() => { @@ -59,6 +59,9 @@ describe('component/Layout/Header/Breadcrumbs', () => { [routes.vaults.path, routes.vaults.path], [routes.convertVrt.path, routes.convertVrt.path], [routes.swap.path, routes.swap.path], + [routes.accountPrimeSimulator.path, routes.accountPrimeSimulator.path], + [routes.dashboardPrimeSimulator.path, routes.dashboardPrimeSimulator.path], + [routes.vaultsPrimeSimulator.path, routes.vaultsPrimeSimulator.path], ])('outputs the right DOM based on the current path: %s', async (pathname, originalRoute) => { const { container } = renderComponent(, { routerInitialEntries: [pathname], diff --git a/src/containers/Layout/Breadcrumbs/index.tsx b/src/containers/Layout/Breadcrumbs/index.tsx index eea524033c..13e3d7f924 100644 --- a/src/containers/Layout/Breadcrumbs/index.tsx +++ b/src/containers/Layout/Breadcrumbs/index.tsx @@ -130,6 +130,9 @@ export const Breadcrumbs: React.FC = () => { case Subdirectory.VAI: dom = t('breadcrumbs.vai'); break; + case Subdirectory.PRIME_SIMULATOR: + dom = t('breadcrumbs.primeSimulator'); + break; default: break; } diff --git a/src/containers/MarketTable/Apy/ApyWithPrimeSimulationBoost/index.tsx b/src/containers/MarketTable/Apy/ApyWithPrimeSimulationBoost/index.tsx index ccd48eff55..397d35c6b3 100644 --- a/src/containers/MarketTable/Apy/ApyWithPrimeSimulationBoost/index.tsx +++ b/src/containers/MarketTable/Apy/ApyWithPrimeSimulationBoost/index.tsx @@ -1,7 +1,7 @@ import { Icon, Link, Tooltip } from 'components'; -import { PRIME_DOC_URL } from 'constants/prime'; import useFormatPercentageToReadableValue from 'hooks/useFormatPercentageToReadableValue'; import useFormatTokensToReadableValue from 'hooks/useFormatTokensToReadableValue'; +import { usePrimeSimulationPagePath } from 'hooks/usePrimeSimulationPagePath'; import { useTranslation } from 'packages/translations'; import { PrimeSimulationDistribution, Token } from 'types'; @@ -21,6 +21,7 @@ export const ApyWithPrimeSimulationBoost: React.FC { const { t, Trans } = useTranslation(); + const primeSimulationPageUrl = usePrimeSimulationPagePath(); const readablePrimeApy = useFormatPercentageToReadableValue({ value: primeSimulationDistribution.apyPercentage, @@ -69,7 +70,7 @@ export const ApyWithPrimeSimulationBoost: React.FC e.stopPropagation()} />, + Link: e.stopPropagation()} />, }} /> } diff --git a/src/containers/PrimeStatusBanner/index.tsx b/src/containers/PrimeStatusBanner/index.tsx index 6483666ba7..1b6f120323 100644 --- a/src/containers/PrimeStatusBanner/index.tsx +++ b/src/containers/PrimeStatusBanner/index.tsx @@ -11,10 +11,10 @@ import { useGetXvsVaultUserInfo, } from 'clients/api'; import { Card, Link, PrimaryButton, ProgressBar } from 'components'; -import { PRIME_DOC_URL } from 'constants/prime'; import { routes } from 'constants/routing'; import useFormatPercentageToReadableValue from 'hooks/useFormatPercentageToReadableValue'; import useConvertMantissaToReadableTokenString from 'hooks/useFormatTokensToReadableValue'; +import { usePrimeSimulationPagePath } from 'hooks/usePrimeSimulationPagePath'; import { displayMutationError } from 'packages/errors'; import { useGetToken } from 'packages/tokens'; import { useTranslation } from 'packages/translations'; @@ -146,6 +146,8 @@ export const PrimeStatusBannerUi: React.FC = ({ t, ]); + const primeSimulationPageUrl = usePrimeSimulationPagePath(); + const displayProgress = !isUserXvsStakeHighEnoughForPrime; const displayWarning = haveAllPrimeTokensBeenClaimed; const displayStakeButton = @@ -218,7 +220,7 @@ export const PrimeStatusBannerUi: React.FC = ({ i18nKey="primeStatusBanner.description" components={{ WhiteText: , - Link: , + Link: , }} values={{ stakeDelta: readableStakeDeltaTokens, diff --git a/src/hooks/usePrimeSimulationPagePath/__tests__/index.spec.tsx b/src/hooks/usePrimeSimulationPagePath/__tests__/index.spec.tsx new file mode 100644 index 0000000000..834eee3fe6 --- /dev/null +++ b/src/hooks/usePrimeSimulationPagePath/__tests__/index.spec.tsx @@ -0,0 +1,35 @@ +import { matchPath, useLocation } from 'react-router'; +import Vi from 'vitest'; + +import { renderHook } from 'testUtils/render'; + +import { routes } from 'constants/routing'; + +import { usePrimeSimulationPagePath } from '..'; + +vi.mock('react-router', () => ({ + ...vi.importActual('react-router'), + useLocation: vi.fn(), + matchPath: vi.fn(), +})); + +describe('usePrimeSimulationPagePath', () => { + beforeEach(() => { + (matchPath as Vi.Mock).mockImplementation((a, b) => a === b); + }); + + it.each([ + { pathname: routes.account.path, expectedResult: routes.accountPrimeSimulator.path }, + { pathname: routes.vaults.path, expectedResult: routes.vaultsPrimeSimulator.path }, + { pathname: '/fake/path', expectedResult: routes.dashboardPrimeSimulator.path }, + ])( + 'should return the right path based on the current location %s', + ({ pathname, expectedResult }) => { + (useLocation as Vi.Mock).mockImplementation(() => ({ pathname })); + + const { result } = renderHook(() => usePrimeSimulationPagePath()); + + expect(result.current).toBe(expectedResult); + }, + ); +}); diff --git a/src/hooks/usePrimeSimulationPagePath/index.tsx b/src/hooks/usePrimeSimulationPagePath/index.tsx new file mode 100644 index 0000000000..6ef99b86e3 --- /dev/null +++ b/src/hooks/usePrimeSimulationPagePath/index.tsx @@ -0,0 +1,20 @@ +import { useMemo } from 'react'; +import { matchPath, useLocation } from 'react-router'; + +import { routes } from 'constants/routing'; + +export const usePrimeSimulationPagePath = () => { + const { pathname } = useLocation(); + + return useMemo(() => { + if (matchPath(routes.account.path, pathname)) { + return routes.accountPrimeSimulator.path; + } + + if (matchPath(routes.vaults.path, pathname)) { + return routes.vaultsPrimeSimulator.path; + } + + return routes.dashboardPrimeSimulator.path; + }, [pathname]); +}; diff --git a/src/packages/translations/translations/en.json b/src/packages/translations/translations/en.json index 8700beb68e..27b2f55de4 100644 --- a/src/packages/translations/translations/en.json +++ b/src/packages/translations/translations/en.json @@ -130,6 +130,7 @@ "isolatedPools": "Isolated pools", "leaderboard": "Leaderboard", "markets": "Markets", + "primeSimulator": "Prime simulator", "proposal": "Proposal #{{proposalId}}", "swap": "Swap", "vai": "VAI", @@ -184,7 +185,7 @@ "title": "Connect your wallet" }, "primePromotionalBanner": { - "buttonLabel": "Learn more", + "buttonLabel": "Calculate your Prime rewards", "description": "Venus Prime and the Venus Prime Token reward dedicated users of Venus with real yield for superior rates with their lending and borrowing activities.", "illustration": { "alt": "Prime promotional banner" @@ -398,7 +399,7 @@ }, "primeSimulationBoost": { "label": "{{apyPrimeBoost}} Prime boost", - "tooltip": "Prime boost based on the median user supply of {{supplyBalance}}, borrow of {{borrowBalance}} and vault stake of {{xvsStaked}}. Learn more about Prime" + "tooltip": "Prime boost based on the median user supply of {{supplyBalance}}, borrow of {{borrowBalance}} and vault stake of {{xvsStaked}}. Calculate your Prime rewards" } }, "columnKeys": { @@ -566,7 +567,7 @@ "primeStatusBanner": { "becomePrimeTitle": "You can now become a Prime user", "claimButtonLabel": "Claim Prime token", - "description": "Stake {{stakeDelta}} more then wait {{claimWaitingPeriod}} to claim your Prime token and boost your earnings. Learn more", + "description": "Stake {{stakeDelta}} more then wait {{claimWaitingPeriod}} to claim your Prime token and boost your earnings. Calculate your Prime rewards", "noPrimeTokenWarning": { "text": "All Prime tokens have been claimed", "tooltip": "All {{primeTokenLimit}} Prime tokens are currently claimed. Some may become available if owners no longer meet the eligibility criteria or if we add more." diff --git a/src/pages/Dashboard/Banner/PrimePromotionalBanner/index.tsx b/src/pages/Dashboard/Banner/PrimePromotionalBanner/index.tsx index 0abf1b503b..48a52a8f09 100644 --- a/src/pages/Dashboard/Banner/PrimePromotionalBanner/index.tsx +++ b/src/pages/Dashboard/Banner/PrimePromotionalBanner/index.tsx @@ -1,5 +1,5 @@ import { ButtonWrapper, Card, Icon, Link } from 'components'; -import { PRIME_DOC_URL } from 'constants/prime'; +import { usePrimeSimulationPagePath } from 'hooks/usePrimeSimulationPagePath'; import { useTranslation } from 'packages/translations'; import boostsIllustration from './boostsIllustration.png'; @@ -13,6 +13,7 @@ export interface PrimePromotionalBannerProps { export const PrimePromotionalBanner: React.FC = ({ onHide }) => { const { t, Trans } = useTranslation(); + const primeSimulationPageUrl = usePrimeSimulationPagePath(); return ( @@ -66,7 +67,10 @@ export const PrimePromotionalBanner: React.FC = ({

- + {t('dashboard.primePromotionalBanner.buttonLabel')} diff --git a/src/pages/PrimeSimulator/Form/index.tsx b/src/pages/PrimeSimulator/Form/index.tsx new file mode 100644 index 0000000000..fe5839be70 --- /dev/null +++ b/src/pages/PrimeSimulator/Form/index.tsx @@ -0,0 +1,3 @@ +import { Card } from 'components'; + +export const Form: React.FC = () => Form; diff --git a/src/pages/PrimeSimulator/RewardDetails/index.tsx b/src/pages/PrimeSimulator/RewardDetails/index.tsx new file mode 100644 index 0000000000..7a97b4e0ef --- /dev/null +++ b/src/pages/PrimeSimulator/RewardDetails/index.tsx @@ -0,0 +1,3 @@ +import { Card } from 'components'; + +export const RewardDetails: React.FC = () => RewardDetails; diff --git a/src/pages/PrimeSimulator/index.tsx b/src/pages/PrimeSimulator/index.tsx index ea005546f5..be2e9e0281 100644 --- a/src/pages/PrimeSimulator/index.tsx +++ b/src/pages/PrimeSimulator/index.tsx @@ -1,3 +1,12 @@ -const PrimeSimulator: React.FC = () => <>Prime Simulator; +import { Form } from './Form'; +import { RewardDetails } from './RewardDetails'; + +const PrimeSimulator: React.FC = () => ( +
+
+ + +
+); export default PrimeSimulator;