Skip to content

Commit

Permalink
Feat/sns (#1191)
Browse files Browse the repository at this point in the history
* ✨ Add icons and hooks

* ✨ Update braavos icon name

* ✨ Add controller icon

* ✨ Refacto token send feature

* 📱 Minor design update

* 🐛 Fix input error type

* 🐛 Fix case where user click elsewhere

* 🐛 Fix header layout

* 🔥 Remove debuggers

* ✨ Add icons and hooks

* ✨ Update braavos icon name

* ✨ Add controller icon

* ✨ Refacto token send feature

* 📱 Minor design update

* 🐛 Fix input error type

* 🐛 Fix case where user click elsewhere

* 🐛 Fix header layout

* 🔥 Remove debuggers

* 💄 Linter

* 🐛 Fix typo

* 💄 Prettier
  • Loading branch information
bal7hazar authored Dec 20, 2024
1 parent 4b28309 commit 1ae107d
Show file tree
Hide file tree
Showing 18 changed files with 773 additions and 271 deletions.
2 changes: 2 additions & 0 deletions packages/profile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@cartridge/utils": "workspace:*",
"@hookform/resolvers": "^3.9.1",
"compare-versions": "^6.1.1",
"lodash": "^4.17.21",
"posthog-js": "^1.181.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
Expand All @@ -32,6 +33,7 @@
"devDependencies": {
"@cartridge/eslint": "workspace:*",
"@eslint/js": "^9.9.0",
"@types/lodash": "^4.17.13",
"@types/node": "^20.6.0",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
Expand Down
3 changes: 2 additions & 1 deletion packages/profile/src/components/inventory/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export { Asset, Collection, SendCollection } from "./collection";
export { Token, SendToken } from "./token";
export { Token } from "./token";
export { SendToken } from "./token/send/index";

import { CopyAddress, ScrollArea } from "@cartridge/ui-next";
import {
Expand Down
7 changes: 4 additions & 3 deletions packages/profile/src/components/inventory/token/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ export const formatBalance = (balance: string, exludes?: string[]) => {
// Exclude each substring from prefix
const cleaned =
exludes?.reduce((prev, curr) => prev.replace(curr, ""), prefix) ?? prefix;
return `${cleaned}${parseFloat(
balance.replace(prefix, ""),
).toLocaleString()}`;
return `${cleaned}${parseFloat(balance.replace(prefix, "")).toLocaleString(
undefined,
{ maximumFractionDigits: 18 },
)}`;
};
228 changes: 0 additions & 228 deletions packages/profile/src/components/inventory/token/send.tsx

This file was deleted.

116 changes: 116 additions & 0 deletions packages/profile/src/components/inventory/token/send/amount.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { useToken } from "@/hooks/token";
import { AlertIcon, Button, cn, Input, Label } from "@cartridge/ui-next";
import { useCountervalue } from "@cartridge/utils";
import { TokenPair } from "@cartridge/utils/api/cartridge";
import { useCallback, useMemo } from "react";
import { useParams } from "react-router-dom";
import { formatBalance } from "../helper";

export function Amount({
amount,
setAmount,
}: {
amount: number | undefined;
setAmount: (amount: number | undefined) => void;
}) {
const { address: tokenAddress } = useParams<{ address: string }>();
const token = useToken({ tokenAddress: tokenAddress! });

const handleMax = useCallback(
(
e: React.MouseEvent<HTMLDivElement> | React.MouseEvent<HTMLButtonElement>,
) => {
e.preventDefault();
if (!token) return;
setAmount(parseFloat(token.balance.formatted));
},
[token, setAmount],
);

const { countervalue } = useCountervalue(
{
balance: amount?.toString() ?? "0",
pair: `${token?.meta.symbol}_USDC` as TokenPair,
},
{
enabled: token && ["ETH", "STRK"].includes(token.meta.symbol) && !!amount,
},
);

const handleChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
setAmount(value === "" ? undefined : Number(value));
},
[setAmount],
);

const error = useMemo(() => {
if (!token) return "";
if (amount && amount > parseFloat(token.balance.formatted))
return "Amount cannot exceed balance";
const decimals = token.meta.decimals ?? 18;
const minAmountStr = `0.${"0".repeat(decimals - 1)}1`;
if (amount && amount < parseFloat(minAmountStr))
return `Amount must be at least ${minAmountStr} ${token.meta.symbol}`;
return "";
}, [token, amount]);

if (!token) {
return null;
}

return (
<div className="flex flex-col gap-y-px">
<div className="flex items-center justify-between">
<Label className="py-3 text-[11px]/3 uppercase font-bold">Amount</Label>
<div className="flex items-center gap-2">
<p className="text-[11px]/3 uppercase font-bold text-quaternary-foreground">
Balance:
</p>
<div
className="text-[11px]/3 uppercase font-bold cursor-pointer hover:opacity-90"
onClick={(e: React.MouseEvent<HTMLDivElement>) => handleMax(e)}
>
{`${formatBalance(token.balance.formatted, ["~"])} ${
token.meta.symbol
}`}
</div>
</div>
</div>

<div className="flex flex-col gap-y-3">
<div className="relative">
<Input
type="number"
className="bg-quaternary pr-12 border border-quaternary focus-visible:border-muted focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 [&::-webkit-inner-spin-button]:appearance-none"
placeholder={(0.01).toLocaleString()}
value={amount ?? ""}
onChange={handleChange}
/>
{countervalue && (
<span className="absolute right-14 top-3.5 text-sm text-muted-foreground">
{formatBalance(countervalue.formatted)}
</span>
)}
<Button
className="absolute right-2 top-1/2 -translate-y-1/2 text-xs/3 font-bold uppercase px-2 py-1.5 h-7 bg-muted text-secondary-foreground hover:opacity-70"
variant="ghost"
onClick={(e: React.MouseEvent<HTMLButtonElement>) => handleMax(e)}
>
Max
</Button>
</div>
<div
className={cn(
"flex items-center gap-x-1 text-destructive-foreground",
!error && "hidden",
)}
>
<AlertIcon className="h-5 w-5" />
<p className="text-sm font-medium">{error}</p>
</div>
</div>
</div>
);
}
Loading

0 comments on commit 1ae107d

Please sign in to comment.