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,27 @@ export const NFTRevealButton: React.FC<NFTRevealButtonProps> = ({
6789 ) ;
6890 }
6991
92+ const onSubmit = async ( data : RevealFormData ) => {
93+ const tx = reveal ( {
94+ batchId : BigInt ( data . batchId ) ,
95+ contract,
96+ password : data . password ,
97+ } ) ;
98+
99+ await 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+
70113 return (
71114 < MinterOnly contract = { contract } >
72115 < Sheet onOpenChange = { setOpen } open = { open } >
@@ -75,80 +118,80 @@ export const NFTRevealButton: React.FC<NFTRevealButtonProps> = ({
75118 < EyeIcon className = "size-4" /> Reveal NFTs
76119 </ Button >
77120 </ SheetTrigger >
78- < SheetContent className = "w-full overflow-y-auto sm:min-w-[540px] lg:min -w-[700px] " >
121+ < SheetContent className = "! w-full lg:!max -w-lg " >
79122 < SheetHeader >
80123 < SheetTitle className = "text-left" > Reveal batch</ SheetTitle >
81124 </ 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"
125+ < Form { ...form } >
126+ < form
127+ className = "mt-4 space-y-6"
128+ onSubmit = { form . handleSubmit ( onSubmit ) }
146129 >
147- Reveal NFTs
148- </ TransactionButton >
149- </ div >
130+ < FormField
131+ control = { form . control }
132+ name = "batchId"
133+ render = { ( { field } ) => (
134+ < FormItem >
135+ < FormLabel > Select a batch</ FormLabel >
136+ < Select onValueChange = { field . onChange } value = { field . value } >
137+ < FormControl >
138+ < SelectTrigger className = "bg-card" >
139+ < SelectValue placeholder = "Select a batch" />
140+ </ SelectTrigger >
141+ </ FormControl >
142+ < SelectContent >
143+ { batchesQuery . data . map ( ( batch ) => (
144+ < SelectItem
145+ disabled = { batch . batchUri === "0x" }
146+ key = { batch . batchId . toString ( ) }
147+ value = { batch . batchId . toString ( ) }
148+ >
149+ { batch . placeholderMetadata ?. name ||
150+ batch . batchId . toString ( ) } { " " }
151+ { batch . batchUri === "0x" && "(REVEALED)" }
152+ </ SelectItem >
153+ ) ) }
154+ </ SelectContent >
155+ </ Select >
156+ < FormMessage />
157+ </ FormItem >
158+ ) }
159+ />
160+ < FormField
161+ control = { form . control }
162+ name = "password"
163+ render = { ( { field } ) => (
164+ < FormItem >
165+ < FormLabel > Password</ FormLabel >
166+ < FormControl >
167+ < Input
168+ { ...field }
169+ placeholder = "The one you used to upload this batch"
170+ type = "password"
171+ className = "bg-card"
172+ />
173+ </ FormControl >
174+ < FormMessage />
175+ </ FormItem >
176+ ) }
177+ />
178+
179+ < div className = "flex justify-end" >
180+ < TransactionButton
181+ client = { contract . client }
182+ isLoggedIn = { isLoggedIn }
183+ isPending = { sendTxMutation . isPending }
184+ transactionCount = { 1 }
185+ txChainID = { contract . chain . id }
186+ type = "submit"
187+ >
188+ Reveal NFTs
189+ </ TransactionButton >
190+ </ div >
191+ </ form >
192+ </ Form >
150193 </ SheetContent >
151194 </ Sheet >
152195 </ MinterOnly >
153196 ) ;
154- } ;
197+ }
0 commit comments