Skip to content

Commit ca02841

Browse files
kien-ngoMananTank
authored andcommitted
[Dashboard] Replace erc721 claim Drawer with Sheet
1 parent 8e80113 commit ca02841

File tree

2 files changed

+147
-175
lines changed

2 files changed

+147
-175
lines changed
Lines changed: 147 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,27 @@
11
"use client";
22

3-
import { useDisclosure } from "@chakra-ui/react";
3+
import {
4+
Sheet,
5+
SheetContent,
6+
SheetHeader,
7+
SheetTitle,
8+
SheetTrigger,
9+
} from "@/components/ui/sheet";
10+
import { FormControl, Input } from "@chakra-ui/react";
11+
import { TransactionButton } from "components/buttons/TransactionButton";
12+
import { useTrack } from "hooks/analytics/useTrack";
413
import { GemIcon } from "lucide-react";
5-
import type { ThirdwebContract } from "thirdweb";
6-
import { Button, Drawer } from "tw-components";
7-
import { NFTClaimForm } from "./claim-form";
14+
import { useState } from "react";
15+
import { useForm } from "react-hook-form";
16+
import { toast } from "sonner";
17+
import { type ThirdwebContract, ZERO_ADDRESS } from "thirdweb";
18+
import { getApprovalForTransaction } from "thirdweb/extensions/erc20";
19+
import { claimTo } from "thirdweb/extensions/erc721";
20+
import { useActiveAccount, useSendAndConfirmTransaction } from "thirdweb/react";
21+
import { Button } from "tw-components";
22+
import { FormErrorMessage, FormHelperText, FormLabel } from "tw-components";
23+
24+
const CLAIM_FORM_ID = "nft-claim-form";
825

926
interface NFTClaimButtonProps {
1027
contract: ThirdwebContract;
@@ -15,26 +32,133 @@ interface NFTClaimButtonProps {
1532
* For Edition Drop we have a dedicated ClaimTabERC1155 inside each Edition's page
1633
*/
1734
export const NFTClaimButton: React.FC<NFTClaimButtonProps> = ({ contract }) => {
18-
const { isOpen, onOpen, onClose } = useDisclosure();
35+
const trackEvent = useTrack();
36+
const address = useActiveAccount()?.address;
37+
const { register, handleSubmit, formState } = useForm({
38+
defaultValues: { amount: "1", to: address },
39+
});
40+
const { errors } = formState;
41+
const sendAndConfirmTx = useSendAndConfirmTransaction();
42+
const account = useActiveAccount();
43+
const [open, setOpen] = useState(false);
1944

2045
return (
21-
<>
22-
<Drawer
23-
allowPinchZoom
24-
preserveScrollBarGap
25-
size="lg"
26-
onClose={onClose}
27-
isOpen={isOpen}
28-
>
29-
<NFTClaimForm contract={contract} />
30-
</Drawer>
31-
<Button
32-
colorScheme="primary"
33-
leftIcon={<GemIcon className="size-4" />}
34-
onClick={onOpen}
35-
>
36-
Claim
37-
</Button>
38-
</>
46+
<Sheet open={open} onOpenChange={setOpen}>
47+
<SheetTrigger asChild>
48+
<Button colorScheme="primary" leftIcon={<GemIcon className="size-4" />}>
49+
Claim
50+
</Button>
51+
</SheetTrigger>
52+
<SheetContent className="z-[10000] overflow-y-auto sm:w-[540px] sm:max-w-[90%] lg:w-[700px]">
53+
<SheetHeader>
54+
<SheetTitle>Claim NFTs</SheetTitle>
55+
</SheetHeader>
56+
<form className="mt-8 flex w-full flex-col gap-3 md:flex-row">
57+
<div className="flex w-full flex-col gap-6 md:flex-row">
58+
<FormControl isRequired isInvalid={!!errors.to}>
59+
<FormLabel>To Address</FormLabel>
60+
<Input placeholder={ZERO_ADDRESS} {...register("to")} />
61+
<FormHelperText>Enter the address to claim to.</FormHelperText>
62+
<FormErrorMessage>{errors.to?.message}</FormErrorMessage>
63+
</FormControl>
64+
<FormControl isRequired isInvalid={!!errors.amount}>
65+
<FormLabel>Amount</FormLabel>
66+
<Input
67+
type="text"
68+
{...register("amount", {
69+
validate: (value) => {
70+
const valueNum = Number(value);
71+
if (!Number.isInteger(valueNum)) {
72+
return "Amount must be an integer";
73+
}
74+
},
75+
})}
76+
/>
77+
<FormHelperText>How many would you like to claim?</FormHelperText>
78+
<FormErrorMessage>{errors.amount?.message}</FormErrorMessage>
79+
</FormControl>
80+
</div>
81+
</form>
82+
<div className="mt-4 flex justify-end">
83+
<TransactionButton
84+
txChainID={contract.chain.id}
85+
transactionCount={1}
86+
form={CLAIM_FORM_ID}
87+
isLoading={formState.isSubmitting}
88+
type="submit"
89+
colorScheme="primary"
90+
onClick={handleSubmit(async (d) => {
91+
trackEvent({
92+
category: "nft",
93+
action: "claim",
94+
label: "attempt",
95+
});
96+
if (!account) {
97+
return toast.error("No account detected");
98+
}
99+
if (!d.to) {
100+
return toast.error(
101+
"Please enter the address that will receive the NFT",
102+
);
103+
}
104+
105+
const transaction = claimTo({
106+
contract,
107+
to: d.to,
108+
quantity: BigInt(d.amount),
109+
from: account.address,
110+
});
111+
112+
const approveTx = await getApprovalForTransaction({
113+
transaction,
114+
account,
115+
});
116+
117+
if (approveTx) {
118+
const promise = sendAndConfirmTx.mutateAsync(approveTx, {
119+
onError: (error) => {
120+
console.error(error);
121+
},
122+
});
123+
toast.promise(promise, {
124+
loading: "Approving ERC20 tokens for this claim",
125+
success: "Tokens approved successfully",
126+
error: "Failed to approve token",
127+
});
128+
129+
await promise;
130+
}
131+
132+
const promise = sendAndConfirmTx.mutateAsync(transaction, {
133+
onSuccess: () => {
134+
trackEvent({
135+
category: "nft",
136+
action: "claim",
137+
label: "success",
138+
});
139+
setOpen(false);
140+
},
141+
onError: (error) => {
142+
trackEvent({
143+
category: "nft",
144+
action: "claim",
145+
label: "error",
146+
error,
147+
});
148+
},
149+
});
150+
151+
toast.promise(promise, {
152+
loading: "Claiming NFT(s)",
153+
success: "NFT(s) claimed successfully",
154+
error: "Failed to claim NFT(s)",
155+
});
156+
})}
157+
>
158+
Claim NFT
159+
</TransactionButton>
160+
</div>
161+
</SheetContent>
162+
</Sheet>
39163
);
40164
};

apps/dashboard/src/contract-ui/tabs/nfts/components/claim-form.tsx

Lines changed: 0 additions & 152 deletions
This file was deleted.

0 commit comments

Comments
 (0)