11"use client" ;
22
3- import { FormControl , Input , Select } from "@chakra-ui/react" ;
4- import { FormErrorMessage , FormLabel } from "chakra/form" ;
3+ import { zodResolver } from "@hookform/resolvers/zod" ;
54import { EyeIcon } from "lucide-react" ;
65import { useState } from "react" ;
76import { useForm } from "react-hook-form" ;
87import { toast } from "sonner" ;
98import type { ThirdwebContract } from "thirdweb" ;
109import { getBatchesToReveal , reveal } from "thirdweb/extensions/erc721" ;
1110import { useReadContract , useSendAndConfirmTransaction } from "thirdweb/react" ;
11+ import * as z from "zod" ;
1212import { MinterOnly } from "@/components/contracts/roles/minter-only" ;
1313import { TransactionButton } from "@/components/tx-button" ;
1414import { Button } from "@/components/ui/button" ;
15+ import {
16+ Form ,
17+ FormControl ,
18+ FormField ,
19+ FormItem ,
20+ FormLabel ,
21+ FormMessage ,
22+ } from "@/components/ui/form" ;
23+ import { Input } from "@/components/ui/input" ;
24+ import {
25+ Select ,
26+ SelectContent ,
27+ SelectItem ,
28+ SelectTrigger ,
29+ SelectValue ,
30+ } from "@/components/ui/select" ;
1531import {
1632 Sheet ,
1733 SheetContent ,
@@ -20,29 +36,35 @@ import {
2036 SheetTrigger ,
2137} from "@/components/ui/sheet" ;
2238import { ToolTipLabel } from "@/components/ui/tooltip" ;
39+ import { parseError } from "@/utils/errorParser" ;
2340
24- interface NFTRevealButtonProps {
25- contract : ThirdwebContract ;
26- isLoggedIn : boolean ;
27- }
41+ const revealFormSchema = z . object ( {
42+ batchId : z . string ( ) . min ( 1 , "Please select a batch" ) ,
43+ password : z . string ( ) . min ( 1 , "Password is required" ) ,
44+ } ) ;
2845
29- const REVEAL_FORM_ID = "reveal-form" ;
46+ type RevealFormData = z . infer < typeof revealFormSchema > ;
3047
31- export const NFTRevealButton : React . FC < NFTRevealButtonProps > = ( {
48+ export function NFTRevealButton ( {
3249 contract,
3350 isLoggedIn,
34- } ) => {
51+ } : {
52+ contract : ThirdwebContract ;
53+ isLoggedIn : boolean ;
54+ } ) {
3555 const batchesQuery = useReadContract ( getBatchesToReveal , {
3656 contract,
3757 } ) ;
3858
3959 const sendTxMutation = useSendAndConfirmTransaction ( ) ;
4060
41- const {
42- register,
43- handleSubmit,
44- formState : { errors, isDirty } ,
45- } = useForm < { batchId : string ; password : string } > ( ) ;
61+ const form = useForm < RevealFormData > ( {
62+ resolver : zodResolver ( revealFormSchema ) ,
63+ defaultValues : {
64+ batchId : "" ,
65+ password : "" ,
66+ } ,
67+ } ) ;
4668
4769 const [ open , setOpen ] = useState ( false ) ;
4870
@@ -67,6 +89,33 @@ export const NFTRevealButton: React.FC<NFTRevealButtonProps> = ({
6789 ) ;
6890 }
6991
92+ const onSubmit = ( data : RevealFormData ) => {
93+ const tx = reveal ( {
94+ batchId : BigInt ( data . batchId ) ,
95+ contract,
96+ password : data . password ,
97+ } ) ;
98+
99+ const promise = sendTxMutation . mutateAsync ( tx , {
100+ onError : ( error ) => {
101+ toast . error ( "Failed to reveal batch" , {
102+ description : parseError ( error ) ,
103+ } ) ;
104+ console . error ( error ) ;
105+ } ,
106+ onSuccess : ( ) => {
107+ toast . success ( "Batch revealed successfully" ) ;
108+ setOpen ( false ) ;
109+ } ,
110+ } ) ;
111+
112+ toast . promise ( promise , {
113+ error : "Failed to reveal batch" ,
114+ loading : "Revealing batch" ,
115+ success : "Batch revealed successfully" ,
116+ } ) ;
117+ } ;
118+
70119 return (
71120 < MinterOnly contract = { contract } >
72121 < Sheet onOpenChange = { setOpen } open = { open } >
@@ -75,80 +124,80 @@ export const NFTRevealButton: React.FC<NFTRevealButtonProps> = ({
75124 < EyeIcon className = "size-4" /> Reveal NFTs
76125 </ Button >
77126 </ SheetTrigger >
78- < SheetContent className = "w-full overflow-y-auto sm:min-w-[540px] lg:min -w-[700px] " >
127+ < SheetContent className = "! w-full lg:!max -w-lg " >
79128 < SheetHeader >
80129 < SheetTitle className = "text-left" > Reveal batch</ SheetTitle >
81130 </ SheetHeader >
82- < form
83- className = "mt-10 flex flex-col gap-6"
84- id = { REVEAL_FORM_ID }
85- onSubmit = { handleSubmit ( ( data ) => {
86- const tx = reveal ( {
87- batchId : BigInt ( data . batchId ) ,
88- contract,
89- password : data . password ,
90- } ) ;
91-
92- const promise = sendTxMutation . mutateAsync ( tx , {
93- onError : ( error ) => {
94- console . error ( error ) ;
95- } ,
96- onSuccess : ( ) => {
97- setOpen ( false ) ;
98- } ,
99- } ) ;
100-
101- toast . promise ( promise , {
102- error : "Failed to reveal batch" ,
103- loading : "Revealing batch" ,
104- success : "Batch revealed successfully" ,
105- } ) ;
106- } ) }
107- >
108- < FormControl isInvalid = { ! ! errors . password } isRequired mr = { 4 } >
109- < FormLabel > Select a batch</ FormLabel >
110- < Select { ...register ( "batchId" ) } autoFocus >
111- { batchesQuery . data . map ( ( batch ) => (
112- < option
113- disabled = { batch . batchUri === "0x" }
114- key = { batch . batchId . toString ( ) }
115- value = { batch . batchId . toString ( ) }
116- >
117- { batch . placeholderMetadata ?. name ||
118- batch . batchId . toString ( ) } { " " }
119- { batch . batchUri === "0x" && "(REVEALED)" }
120- </ option >
121- ) ) }
122- </ Select >
123- < FormErrorMessage > { errors ?. password ?. message } </ FormErrorMessage >
124- </ FormControl >
125- < FormControl isInvalid = { ! ! errors . password } isRequired mr = { 4 } >
126- < FormLabel > Password</ FormLabel >
127- < Input
128- { ...register ( "password" ) }
129- autoFocus
130- placeholder = "The one you used to upload this batch"
131- type = "password"
132- />
133- < FormErrorMessage > { errors ?. password ?. message } </ FormErrorMessage >
134- </ FormControl >
135- </ form >
136- < div className = "mt-4 flex justify-end" >
137- < TransactionButton
138- client = { contract . client }
139- disabled = { ! isDirty }
140- form = { REVEAL_FORM_ID }
141- isLoggedIn = { isLoggedIn }
142- isPending = { sendTxMutation . isPending }
143- transactionCount = { 1 }
144- txChainID = { contract . chain . id }
145- type = "submit"
131+ < Form { ...form } >
132+ < form
133+ className = "mt-4 space-y-6"
134+ onSubmit = { form . handleSubmit ( onSubmit ) }
146135 >
147- Reveal NFTs
148- </ TransactionButton >
149- </ div >
136+ < FormField
137+ control = { form . control }
138+ name = "batchId"
139+ render = { ( { field } ) => (
140+ < FormItem >
141+ < FormLabel > Select a batch</ FormLabel >
142+ < Select onValueChange = { field . onChange } value = { field . value } >
143+ < FormControl >
144+ < SelectTrigger className = "bg-card" >
145+ < SelectValue placeholder = "Select a batch" />
146+ </ SelectTrigger >
147+ </ FormControl >
148+ < SelectContent >
149+ { batchesQuery . data . map ( ( batch ) => (
150+ < SelectItem
151+ disabled = { batch . batchUri === "0x" }
152+ key = { batch . batchId . toString ( ) }
153+ value = { batch . batchId . toString ( ) }
154+ >
155+ { batch . placeholderMetadata ?. name ||
156+ batch . batchId . toString ( ) } { " " }
157+ { batch . batchUri === "0x" && "(REVEALED)" }
158+ </ SelectItem >
159+ ) ) }
160+ </ SelectContent >
161+ </ Select >
162+ < FormMessage />
163+ </ FormItem >
164+ ) }
165+ />
166+ < FormField
167+ control = { form . control }
168+ name = "password"
169+ render = { ( { field } ) => (
170+ < FormItem >
171+ < FormLabel > Password</ FormLabel >
172+ < FormControl >
173+ < Input
174+ { ...field }
175+ placeholder = "The one you used to upload this batch"
176+ type = "password"
177+ className = "bg-card"
178+ />
179+ </ FormControl >
180+ < FormMessage />
181+ </ FormItem >
182+ ) }
183+ />
184+
185+ < div className = "flex justify-end" >
186+ < TransactionButton
187+ client = { contract . client }
188+ isLoggedIn = { isLoggedIn }
189+ isPending = { sendTxMutation . isPending }
190+ transactionCount = { 1 }
191+ txChainID = { contract . chain . id }
192+ type = "submit"
193+ >
194+ Reveal NFTs
195+ </ TransactionButton >
196+ </ div >
197+ </ form >
198+ </ Form >
150199 </ SheetContent >
151200 </ Sheet >
152201 </ MinterOnly >
153202 ) ;
154- } ;
203+ }
0 commit comments