11import { type ReactNode , useId , useState , useEffect } from 'react' ;
22
3+ import { zodResolver } from '@hookform/resolvers/zod' ;
4+ import { useForm } from 'react-hook-form' ;
35import { useTranslation } from 'react-i18next' ;
6+ import { z } from 'zod' ;
47
58import { Button } from '@/components/base/Button' ;
69import {
@@ -11,24 +14,48 @@ import {
1114 DialogTitle ,
1215 DialogTrigger ,
1316} from '@/components/base/Dialog' ;
17+ import {
18+ Form ,
19+ FormControl ,
20+ FormField ,
21+ FormItem ,
22+ FormLabel ,
23+ FormMessage ,
24+ } from '@/components/base/Form' ;
1425import { Input } from '@/components/base/Input' ;
1526
27+ const formSchema = z . object ( {
28+ name : z . string ( ) . min ( 1 , { message : 'dialog.pickName.nameIsRequired' } ) ,
29+ } ) ;
30+ type FormSchema = z . infer < typeof formSchema > ;
31+
1632export type EnterFlashcardSetNameProps = {
1733 children : ReactNode ;
1834 onSetName ?: ( name : string ) => void ;
1935} ;
2036
2137export function EnterFlashcardSetName ( { children, onSetName } : EnterFlashcardSetNameProps ) {
2238 const [ dialogOpen , setDialogOpen ] = useState ( false ) ;
23- const [ name , setName ] = useState ( '' ) ;
2439 const formId = useId ( ) ;
2540 const { t } = useTranslation ( 'sets' ) ;
41+ const form = useForm < FormSchema > ( {
42+ resolver : zodResolver ( formSchema ) ,
43+ defaultValues : {
44+ name : '' ,
45+ } ,
46+ } ) ;
47+
48+ const onSubmit = ( { name } : FormSchema ) => {
49+ setDialogOpen ( false ) ;
50+ onSetName ?.( name ) ;
51+ } ;
52+
2653 useEffect ( ( ) => {
2754 if ( dialogOpen ) {
2855 // Reset the name when the dialog is opened
29- setName ( '' ) ;
56+ form . reset ( ) ;
3057 }
31- } , [ dialogOpen ] ) ;
58+ } , [ dialogOpen , form , form . reset ] ) ;
3259
3360 return (
3461 < Dialog open = { dialogOpen } onOpenChange = { setDialogOpen } >
@@ -37,22 +64,23 @@ export function EnterFlashcardSetName({ children, onSetName }: EnterFlashcardSet
3764 < DialogHeader >
3865 < DialogTitle > { t ( 'dialog.pickName.title' ) } </ DialogTitle >
3966 </ DialogHeader >
40- < form
41- id = { formId }
42- onSubmit = { ( e ) => {
43- e . preventDefault ( ) ;
44- onSetName ?.( name ) ;
45- setDialogOpen ( false ) ;
46- } }
47- >
48- < Input
49- placeholder = { t ( 'dialog.pickName.placeholder' ) }
50- value = { name }
51- onChange = { ( e ) => {
52- setName ( e . target . value ) ;
53- } }
54- />
55- </ form >
67+ < Form { ...form } >
68+ < form id = { formId } onSubmit = { form . handleSubmit ( onSubmit ) } >
69+ < FormField
70+ control = { form . control }
71+ name = "name"
72+ render = { ( { field } ) => (
73+ < FormItem >
74+ < FormLabel > { t ( 'dialog.pickName.name' ) } </ FormLabel >
75+ < FormControl >
76+ < Input { ...field } />
77+ </ FormControl >
78+ < FormMessage />
79+ </ FormItem >
80+ ) }
81+ />
82+ </ form >
83+ </ Form >
5684
5785 < DialogFooter className = "flex flex-row justify-between" >
5886 < Button variant = "outlined" onClick = { ( ) => setDialogOpen ( false ) } >
0 commit comments