Skip to content

Commit 0e900fe

Browse files
committed
[Dashboard] Replace erc721 claim Drawer with Sheet (#4932)
## Problem solved Short description of the bug fixed or feature added <!-- start pr-codex --> --- ## PR-Codex overview This PR focuses on refactoring the `NFTClaimButton` component to replace the `Drawer` with a `Sheet` component for a better user interface. It enhances the form handling by integrating validation and error messaging for claiming NFTs. ### Detailed summary - Removed the `Drawer` component and replaced it with a `Sheet`. - Integrated `react-hook-form` for form handling. - Added validation for the "To Address" and "Amount" fields. - Implemented error messages for form validation. - Added transaction handling logic for NFT claims. - Used `TransactionButton` for submitting the claim. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent 1adbc62 commit 0e900fe

File tree

2 files changed

+158
-175
lines changed

2 files changed

+158
-175
lines changed
Lines changed: 158 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,144 @@ 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+
try {
92+
trackEvent({
93+
category: "nft",
94+
action: "claim",
95+
label: "attempt",
96+
});
97+
if (!account) {
98+
return toast.error("No account detected");
99+
}
100+
if (!d.to) {
101+
return toast.error(
102+
"Please enter the address that will receive the NFT",
103+
);
104+
}
105+
106+
const transaction = claimTo({
107+
contract,
108+
to: d.to,
109+
quantity: BigInt(d.amount),
110+
from: account.address,
111+
});
112+
113+
const approveTx = await getApprovalForTransaction({
114+
transaction,
115+
account,
116+
});
117+
118+
if (approveTx) {
119+
const promise = sendAndConfirmTx.mutateAsync(approveTx, {
120+
onError: (error) => {
121+
console.error(error);
122+
},
123+
});
124+
toast.promise(promise, {
125+
loading: "Approving ERC20 tokens for this claim",
126+
success: "Tokens approved successfully",
127+
error: "Failed to approve token",
128+
});
129+
130+
await promise;
131+
}
132+
133+
const promise = sendAndConfirmTx.mutateAsync(transaction, {
134+
onSuccess: () => {
135+
trackEvent({
136+
category: "nft",
137+
action: "claim",
138+
label: "success",
139+
});
140+
setOpen(false);
141+
},
142+
onError: (error) => {
143+
trackEvent({
144+
category: "nft",
145+
action: "claim",
146+
label: "error",
147+
error,
148+
});
149+
},
150+
});
151+
152+
toast.promise(promise, {
153+
loading: "Claiming NFT(s)",
154+
success: "NFT(s) claimed successfully",
155+
error: "Failed to claim NFT(s)",
156+
});
157+
} catch (error) {
158+
console.error(error);
159+
toast.error((error as Error).message || "Error claiming NFT");
160+
trackEvent({
161+
category: "nft",
162+
action: "claim",
163+
label: "error",
164+
error,
165+
});
166+
}
167+
})}
168+
>
169+
Claim NFT
170+
</TransactionButton>
171+
</div>
172+
</SheetContent>
173+
</Sheet>
39174
);
40175
};

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)