11'use client' ;
22
3+ import styled from '@emotion/styled' ;
34import { zodResolver } from '@hookform/resolvers/zod' ;
4- import { Box , Button , FormHelperText } from '@mui/material' ;
5- import React from 'react' ;
5+ import { Save } from '@mui/icons-material' ;
6+ import { Box , Button , FormHelperText , TextField } from '@mui/material' ;
7+ import React , { useEffect , useState } from 'react' ;
68import { Controller , SubmitHandler , useForm } from 'react-hook-form' ;
79import { z } from 'zod' ;
810
11+ import { AlertBar , AlertBarProps } from '@/components/shared/AlertBar' ;
12+
913import { consoleLog } from '@/utils/shared/console-log' ;
1014import { getApiResponse } from '@/utils/shared/get-api-response' ;
1115
1216const zodSchema = z . object ( {
13- name : z . string ( ) . min ( 5 ) . nonempty ( { message : 'Name is required' } ) ,
14- email : z . string ( ) . min ( 10 ) . email ( { message : 'Invalid email address' } ) ,
17+ name : z
18+ . string ( )
19+ . min ( 3 , { message : 'Name must contain at least 3 characters' } )
20+ . nonempty ( { message : 'Name is required' } ) ,
21+ email : z
22+ . string ( )
23+ . min ( 10 , { message : 'Email must contain at least 10 characters' } )
24+ . email ( { message : 'Invalid email address' } ) ,
1525} ) ;
1626
27+ const StyledForm = styled . form `
28+ .MuiFormHelperText-root {
29+ text-align: center;
30+ color: darkred;
31+ margin-bottom: 1rem;
32+ }
33+ ` ;
34+
1735type FormValues = z . infer < typeof zodSchema > ;
1836
1937const ReactHookForm : React . FC = ( ) => {
2038 const apiEndpoint = '/api/test' ;
2139 const [ apiResult , setApiResult ] = React . useState < FormValues > ( ) ;
2240
41+ const [ alertBarProps , setAlertBarProps ] = useState < AlertBarProps > ( {
42+ message : '' ,
43+ severity : 'info' ,
44+ } ) ;
45+
2346 const {
2447 handleSubmit,
2548 control,
26- formState : { errors } ,
49+ formState : { errors, isValid } ,
2750 } = useForm < FormValues > ( {
2851 resolver : zodResolver ( zodSchema ) ,
2952 } ) ;
@@ -39,20 +62,42 @@ const ReactHookForm: React.FC = () => {
3962 } ) ;
4063 setApiResult ( result ?. reqData ) ;
4164 consoleLog ( 'getApiResponse result' , result , errors ) ;
65+
66+ setAlertBarProps ( {
67+ message : 'Form submitted successfully' ,
68+ severity : 'success' ,
69+ } ) ;
4270 } catch ( error ) {
4371 consoleLog ( 'handleSubmit ERROR' , error ) ;
72+
73+ setAlertBarProps ( {
74+ message : 'Form submission failed' ,
75+ severity : 'error' ,
76+ } ) ;
4477 }
4578 } ;
4679
80+ useEffect ( ( ) => {
81+ if ( ! isValid && Object . keys ( errors ) . length > 0 ) {
82+ setAlertBarProps ( {
83+ message : 'Please fix the form errors' ,
84+ severity : 'warning' ,
85+ autoHideSeconds : 4 ,
86+ } ) ;
87+ }
88+ } , [ isValid , errors ] ) ;
89+
4790 return (
48- < form onSubmit = { handleSubmit ( onSubmit ) } >
91+ < StyledForm onSubmit = { handleSubmit ( onSubmit ) } >
4992 < Box sx = { { m : 2 } } >
50- < label > Name:</ label >
93+ { /* <label>Name:</label> */ }
5194 < Controller
5295 name = 'name'
5396 control = { control }
5497 defaultValue = ''
55- render = { ( { field } ) => < input { ...field } /> }
98+ render = { ( { field } ) => (
99+ < TextField label = 'Name' { ...field } size = 'small' />
100+ ) }
56101 />
57102 { errors . name && (
58103 < FormHelperText sx = { { textAlign : 'center' } } >
@@ -62,12 +107,14 @@ const ReactHookForm: React.FC = () => {
62107 </ Box >
63108
64109 < Box sx = { { m : 2 } } >
65- < label > Email:</ label >
110+ { /* <label>Email:</label> */ }
66111 < Controller
67112 name = 'email'
68113 control = { control }
69114 defaultValue = ''
70- render = { ( { field } ) => < input { ...field } /> }
115+ render = { ( { field } ) => (
116+ < TextField label = 'Email' { ...field } size = 'small' />
117+ ) }
71118 />
72119 { errors . email && (
73120 < FormHelperText sx = { { textAlign : 'center' } } >
@@ -80,10 +127,15 @@ const ReactHookForm: React.FC = () => {
80127 API result from { apiEndpoint } : { apiResult . name } & { apiResult . email }
81128 </ Box >
82129 ) }
83- < Button variant = 'contained' type = 'submit' >
130+ < Button variant = 'contained' type = 'submit' startIcon = { < Save /> } >
84131 Test react hook form with zod
85132 </ Button >
86- </ form >
133+
134+ < AlertBar
135+ onClose = { ( ) => setAlertBarProps ( { message : '' } ) }
136+ { ...alertBarProps }
137+ />
138+ </ StyledForm >
87139 ) ;
88140} ;
89141
0 commit comments