Skip to content
This repository has been archived by the owner on Nov 13, 2024. It is now read-only.

Commit

Permalink
Various updates
Browse files Browse the repository at this point in the history
Favourites
Portfolio tweaks
Portfolio sort
Portfolio balance pool links
  • Loading branch information
grctest committed Sep 1, 2024
1 parent f564631 commit 19dabec
Show file tree
Hide file tree
Showing 32 changed files with 551 additions and 74 deletions.
1 change: 1 addition & 0 deletions src/components/CreditOfferEditor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,7 @@ export default function CreditOfferEditor(properties) {
otherAsset={null}
marketSearch={marketSearch}
type={null}
chain={usr.chain}
/>
) : null}
</div>
Expand Down
10 changes: 7 additions & 3 deletions src/components/Market.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ export default function Market(properties) {
marketSearch={marketSearch}
type={activeLimitCard === "buy" ? "quote" : "base"}
size="small"
chain={usr.chain}
/>

<a
Expand All @@ -510,6 +511,7 @@ export default function Market(properties) {
marketSearch={marketSearch}
type={activeLimitCard === "sell" ? "quote" : "base"}
size="small"
chain={usr.chain}
/>
</div>
</CardContent>
Expand Down Expand Up @@ -564,9 +566,11 @@ export default function Market(properties) {
<Card>
<CardHeader className="pb-2 pt-4">
<CardTitle>
{activeLimitCard === "sell"
? t("Market:baseAsset")
: t("Market:quoteAsset")}
{
activeLimitCard === "sell"
? t("Market:baseAsset")
: t("Market:quoteAsset")
}
</CardTitle>
<CardDescription className="text-lg">{t("Market:loading")}</CardDescription>
</CardHeader>
Expand Down
143 changes: 117 additions & 26 deletions src/components/Market/AssetDropDownCard.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useState, useEffect } from "react";
import React, { useState, useEffect, useMemo } from "react";
import Fuse from "fuse.js";
import { FixedSizeList as List } from "react-window";
import { useStore } from '@nanostores/react';
import { useTranslation } from "react-i18next";
import { i18n as i18nInstance, locale } from "@/lib/i18n.js";

Expand All @@ -25,6 +26,12 @@ import {
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";

import {
$favouriteAssets,
addFavouriteAsset,
removeFavouriteAsset,
} from "@/stores/favourites.ts"

/**
* Creating an asset dropdown component
* @param {String} assetSymbol current asset symbol
Expand Down Expand Up @@ -74,38 +81,78 @@ export default function AssetDropDown(properties) {
}, [thisInput]);

const Row = ({ index, style }) => {
const res = thisResult[index];
const res = mode === "search"
? thisResult[index]
: relevantAssets[index];
return (
<div style={{ ...style, marginBottom: "10px", paddingRight: "10px" }}>
<Card
key={`acard-${res.item.id}`}
key={
mode === "search"
? `acard-${res.item.id}`
: `acard-${res.id}`
}
style={{ marginBottom: "2px" }}
onClick={() => {
setTimeout(() => {
storeCallback(res.item.s);
storeCallback(
mode === "search"
? res.item.s
: res.symbol,
);
}, 0);
setDialogOpen(false);
}}
>
<CardHeader className="p-3">
<CardTitle className="h-3">
{res.item.s} ({res.item.id})
{
mode === "search"
? `${res.item.s} (${res.item.id})`
: `${res.symbol} (${res.id})`
}
</CardTitle>
<CardDescription>{t("AssetDropDownCard:issued", { user: res.item.u })}</CardDescription>
<CardDescription>
{t(
"AssetDropDownCard:issued",
{ user: mode === "search" ? res.item.u : res.issuer }
)}
</CardDescription>
</CardHeader>
</Card>
</div>
);
};

const [mode, setMode] = useState("search");

const favouriteAssets = useStore($favouriteAssets);

const relevantAssets = useMemo(() => {
if (!chain || !favouriteAssets) {
return [];
}

const _chainAssets = favouriteAssets[chain];

if (!assetSymbol && !otherAsset) {
return _chainAssets;
}

return _chainAssets.filter(
(asset) => assetSymbol && otherAsset
? asset.symbol !== assetSymbol && asset.symbol !== otherAsset
: asset.symbol !== assetSymbol
);
}, [favouriteAssets, assetSymbol, otherAsset, chain]);

return (
<Dialog
open={dialogOpen}
onOpenChange={(open) => {
if (!open) {
setThisResult();
}

setDialogOpen(open);
}}
>
Expand All @@ -128,25 +175,69 @@ export default function AssetDropDown(properties) {
? t("AssetDropDownCard:replacing", { assetSymbol: assetSymbol })
: t("AssetDropDownCard:selecting")}
</h3>
<h4 className="text-md font-bold tracking-tight">
{!type ? t("AssetDropDownCard:noType") : null}
{type && type === "base" ? t("AssetDropDownCard:baseType") : null}
{type && type === "quote" ? t("AssetDropDownCard:quoteType") : null}
</h4>
<Input
name="assetSearch"
placeholder={t("AssetDropDownCard:search")}
onChange={(event) => {
setThisInput(event.target.value);
}}
/>
{thisResult && thisResult.length ? (
<>
<List height={200} itemCount={thisResult.length} itemSize={70} className="w-full">
{Row}
</List>
</>
) : null}

<div className="grid grid-cols-2 gap-2">
<Button
variant={mode === "search" ? "" : "outline"}
size="sm"
onClick={() => setMode("search")}
>
{t("AssetDropDownCard:search")}
</Button>
<Button
variant={mode === "favourites" ? "" : "outline"}
size="sm"
onClick={() => setMode("favourites")}
>
{t("AssetDropDownCard:favourites")}
</Button>
</div>

{
mode === "search"
? <>
<h4 className="text-md font-bold tracking-tight">
{!type ? t("AssetDropDownCard:noType") : null}
{type && type === "base" ? t("AssetDropDownCard:baseType") : null}
{type && type === "quote" ? t("AssetDropDownCard:quoteType") : null}
</h4>
<Input
name="assetSearch"
placeholder={t("AssetDropDownCard:search")}
onChange={(event) => {
setThisInput(event.target.value);
}}
/>
{thisResult && thisResult.length ? (
<>
<List height={200} itemCount={thisResult.length} itemSize={70} className="w-full">
{Row}
</List>
</>
) : null}
</>
: null
}

{
mode === "favourites"
? <>
<h4 className="text-md font-bold tracking-tight">
{!type ? t("AssetDropDownCard:noType") : null}
{type && type === "base" ? t("AssetDropDownCard:baseType") : null}
{type && type === "quote" ? t("AssetDropDownCard:quoteType") : null}
</h4>
{relevantAssets && relevantAssets.length ? (
<>
<List height={200} itemCount={relevantAssets.length} itemSize={70} className="w-full">
{Row}
</List>
</>
) : "No favourite assets..."}

</>
: null
}
</>
</DialogContent>
</Dialog>
Expand Down
63 changes: 61 additions & 2 deletions src/components/Market/MarketAssetCard.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import React, { useState, useEffect } from "react";
import React, { useState, useEffect, useMemo } from "react";
import { useTranslation } from "react-i18next";
import { i18n as i18nInstance, locale } from "@/lib/i18n.js";
import {
HeartFilledIcon,
HeartIcon
} from "@radix-ui/react-icons"
import { useStore } from '@nanostores/react';

import {
Card,
Expand All @@ -11,6 +16,13 @@ import {
CardTitle,
} from "@/components/ui/card";

import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";

import {
Dialog,
DialogContent,
Expand All @@ -28,12 +40,23 @@ import ExternalLink from "../common/ExternalLink.jsx";
import CardRow from "../common/CardRow.jsx";

import { humanReadableFloat } from "@/lib/common";
import {
$favouriteAssets,
addFavouriteAsset,
removeFavouriteAsset,
} from "@/stores/favourites.ts"

export default function MarketAssetCard(properties) {
const { asset, assetData, assetDetails, bitassetData, marketSearch, chain, usrBalances, type } =
properties;
const { t, i18n } = useTranslation(locale.get(), { i18n: i18nInstance });

const favouriteAssets = useStore($favouriteAssets);

const isFavourite = useMemo(() => {
return favouriteAssets[chain].map(x => x.id).includes(assetData.id);
}, [favouriteAssets, chain, asset]);

const [assetBalance, setAssetBalance] = useState(0);
useEffect(() => {
if (assetData && usrBalances) {
Expand Down Expand Up @@ -71,7 +94,43 @@ export default function MarketAssetCard(properties) {
<Card>
<CardHeader className="pb-2 pt-4">
<CardTitle>
{asset} {assetData ? `(${assetData.id})` : ""}
<div className="grid grid-cols-2">
<div>
{asset} {assetData ? `(${assetData.id})` : ""}
</div>
<div className="flex justify-end mt-1">
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
{
isFavourite
? <HeartFilledIcon
onClick={() => {
removeFavouriteAsset(chain, {
id: assetData.id,
symbol: assetData.symbol,
issuer: assetData.issuer
})
}}
/>
: <HeartIcon
onClick={() => {
addFavouriteAsset(chain, {
id: assetData.id,
symbol: assetData.symbol,
issuer: assetData.issuer
})
}}
/>
}
</TooltipTrigger>
<TooltipContent>
Favourite
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
</div>
</CardTitle>
<CardDescription className="text-lg">
{type === "buy" ? (
Expand Down
Loading

0 comments on commit 19dabec

Please sign in to comment.