Skip to content

Commit

Permalink
Cleanup portfolio components (#1658)
Browse files Browse the repository at this point in the history
* Cleanup portfolio components

* Unnest, link to regex101 in comment, switch to ExternalLink
  • Loading branch information
DannyDelott authored Nov 18, 2024
1 parent 92676c9 commit 9a4e691
Show file tree
Hide file tree
Showing 12 changed files with 402 additions and 372 deletions.
6 changes: 3 additions & 3 deletions apps/hyperdrive-trading/src/ui/portfolio/Portfolio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { useNavigate, useSearch } from "@tanstack/react-router";
import { ReactElement } from "react";
import { Tabs } from "src/ui/base/components/Tabs/Tabs";
import { useFeatureFlag } from "src/ui/base/featureFlags/featureFlags";
import { OpenLongsContainer } from "src/ui/portfolio/longs/OpenLongsTable/OpenLongsTableDesktop";
import { LpAndWithdrawalSharesContainer } from "src/ui/portfolio/lp/LpAndWithdrawalSharesTable/LpAndWithdrawalSharesTable";
import { OpenLongsContainer } from "src/ui/portfolio/longs/LongsContainer";
import { LpAndWithdrawalSharesContainer } from "src/ui/portfolio/lp/LpAndWithdrawalSharesContainer";
import { PORTFOLIO_ROUTE } from "src/ui/portfolio/routes";
import { OpenShortsContainer } from "src/ui/portfolio/shorts/OpenShortsTable/OpenShortsTableDesktop";
import { OpenShortsContainer } from "src/ui/portfolio/shorts/ShortsContainer";

export function Portfolio(): ReactElement {
const { position } = useSearch({ from: PORTFOLIO_ROUTE });
Expand Down
13 changes: 13 additions & 0 deletions apps/hyperdrive-trading/src/ui/portfolio/PositionContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import classNames from "classnames";
import { PropsWithChildren, ReactElement } from "react";

export function PositionContainer({
className,
children,
}: PropsWithChildren<{ className?: string }>): ReactElement {
return (
<div className={classNames("flex w-[1036px] flex-col gap-10", className)}>
{children}
</div>
);
}
29 changes: 29 additions & 0 deletions apps/hyperdrive-trading/src/ui/portfolio/PositionTableHeading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { HyperdriveConfig } from "@delvtech/hyperdrive-appconfig";
import { ReactElement, ReactNode } from "react";
import { AssetStack } from "src/ui/markets/AssetStack";

export function PositionTableHeading({
hyperdrive,
hyperdriveName,
rightElement,
}: {
hyperdrive: HyperdriveConfig;
/**
* Optional name to override the name from the hyperdrive
*/
hyperdriveName?: string;
rightElement: ReactNode;
}): ReactElement {
return (
<div className="flex items-center justify-between">
<div className="flex items-center gap-1 font-chakraPetch text-h4">
<AssetStack
hyperdriveAddress={hyperdrive.address}
hyperdriveChainId={hyperdrive.chainId}
/>
<p className="text-h4">{hyperdriveName ?? hyperdrive.name}</p>
</div>
{rightElement}
</div>
);
}
114 changes: 114 additions & 0 deletions apps/hyperdrive-trading/src/ui/portfolio/longs/LongsContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { appConfig, HyperdriveConfig } from "@delvtech/hyperdrive-appconfig";
import { Link } from "@tanstack/react-router";
import { ReactElement } from "react";
import { ExternalLink } from "src/ui/analytics/ExternalLink";
import LoadingState from "src/ui/base/components/LoadingState";
import { NonIdealState } from "src/ui/base/components/NonIdealState";
import { ConnectWalletButton } from "src/ui/compliance/ConnectWallet";
import { OpenLongsTableDesktop } from "src/ui/portfolio/longs/OpenLongsTable/OpenLongsTableDesktop";
import { TotalOpenLongsValue } from "src/ui/portfolio/longs/TotalOpenLongsValue/TotalOpenLongsValue";
import {
OpenLongPositionsData,
usePortfolioLongsData,
} from "src/ui/portfolio/longs/usePortfolioLongsData";
import { PositionContainer } from "src/ui/portfolio/PositionContainer";
import { PositionTableHeading } from "src/ui/portfolio/PositionTableHeading";
import { useAccount } from "wagmi";

export function OpenLongsContainer(): ReactElement {
const { address: account } = useAccount();
const { openLongPositions, openLongPositionsStatus } =
usePortfolioLongsData();
if (!account) {
return (
<PositionContainer className="my-28">
<NonIdealState
heading="No wallet connected"
action={<ConnectWalletButton />}
/>
</PositionContainer>
);
}

if (openLongPositionsStatus === "loading") {
return (
<PositionContainer>
<LoadingState
heading="Loading your Longs..."
text="Searching for Long events, calculating current value and PnL..."
/>
</PositionContainer>
);
}

if (openLongPositions?.every((position) => !position.openLongs.length)) {
return (
<PositionContainer className="my-28">
<NonIdealState
heading="No Longs found"
text={
<p className="max-w-xl">
Visit the{" "}
<ExternalLink
href="https://docs.hyperdrive.box/hyperdrive-overview/position-types/longs-fixed-rates"
newTab
>
documentation
</ExternalLink>{" "}
or explore pools to open your first Long position.
</p>
}
action={
<Link className="daisy-btn daisy-btn-primary rounded-full" to="/">
View Pools
</Link>
}
/>
</PositionContainer>
);
}

return (
<PositionContainer className="mt-10">
{openLongPositions &&
appConfig.hyperdrives
.filter((hyperdrive) => {
const openLongs = findOpenLongs(
openLongPositions,
hyperdrive,
)?.openLongs;
// Ensure this hyperdrive pool has open positions before rendering.
return openLongPositionsStatus === "success" && openLongs?.length;
})
.map((hyperdrive) => {
const openLongs = findOpenLongs(
openLongPositions,
hyperdrive,
)?.openLongs;
return (
<div className="flex flex-col gap-6" key={hyperdrive.address}>
<PositionTableHeading
hyperdrive={hyperdrive}
rightElement={<TotalOpenLongsValue hyperdrive={hyperdrive} />}
/>
<OpenLongsTableDesktop
hyperdrive={hyperdrive}
openLongs={openLongs}
/>
</div>
);
})}
</PositionContainer>
);
}

function findOpenLongs(
openLongPositions: OpenLongPositionsData,
hyperdrive: HyperdriveConfig,
) {
return openLongPositions.find(
(position) =>
position.hyperdrive.address === hyperdrive.address &&
position.hyperdrive.chainId === hyperdrive.chainId,
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@ import {
AppConfig,
appConfig,
getBaseToken,
getToken,
HyperdriveConfig,
} from "@delvtech/hyperdrive-appconfig";
import {
calculateAprFromPrice,
OpenLongPositionReceived,
} from "@delvtech/hyperdrive-js";
import { ChevronDownIcon, ChevronUpIcon } from "@heroicons/react/24/outline";
import { Link } from "@tanstack/react-router";
import {
createColumnHelper,
flexRender,
Expand All @@ -24,7 +22,6 @@ import { ReactElement } from "react";
import { calculateAnnualizedPercentageChange } from "src/base/calculateAnnualizedPercentageChange";
import { convertMillisecondsToDays } from "src/base/convertMillisecondsToDays";
import { formatRate } from "src/base/formatRate";
import LoadingState from "src/ui/base/components/LoadingState";
import { NonIdealState } from "src/ui/base/components/NonIdealState";
import { Pagination } from "src/ui/base/components/Pagination";
import { formatBalance } from "src/ui/base/formatting/formatBalance";
Expand All @@ -33,126 +30,9 @@ import { MaturesOnCell } from "src/ui/hyperdrive/MaturesOnCell/MaturesOnCell";
import { CloseLongModalButton } from "src/ui/hyperdrive/longs/CloseLongModalButton/CloseLongModalButton";
import { StatusCell } from "src/ui/hyperdrive/longs/StatusCell";
import { CurrentValueCell } from "src/ui/portfolio/longs/OpenLongsTable/CurrentValueCell";
import { TotalOpenLongsValue } from "src/ui/portfolio/longs/OpenLongsTable/TotalOpenLongsValue";
import { usePortfolioLongsData } from "src/ui/portfolio/longs/usePortfolioLongsData";
import { useAccount } from "wagmi";
import { ManageLongsButton } from "./ManageLongsButton";

export function OpenLongsContainer(): ReactElement {
const { address: account } = useAccount();
const { openLongPositions, openLongPositionsStatus } =
usePortfolioLongsData();
if (!account) {
return (
<div className="my-28 flex w-[1036px] flex-col gap-10">
<NonIdealState
heading="No wallet connected"
action={<ConnectWalletButton />}
/>
</div>
);
}

if (openLongPositionsStatus === "loading") {
return (
<div className="flex w-[1036px] flex-col gap-10">
<LoadingState
heading="Loading your Longs..."
text="Searching for Long events, calculating current value and PnL..."
/>
</div>
);
}

if (openLongPositions?.every((position) => position.openLongs.length === 0)) {
return (
<div className="my-28 flex w-[1036px] flex-col gap-10">
<NonIdealState
heading="No Longs found"
text={
<p className="max-w-xl">
Visit the{" "}
<a
className="daisy-link"
href="https://docs.hyperdrive.box/hyperdrive-overview/position-types/longs-fixed-rates"
rel="noopener noreferrer"
target="_blank"
>
documentation
</a>{" "}
or explore pools to open your first Long position.
</p>
}
action={
<Link className="daisy-btn daisy-btn-primary rounded-full" to="/">
View Pools
</Link>
}
/>
</div>
);
}

return (
<div className="mt-10 flex w-[1036px] flex-col gap-10">
{appConfig.hyperdrives.map((hyperdrive) => {
const openLongs = openLongPositions?.find(
(position) =>
position.hyperdrive.address === hyperdrive.address &&
position.hyperdrive.chainId === hyperdrive.chainId,
)?.openLongs;
const baseToken = getBaseToken({
hyperdriveChainId: hyperdrive.chainId,
hyperdriveAddress: hyperdrive.address,
appConfig,
});
const sharesToken = getToken({
chainId: hyperdrive.chainId,
tokenAddress: hyperdrive.poolConfig.vaultSharesToken,
appConfig,
});
// Ensure this hyperdrive pool has open positions before rendering.
if (openLongPositionsStatus === "success" && !openLongs?.length) {
return null;
}
return (
<div className="flex flex-col gap-6" key={hyperdrive.address}>
<div className="flex items-center justify-between">
<div className="flex items-center gap-1 font-chakraPetch text-h4">
<div className="daisy-avatar-group inline-flex justify-center -space-x-6 overflow-visible rtl:space-x-reverse">
{hyperdrive.depositOptions.isBaseTokenDepositEnabled ? (
<div
className="daisy-avatar daisy-tooltip daisy-tooltip-bottom w-12 scale-75 overflow-visible sm:scale-100"
data-tip={baseToken.symbol}
>
<img src={baseToken.iconUrl} className="rounded-full" />
</div>
) : null}
{sharesToken &&
hyperdrive.depositOptions.isShareTokenDepositsEnabled ? (
<div
className="daisy-avatar daisy-tooltip daisy-tooltip-bottom w-12 scale-75 overflow-visible sm:scale-100"
data-tip={sharesToken.symbol}
>
<img src={sharesToken.iconUrl} className="rounded-full" />
</div>
) : null}
</div>
<p className="text-h4">{hyperdrive.name}</p>
</div>
<TotalOpenLongsValue hyperdrive={hyperdrive} />
</div>
<OpenLongsTableDesktop
hyperdrive={hyperdrive}
openLongs={openLongs}
/>
</div>
);
})}
</div>
);
}

export function OpenLongsTableDesktop({
hyperdrive,
openLongs,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { getDrift } from "src/drift/getDrift";
import { useAppConfigForConnectedChain } from "src/ui/appconfig/useAppConfigForConnectedChain";
import { useAccount } from "wagmi";

type OpenLongPositionsData = {
export type OpenLongPositionsData = {
hyperdrive: HyperdriveConfig;
openLongs: OpenLongPositionReceived[];
}[];
Expand Down
Loading

0 comments on commit 9a4e691

Please sign in to comment.