Skip to content

Commit

Permalink
Mattupham/fe 726 porfolio v3 alloyed convert button deposit withdraw …
Browse files Browse the repository at this point in the history
…dropdown (#3841)

* Add convert button

* Add convert button

* Clean up

* Handle feature via flag

* Update icons

* Clean up

* Clean up

* i18n

* Extract functionality

* Extract type

* Clean up comments

* Refactor icon

* Clean up styles

* Update types
  • Loading branch information
mattupham authored Sep 20, 2024
1 parent 62531de commit 6db052a
Show file tree
Hide file tree
Showing 20 changed files with 274 additions and 60 deletions.
208 changes: 166 additions & 42 deletions packages/web/components/table/asset-balances.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Popover, PopoverButton, PopoverPanel } from "@headlessui/react";
import { Dec } from "@keplr-wallet/unit";
import type { Search } from "@osmosis-labs/server";
import type { SortDirection } from "@osmosis-labs/utils";
Expand All @@ -12,7 +13,7 @@ import { useWindowVirtualizer } from "@tanstack/react-virtual";
import classNames from "classnames";
import { observer } from "mobx-react-lite";
import Link from "next/link";
import { useRouter } from "next/router";
import { NextRouter, useRouter } from "next/router";
import {
FunctionComponent,
useCallback,
Expand All @@ -23,6 +24,8 @@ import {
import { useLocalStorage } from "react-use";

import { AssetCell } from "~/components/table/cells/asset";
import { SpriteIconId } from "~/config";
import { MultiLanguageT } from "~/hooks";
import {
Breakpoint,
useFeatureFlags,
Expand Down Expand Up @@ -56,6 +59,8 @@ type SortKey = NonNullable<
RouterInputs["edge"]["assets"]["getUserBridgeAssets"]["sort"]
>["keyPath"];

type Action = "deposit" | "withdraw" | "trade" | "earn";

const DUST_THRESHOLD = new Dec(0.01);

export const AssetBalancesTable: FunctionComponent<{
Expand All @@ -70,8 +75,6 @@ export const AssetBalancesTable: FunctionComponent<{
const { t } = useTranslation();
const featureFlags = useFeatureFlags();

// State

// search
const [searchQuery, setSearchQuery] = useState<Search | undefined>();
const onSearchInput = useCallback((input: string) => {
Expand Down Expand Up @@ -490,6 +493,48 @@ const PriceCell: AssetCellComponent = ({ currentPrice, priceChange24h }) => (
</div>
);

const getActionOptions = (t: MultiLanguageT, showConvertButton: boolean) => {
return [
...(showConvertButton
? [
{ key: "deposit", label: t("portfolio.deposit"), icon: "deposit" },
{ key: "withdraw", label: t("portfolio.withdraw"), icon: "withdraw" },
]
: []),
{ key: "trade", label: t("portfolio.trade"), icon: "arrows-swap" },
{ key: "earn", label: t("portfolio.earn"), icon: "chart-up" },
] as Array<{ key: Action; label: string; icon: SpriteIconId }>;
};

const handleSelectAction = (
action: Action,
coinDenom: string,
router: NextRouter,
bridgeAsset: ({
anyDenom,
direction,
}: {
anyDenom: string | undefined;
direction: "deposit" | "withdraw" | undefined;
}) => void
) => {
if (action === "trade") {
router.push(`/assets/${coinDenom}`);
} else if (action === "earn") {
router.push(`/earn?search=${coinDenom}`);
} else if (action === "deposit") {
bridgeAsset({
anyDenom: coinDenom,
direction: "deposit",
});
} else if (action === "withdraw") {
bridgeAsset({
anyDenom: coinDenom,
direction: "withdraw",
});
}
};

export const AssetActionsCell: AssetCellComponent<{
showUnverifiedAssetsSetting?: boolean;
confirmUnverifiedAsset: (asset: {
Expand All @@ -499,69 +544,148 @@ export const AssetActionsCell: AssetCellComponent<{
}> = ({
coinDenom,
coinImageUrl,
amount,
isVerified,
showUnverifiedAssetsSetting,
confirmUnverifiedAsset,
coinMinimalDenom,
variantGroupKey,
}) => {
const { t } = useTranslation();
const router = useRouter();
const featureFlags = useFeatureFlags();

const bridgeAsset = useBridgeStore((state) => state.bridgeAsset);

const needsActivation = !isVerified && !showUnverifiedAssetsSetting;
const needsConversion = coinMinimalDenom !== variantGroupKey;
const showConvertButton = featureFlags.alloyedAssets && needsConversion;

const actionOptions = getActionOptions(t, showConvertButton);

return (
<div className="flex items-center justify-end gap-2 text-wosmongton-200">
{needsActivation && (
<Button
variant="ghost"
className="flex gap-2 text-wosmongton-200 hover:text-rust-200"
className="flex gap-2 rounded-[48px] text-wosmongton-200 hover:text-rust-200"
onClick={(e) => {
e.stopPropagation();
e.preventDefault();

confirmUnverifiedAsset({ coinDenom, coinImageUrl });
}}
>
{t("assets.table.activate")}
</Button>
)}
<div className="flex gap-3 md:hidden">
{!needsActivation && (
<Button
size="icon"
variant="secondary"
className="bg-osmoverse-alpha-850 hover:bg-osmoverse-alpha-800"
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
bridgeAsset({
anyDenom: coinDenom,
direction: "deposit",
});
}}
>
<Icon id="deposit" height={20} width={20} />
</Button>
)}
{!needsActivation && amount?.toDec().isPositive() && (
<Button
size="icon"
variant="secondary"
className="bg-osmoverse-alpha-850 hover:bg-osmoverse-alpha-800"
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
bridgeAsset({
anyDenom: coinDenom,
direction: "withdraw",
});
}}
>
<Icon id="withdraw" height={20} width={20} />
</Button>
)}
</div>
{!needsActivation && (
<div className="flex gap-3 md:hidden">
{showConvertButton ? (
<Button
variant="secondary"
className="max-h-12 w-[108px] rounded-[48px] bg-osmoverse-alpha-850 hover:bg-osmoverse-alpha-800"
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
// TODO - open conversion modal once clicked
alert("Convert clicked");
}}
>
{t("portfolio.convert")}
</Button>
) : (
<>
<Button
size="icon"
variant="secondary"
className="bg-osmoverse-alpha-850 hover:bg-osmoverse-alpha-800"
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
bridgeAsset({
anyDenom: coinDenom,
direction: "deposit",
});
}}
>
<Icon id="deposit" height={20} width={20} />
</Button>
<Button
size="icon"
variant="secondary"
className="bg-osmoverse-alpha-850 hover:bg-osmoverse-alpha-800"
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
bridgeAsset({
anyDenom: coinDenom,
direction: "withdraw",
});
}}
>
<Icon id="withdraw" height={20} width={20} />
</Button>
</>
)}
<AssetActionsDropdown
actionOptions={actionOptions}
onSelectAction={(action) =>
handleSelectAction(action, coinDenom, router, bridgeAsset)
}
/>
</div>
)}
</div>
);
};

const AssetActionsDropdown: FunctionComponent<{
actionOptions: {
key: Action;
label: string;
icon: SpriteIconId;
}[];
onSelectAction: (key: Action) => void;
}> = ({ actionOptions, onSelectAction }) => {
return (
<Popover className="relative shrink-0">
{() => (
<>
<PopoverButton as={Button} size="icon" variant="ghost">
<Icon id="dots-three-vertical" width={24} height={24} />
</PopoverButton>

<PopoverPanel className="absolute right-0 z-50 mt-3 w-[320px]">
{({ close }) => (
<div className="flex flex-col gap-3 rounded-2xl border border-osmoverse-700 bg-osmoverse-825 p-2">
{actionOptions.map(({ key, label, icon }) => (
<button
key={key}
className="body2 flex place-content-between items-center gap-2 rounded-full !px-3 !py-1 text-osmoverse-200 hover:bg-osmoverse-700"
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
onSelectAction(key);
close();
}}
>
<span className="subtitle1 flex items-center gap-3 whitespace-nowrap text-white-full">
<span className="flex h-10 w-10 items-center justify-center">
<Icon
id={icon}
width={24}
height={24}
className="text-wosmongton-300"
/>
</span>
{label}
</span>
</button>
))}
</div>
)}
</PopoverPanel>
</>
)}
</Popover>
);
};
4 changes: 3 additions & 1 deletion packages/web/hooks/use-feature-flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export type AvailableFlags =
| "cypherCard"
| "newPortfolioPage"
| "inGivenOut"
| "sqsActiveOrders";
| "sqsActiveOrders"
| "alloyedAssets";

const defaultFlags: Record<AvailableFlags, boolean> = {
staking: true,
Expand All @@ -58,6 +59,7 @@ const defaultFlags: Record<AvailableFlags, boolean> = {
newPortfolioPage: false,
inGivenOut: false,
sqsActiveOrders: false,
alloyedAssets: false,
};

const LIMIT_ORDER_COUNTRY_CODES =
Expand Down
7 changes: 6 additions & 1 deletion packages/web/localizations/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,12 @@
"last7d": "Letzte 7 Tage",
"last30d": "Letzte 30 Tage",
"last1y": "Letztes 1 Jahr",
"allTime": "Alle Zeit"
"allTime": "Alle Zeit",
"trade": "Handel",
"earn": "Verdienen",
"deposit": "Kaution",
"withdraw": "Zurückziehen",
"convert": "Konvertieren"
},
"buyTokens": "Kaufen Sie Token",
"components": {
Expand Down
7 changes: 6 additions & 1 deletion packages/web/localizations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,12 @@
"last7d": "Last 7d",
"last30d": "Last 30d",
"last1y": "Last 1y",
"allTime": "All time"
"allTime": "All time",
"trade": "Trade",
"earn": "Earn",
"deposit": "Deposit",
"withdraw": "Withdraw",
"convert": "Convert"
},
"buyTokens": "Buy tokens",
"components": {
Expand Down
7 changes: 6 additions & 1 deletion packages/web/localizations/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,12 @@
"last7d": "Últimos 7 días",
"last30d": "Últimos 30 días",
"last1y": "Último 1 año",
"allTime": "Todo el tiempo"
"allTime": "Todo el tiempo",
"trade": "Comercio",
"earn": "Ganar",
"deposit": "Depósito",
"withdraw": "Retirar",
"convert": "Convertir"
},
"buyTokens": "Comprar fichas",
"components": {
Expand Down
7 changes: 6 additions & 1 deletion packages/web/localizations/fa.json
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,12 @@
"last7d": "7 روز گذشته",
"last30d": "30 روز گذشته",
"last1y": "1 سال گذشته",
"allTime": "تمام زمان"
"allTime": "تمام زمان",
"trade": "تجارت",
"earn": "کسب درآمد",
"deposit": "سپرده گذاری",
"withdraw": "برداشت",
"convert": "تبدیل کنید"
},
"buyTokens": "خرید توکن",
"components": {
Expand Down
7 changes: 6 additions & 1 deletion packages/web/localizations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,12 @@
"last7d": "Derniers 7 jours",
"last30d": "Les 30 derniers jours",
"last1y": "Dernière année",
"allTime": "Tout le temps"
"allTime": "Tout le temps",
"trade": "Commerce",
"earn": "Gagner",
"deposit": "Dépôt",
"withdraw": "Retirer",
"convert": "Convertir"
},
"buyTokens": "Acheter jetons",
"components": {
Expand Down
7 changes: 6 additions & 1 deletion packages/web/localizations/gu.json
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,12 @@
"last7d": "ગત તા",
"last30d": "છેલ્લા 30 ડી",
"last1y": "છેલ્લા 1 વર્ષ",
"allTime": "બધા સમય"
"allTime": "બધા સમય",
"trade": "વેપાર",
"earn": "કમાઓ",
"deposit": "જમા",
"withdraw": "ઉપાડો",
"convert": "કન્વર્ટ કરો"
},
"buyTokens": "ટોકન્સ ખરીદો",
"components": {
Expand Down
7 changes: 6 additions & 1 deletion packages/web/localizations/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,12 @@
"last7d": "अंतिम 7 दिन",
"last30d": "अंतिम 30 दिन",
"last1y": "पिछले 1 वर्ष",
"allTime": "पूरे समय"
"allTime": "पूरे समय",
"trade": "व्यापार",
"earn": "कमाना",
"deposit": "जमा",
"withdraw": "निकालना",
"convert": "बदलना"
},
"buyTokens": "टोकन खरीदें",
"components": {
Expand Down
Loading

0 comments on commit 6db052a

Please sign in to comment.