@@ -9,49 +9,62 @@ import Button from '../../../common/Button';
99import apiClient from '../../../utils/apiClient' ;
1010import useSyncFormTranslations from '../../../common/useSyncFormTranslations' ;
1111
12- function asyncValidate ( fieldToValidate , value ) {
12+ const debounce = ( func , delay ) => {
13+ let timer ;
14+ return ( ...args ) =>
15+ new Promise ( ( resolve ) => {
16+ clearTimeout ( timer ) ;
17+ timer = setTimeout ( ( ) => resolve ( func ( ...args ) ) , delay ) ;
18+ } ) ;
19+ } ;
20+
21+ // API Validation Function
22+ async function asyncValidate ( fieldToValidate , value ) {
1323 if ( ! value || value . trim ( ) . length === 0 ) {
1424 return '' ;
1525 }
16- const queryParams = { } ;
17- queryParams [ fieldToValidate ] = value ;
18- queryParams . check_type = fieldToValidate ;
19- return apiClient
20- . get ( '/signup/duplicate_check' , { params : queryParams } )
21- . then ( ( response ) => {
22- if ( response . data . exists ) {
23- return response . data . message ;
24- }
25- return '' ;
26+ const queryParams = {
27+ [ fieldToValidate ] : value ,
28+ check_type : fieldToValidate
29+ } ;
30+
31+ try {
32+ const response = await apiClient . get ( '/signup/duplicate_check' , {
33+ params : queryParams
2634 } ) ;
35+ return response . data . exists ? response . data . message : '' ;
36+ } catch ( error ) {
37+ return 'Error validating field.' ;
38+ }
2739}
2840
41+ const debouncedAsyncValidate = debounce ( asyncValidate , 300 ) ;
42+
2943function validateUsername ( username ) {
30- return asyncValidate ( 'username' , username ) ;
44+ return debouncedAsyncValidate ( 'username' , username ) ;
3145}
3246
3347function validateEmail ( email ) {
34- return asyncValidate ( 'email' , email ) ;
48+ return debouncedAsyncValidate ( 'email' , email ) ;
3549}
3650
3751function SignupForm ( ) {
3852 const { t, i18n } = useTranslation ( ) ;
39-
4053 const dispatch = useDispatch ( ) ;
41- function onSubmit ( formProps ) {
42- return dispatch ( validateAndSignUpUser ( formProps ) ) ;
43- }
54+ const formRef = useRef ( null ) ;
4455 const [ showPassword , setShowPassword ] = useState ( false ) ;
4556 const [ showConfirmPassword , setShowConfirmPassword ] = useState ( false ) ;
46- const formRef = useRef ( null ) ;
47- const handleVisibility = ( ) => {
48- setShowPassword ( ! showPassword ) ;
49- } ;
50- const handleConfirmVisibility = ( ) => {
51- setShowConfirmPassword ( ! showConfirmPassword ) ;
52- } ;
57+
5358 useSyncFormTranslations ( formRef , i18n . language ) ;
5459
60+ const handleVisibility = ( ) => setShowPassword ( ! showPassword ) ;
61+ const handleConfirmVisibility = ( ) =>
62+ setShowConfirmPassword ( ! showConfirmPassword ) ;
63+
64+ function onSubmit ( formProps ) {
65+ return dispatch ( validateAndSignUpUser ( formProps ) ) ;
66+ }
67+
5568 return (
5669 < Form
5770 fields = { [ 'username' , 'email' , 'password' , 'confirmPassword' ] }
@@ -62,12 +75,13 @@ function SignupForm() {
6275 formRef . current = form ;
6376 return (
6477 < form className = "form" onSubmit = { handleSubmit } >
78+ { /* Username Field */ }
6579 < Field
6680 name = "username"
6781 validate = { validateUsername }
6882 validateFields = { [ ] }
6983 >
70- { ( field ) => (
84+ { ( { input , meta } ) => (
7185 < div className = "form__field" >
7286 < label htmlFor = "username" className = "form__label" >
7387 { t ( 'SignupForm.Title' ) }
@@ -79,18 +93,20 @@ function SignupForm() {
7993 id = "username"
8094 autoComplete = "username"
8195 autoCapitalize = "none"
82- { ...field . input }
96+ { ...input }
8397 />
84- { field . meta . touched && field . meta . error && (
98+ { meta . touched && meta . error && (
8599 < span className = "form-error" aria-live = "polite" >
86- { field . meta . error }
100+ { meta . error }
87101 </ span >
88102 ) }
89103 </ div >
90104 ) }
91105 </ Field >
106+
107+ { /* Email Field */ }
92108 < Field name = "email" validate = { validateEmail } validateFields = { [ ] } >
93- { ( field ) => (
109+ { ( { input , meta } ) => (
94110 < div className = "form__field" >
95111 < label htmlFor = "email" className = "form__label" >
96112 { t ( 'SignupForm.Email' ) }
@@ -101,18 +117,20 @@ function SignupForm() {
101117 type = "email"
102118 id = "email"
103119 autoComplete = "email"
104- { ...field . input }
120+ { ...input }
105121 />
106- { field . meta . touched && field . meta . error && (
122+ { meta . touched && meta . error && (
107123 < span className = "form-error" aria-live = "polite" >
108- { field . meta . error }
124+ { meta . error }
109125 </ span >
110126 ) }
111127 </ div >
112128 ) }
113129 </ Field >
130+
131+ { /* Password Field */ }
114132 < Field name = "password" >
115- { ( field ) => (
133+ { ( { input , meta } ) => (
116134 < div className = "form__field" >
117135 < label htmlFor = "password" className = "form__label" >
118136 { t ( 'SignupForm.Password' ) }
@@ -124,7 +142,7 @@ function SignupForm() {
124142 type = { showPassword ? 'text' : 'password' }
125143 id = "password"
126144 autoComplete = "new-password"
127- { ...field . input }
145+ { ...input }
128146 />
129147 < button
130148 className = "form__eye__icon"
@@ -139,28 +157,30 @@ function SignupForm() {
139157 ) }
140158 </ button >
141159 </ div >
142- { field . meta . touched && field . meta . error && (
160+ { meta . touched && meta . error && (
143161 < span className = "form-error" aria-live = "polite" >
144- { field . meta . error }
162+ { meta . error }
145163 </ span >
146164 ) }
147165 </ div >
148166 ) }
149167 </ Field >
168+
169+ { /* Confirm Password Field */ }
150170 < Field name = "confirmPassword" >
151- { ( field ) => (
171+ { ( { input , meta } ) => (
152172 < div className = "form__field" >
153173 < label htmlFor = "confirmPassword" className = "form__label" >
154174 { t ( 'SignupForm.ConfirmPassword' ) }
155175 </ label >
156176 < div className = "form__field__password" >
157177 < input
158178 className = "form__input"
159- type = { showConfirmPassword ? 'text' : 'password' }
160179 aria-label = { t ( 'SignupForm.ConfirmPasswordARIA' ) }
161- id = "confirmPassword" // Match the id with htmlFor
180+ type = { showConfirmPassword ? 'text' : 'password' }
181+ id = "confirmPassword"
162182 autoComplete = "new-password"
163- { ...field . input }
183+ { ...input }
164184 />
165185 < button
166186 className = "form__eye__icon"
@@ -175,14 +195,16 @@ function SignupForm() {
175195 ) }
176196 </ button >
177197 </ div >
178- { field . meta . touched && field . meta . error && (
198+ { meta . touched && meta . error && (
179199 < span className = "form-error" aria-live = "polite" >
180- { field . meta . error }
200+ { meta . error }
181201 </ span >
182202 ) }
183203 </ div >
184204 ) }
185205 </ Field >
206+
207+ { /* Submit Button */ }
186208 < Button type = "submit" disabled = { submitting || invalid || pristine } >
187209 { t ( 'SignupForm.SubmitSignup' ) }
188210 </ Button >
0 commit comments