Skip to content

Commit

Permalink
feat: add insufficient funds modal
Browse files Browse the repository at this point in the history
  • Loading branch information
OKendigelyan committed Feb 12, 2025
1 parent 8e5262f commit 2435145
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 10 deletions.
16 changes: 14 additions & 2 deletions apps/web/src/components/AccountCard/SendTezButton.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
import { useDynamicModalContext } from "@umami/components";
import { useCurrentAccount } from "@umami/state";
import { useCurrentAccount, useGetAccountBalanceDetails } from "@umami/state";

import { ArrowUpRightIcon } from "../../assets/icons";
import { IconButtonWithText } from "../IconButtonWithText/IconButtonWithText";
import { useIsAccountVerified } from "../Onboarding/VerificationFlow";
import { InsufficientFunds } from "../SendFlow/InsufficientFunds/InsufficientFunds";
import { FormPage as SendTezFormPage } from "../SendFlow/Tez/FormPage";

export const SendTezButton = () => {
const { openWith } = useDynamicModalContext();
const currentAccount = useCurrentAccount()!;
const isVerified = useIsAccountVerified();

const { spendableBalance } = useGetAccountBalanceDetails(currentAccount.address.pkh);
const hasInsufficientFunds = spendableBalance.lte(0);

const handleClick = async () => {
if (hasInsufficientFunds) {
await openWith(<InsufficientFunds />);
} else {
await openWith(<SendTezFormPage sender={currentAccount} />);
}
};

return (
<IconButtonWithText
icon={ArrowUpRightIcon}
isDisabled={!isVerified}
label="Send"
onClick={() => openWith(<SendTezFormPage sender={currentAccount} />)}
onClick={handleClick}
variant="primary"
/>
);
Expand Down
22 changes: 15 additions & 7 deletions apps/web/src/components/ConfirmationModal/ConfirmationModal.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {
Button,
type ButtonProps,
Center,
Heading,
type LinkProps,
ModalBody,
ModalContent,
ModalFooter,
Expand All @@ -14,17 +16,23 @@ import { useColor } from "../../styles/useColor";
import { ModalBackButton } from "../BackButton";
import { ModalCloseButton } from "../CloseButton";

type ConfirmationModalProps = {
title: string;
description?: string;
buttonLabel: string;
onSubmit: () => void;
type?: ButtonProps["variant"];
props?: ButtonProps & LinkProps;
};

export const ConfirmationModal = ({
title,
description,
buttonLabel,
onSubmit,
}: {
title: string;
buttonLabel: string;
description?: string;
onSubmit: () => void;
}) => {
type = "alert",
props,
}: ConfirmationModalProps) => {
const { onClose } = useDynamicModalContext();
const onClick = () => {
onSubmit();
Expand Down Expand Up @@ -55,7 +63,7 @@ export const ConfirmationModal = ({
</Center>
</ModalBody>
<ModalFooter>
<Button width="full" onClick={onClick} size="lg" variant="alert">
<Button width="full" onClick={onClick} variant={type} {...props}>
{buttonLabel}
</Button>
</ModalFooter>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {
Button,
Flex,
Heading,
Link,
ModalBody,
ModalContent,
ModalFooter,
ModalHeader,
Text,
} from "@chakra-ui/react";
import { useDynamicModalContext } from "@umami/components";
import { useBuyTezUrl, useCurrentAccount } from "@umami/state";

import { ExternalLinkIcon, WalletIcon } from "../../../assets/icons";
import { useColor } from "../../../styles/useColor";
import { ModalCloseButton } from "../../CloseButton";

export const InsufficientFunds = () => {
const color = useColor();
const currentAccount = useCurrentAccount();
const buyTezUrl = useBuyTezUrl(currentAccount!.address.pkh);

const { onClose } = useDynamicModalContext();

return (
<ModalContent>
<ModalHeader marginBottom="12px">
<Flex alignItems="center" justifyContent="center" flexDirection="column" gap="18px">
<WalletIcon width="24px" color={color("400")} />
<Heading size="xl">Insufficient Funds</Heading>
</Flex>
<ModalCloseButton />
</ModalHeader>
<ModalBody>
<Text color={color("700")} fontWeight="400" textAlign="center" size="md">
Oops, looks like you don't have enough funds on your account.
</Text>
</ModalBody>
<ModalFooter>
<Button
as={Link}
width="full"
href={buyTezUrl}
isExternal
leftIcon={<ExternalLinkIcon />}
onClick={onClose}
variant="primary"
>
Buy Tez
</Button>
</ModalFooter>
</ModalContent>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./InsufficientFunds";
20 changes: 19 additions & 1 deletion apps/web/src/components/SendFlow/Tez/FormPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
ModalFooter,
} from "@chakra-ui/react";
import { type TezTransfer } from "@umami/core";
import { useGetAccountBalanceDetails } from "@umami/state";
import { type RawPkh, TEZ, TEZ_DECIMALS, parsePkh, tezToMutez } from "@umami/tezos";
import { FormProvider, useForm } from "react-hook-form";

Expand Down Expand Up @@ -65,6 +66,23 @@ export const FormPage = ({ ...props }: FormPageProps<FormValues>) => {
handleSubmit,
} = form;

const { spendableBalance } = useGetAccountBalanceDetails(props.sender?.address.pkh ?? "");

const handleValidateAmount = (value: string) => {
const validationMessage = makeValidateDecimals(TEZ_DECIMALS)(value);

if (typeof validationMessage === "string") {
return validationMessage;
}

const amountToSend = tezToMutez(value);

if (amountToSend.gt(spendableBalance)) {
return "Insufficient funds";
}

return true;
};
return (
<FormProvider {...form}>
<ModalContent>
Expand All @@ -84,7 +102,7 @@ export const FormPage = ({ ...props }: FormPageProps<FormValues>) => {
type="number"
{...register("prettyAmount", {
required: "Amount is required",
validate: makeValidateDecimals(TEZ_DECIMALS),
validate: handleValidateAmount,
})}
placeholder="0.000000"
/>
Expand Down

0 comments on commit 2435145

Please sign in to comment.