1
1
"use client" ;
2
2
3
- import { FormControl , Input , Select , Skeleton , Spacer } from "@chakra-ui/react" ;
4
3
import { useMutation , useQuery } from "@tanstack/react-query" ;
5
- import { FormErrorMessage , FormLabel } from "chakra/form" ;
6
4
import { useMemo } from "react" ;
7
5
import { FormProvider , type UseFormReturn , useForm } from "react-hook-form" ;
8
6
import { toast } from "sonner" ;
@@ -26,8 +24,18 @@ import {
26
24
toFunctionSelector ,
27
25
} from "thirdweb/utils" ;
28
26
import type { Account } from "thirdweb/wallets" ;
27
+ import { FormFieldSetup } from "@/components/blocks/FormFieldSetup" ;
29
28
import { TransactionButton } from "@/components/tx-button" ;
29
+ import { Input } from "@/components/ui/input" ;
30
30
import { Spinner } from "@/components/ui/Spinner/Spinner" ;
31
+ import {
32
+ Select ,
33
+ SelectContent ,
34
+ SelectItem ,
35
+ SelectTrigger ,
36
+ SelectValue ,
37
+ } from "@/components/ui/select" ;
38
+ import { Skeleton } from "@/components/ui/skeleton" ;
31
39
import {
32
40
useAllVersions ,
33
41
usePublishedContractsQuery ,
@@ -65,7 +73,7 @@ export const InstallModuleForm = (props: InstallModuleFormProps) => {
65
73
version : "latest" ,
66
74
} ,
67
75
} ) ;
68
- const { register, watch, formState, resetField, reset } = form ;
76
+ const { register, watch, formState, resetField, reset, setValue } = form ;
69
77
const { contract, account } = props ;
70
78
const { errors } = formState ;
71
79
@@ -144,10 +152,6 @@ export const InstallModuleForm = (props: InstallModuleFormProps) => {
144
152
installMutation . mutate ( ) ;
145
153
} ;
146
154
147
- const moduleContractInputProps = register ( "moduleContract" , {
148
- required : "Module name is required" ,
149
- } ) ;
150
-
151
155
const selectedModule = modulesOnly ?. find (
152
156
( x ) => x . contractId === watch ( "moduleContract" ) ,
153
157
) ;
@@ -267,62 +271,65 @@ export const InstallModuleForm = (props: InstallModuleFormProps) => {
267
271
} }
268
272
>
269
273
< div className = "grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3" >
270
- < FormControl isInvalid = { ! ! errors . publisherAddress } >
271
- < FormLabel > Publisher</ FormLabel >
274
+ < FormFieldSetup
275
+ htmlFor = "publisherAddress"
276
+ label = "Publisher"
277
+ errorMessage = { errors . publisherAddress ?. message }
278
+ isRequired = { true }
279
+ >
272
280
< Input
273
- bg = "backgroundHighlight "
281
+ id = "publisherAddress "
274
282
disabled = { installMutation . isPending }
275
283
placeholder = "Publisher address"
276
284
{ ...register ( "publisherAddress" , {
277
285
required : "Publisher address is required" ,
278
286
} ) }
279
287
/>
280
- < FormErrorMessage >
281
- { errors . publisherAddress ?. message }
282
- </ FormErrorMessage >
283
- </ FormControl >
284
-
285
- < FormControl
286
- isInvalid = {
287
- ! ! errors . moduleContract || isModuleCompatibleQuery . data === false
288
+ </ FormFieldSetup >
289
+
290
+ < FormFieldSetup
291
+ htmlFor = "moduleContract"
292
+ label = "Module Name"
293
+ errorMessage = {
294
+ ! isModuleCompatibleQuery . isFetching &&
295
+ isModuleCompatibleQuery . data === false
296
+ ? "Module is not compatible"
297
+ : errors . moduleContract ?. message
288
298
}
289
299
isRequired = { true }
290
300
>
291
- < FormLabel > Module Name</ FormLabel >
292
- < Skeleton
293
- borderRadius = "lg"
294
- isLoaded = { ! ! modulesOnly . length || ! isFetching }
295
- >
301
+ { ! modulesOnly . length && isFetching ? (
302
+ < Skeleton className = "h-10 w-full rounded-md" />
303
+ ) : (
296
304
< Select
297
- bg = "backgroundHighlight"
298
305
disabled = {
299
306
installMutation . isPending ||
300
307
modulesOnly ?. length === 0 ||
301
308
isPending
302
309
}
303
- { ...moduleContractInputProps }
304
- onChange = { ( e ) => {
310
+ value = { watch ( "moduleContract" ) }
311
+ onValueChange = { ( value ) => {
312
+ setValue ( "moduleContract" , value ) ;
305
313
// reset version when module changes
306
314
resetField ( "version" ) ;
307
- moduleContractInputProps . onChange ( e ) ;
308
315
} }
309
- placeholder = {
310
- modulesOnly . length === 0 ? "No modules" : "Select module"
311
- }
312
316
>
313
- { modulesOnly . map ( ( { contractId } ) => (
314
- < option key = { contractId } value = { contractId } >
315
- { contractId }
316
- </ option >
317
- ) ) }
317
+ < SelectTrigger >
318
+ < SelectValue
319
+ placeholder = {
320
+ modulesOnly . length === 0 ? "No modules" : "Select module"
321
+ }
322
+ />
323
+ </ SelectTrigger >
324
+ < SelectContent >
325
+ { modulesOnly . map ( ( { contractId } ) => (
326
+ < SelectItem key = { contractId } value = { contractId } >
327
+ { contractId }
328
+ </ SelectItem >
329
+ ) ) }
330
+ </ SelectContent >
318
331
</ Select >
319
- </ Skeleton >
320
- < FormErrorMessage fontWeight = { 500 } >
321
- { ! isModuleCompatibleQuery . isFetching &&
322
- isModuleCompatibleQuery . data === false &&
323
- "Module is not compatible" }
324
- { errors . moduleContract ?. message }
325
- </ FormErrorMessage >
332
+ ) }
326
333
327
334
{ isModuleCompatibleQuery . isFetching && selectedModule && (
328
335
< div className = "mt-2 flex items-center gap-1.5 text-link-foreground" >
@@ -338,39 +345,52 @@ export const InstallModuleForm = (props: InstallModuleFormProps) => {
338
345
</ p >
339
346
</ div >
340
347
) }
341
- </ FormControl >
348
+ </ FormFieldSetup >
342
349
343
- < FormControl isInvalid = { ! ! errors . version } isRequired = { true } >
344
- < FormLabel > Module Version</ FormLabel >
345
- < Skeleton borderRadius = "lg" isLoaded = { ! allVersions . isFetching } >
350
+ < FormFieldSetup
351
+ htmlFor = "version"
352
+ label = "Module Version"
353
+ errorMessage = { errors . version ?. message }
354
+ isRequired = { true }
355
+ >
356
+ { allVersions . isFetching ? (
357
+ < Skeleton className = "h-10 w-full rounded-md" />
358
+ ) : (
346
359
< Select
347
- bg = "backgroundHighlight"
348
360
disabled = {
349
361
! allVersions . data ||
350
362
allVersions . isPending ||
351
363
isModuleCompatibleQuery . data === false ||
352
364
installMutation . isPending ||
353
365
isModuleCompatibleQuery . isFetching
354
366
}
355
- w = "full"
356
- { ...register ( "version" , {
357
- required : "Version is required" ,
358
- } ) }
367
+ value = { watch ( "version" ) }
368
+ onValueChange = { ( value ) => setValue ( "version" , value ) }
359
369
>
360
- < option value = "latest" > Latest</ option >
361
- { allVersions ?. data ?. map ( ( { version } ) => (
362
- < option key = { version } value = { version } >
363
- { version }
364
- </ option >
365
- ) ) }
370
+ < SelectTrigger >
371
+ < SelectValue placeholder = "Select version" />
372
+ </ SelectTrigger >
373
+ < SelectContent >
374
+ < SelectItem value = "latest" > Latest</ SelectItem >
375
+ { allVersions ?. data ?. map ( ( { version } ) => {
376
+ if ( ! version ) {
377
+ return null ;
378
+ }
379
+
380
+ return (
381
+ < SelectItem key = { version } value = { version } >
382
+ { version }
383
+ </ SelectItem >
384
+ ) ;
385
+ } ) }
386
+ </ SelectContent >
366
387
</ Select >
367
- </ Skeleton >
368
- < FormErrorMessage > { errors . version ?. message } </ FormErrorMessage >
369
- </ FormControl >
388
+ ) }
389
+ </ FormFieldSetup >
370
390
</ div >
371
391
372
392
{ moduleInstallParams . isFetching ? (
373
- < Skeleton h = "80px" mt = { 4 } />
393
+ < Skeleton className = "h-20 w-full mt-4" />
374
394
) : (
375
395
moduleInstallParams . data &&
376
396
! isModuleCompatibleQuery . isFetching &&
@@ -383,7 +403,7 @@ export const InstallModuleForm = (props: InstallModuleFormProps) => {
383
403
)
384
404
) }
385
405
386
- < Spacer h = { 5 } />
406
+ < div className = "h-5" />
387
407
388
408
{ /* Submit */ }
389
409
< div className = "flex justify-end" >
0 commit comments