@@ -21,13 +21,39 @@ export function ParticipantFormPage() {
2121 const [ passwordValidationErrors , setPasswordValidationErrors ] = useState < string [ ] > ( [ ] ) ;
2222 const router = useRouter ( ) ;
2323
24+ // Frontend password validation function that mirrors backend logic
25+ const validatePasswordFrontend = ( password : string ) : string [ ] => {
26+ const errors : string [ ] = [ ] ;
27+ if ( password . length < 8 ) {
28+ errors . push ( 'Password must be at least 8 characters long' ) ;
29+ }
30+ if ( ! / [ A - Z ] / . test ( password ) ) {
31+ errors . push ( 'Password must contain at least one uppercase letter' ) ;
32+ }
33+ if ( ! / [ a - z ] / . test ( password ) ) {
34+ errors . push ( 'Password must contain at least one lowercase letter' ) ;
35+ }
36+ if ( ! / [ ! @ # $ % ^ & * ] / . test ( password ) ) {
37+ errors . push (
38+ 'Password must contain at least one special character (!, @, #, $, %, ^, &, or *)' ,
39+ ) ;
40+ }
41+ return errors ;
42+ } ;
43+
2444 const handleSubmit = async ( e : React . FormEvent ) => {
2545 e . preventDefault ( ) ;
2646 setError ( '' ) ;
2747 if ( password !== confirmPassword ) {
2848 setError ( 'Passwords do not match' ) ;
2949 return ;
3050 }
51+
52+ if ( passwordValidationErrors . length > 0 ) {
53+ setError ( 'Please fix the password requirements above' ) ;
54+ return ;
55+ }
56+
3157 const userData = {
3258 first_name : '' ,
3359 last_name : '' ,
@@ -46,14 +72,7 @@ export function ParticipantFormPage() {
4672 setError ( '' ) ; // Clear any error messages
4773 router . push ( `/verify?email=${ encodeURIComponent ( email ) } &role=${ signupType } ` ) ;
4874 } else {
49- // Handle registration failure
50- if ( result . error === 'password_validation' && result . validationErrors ) {
51- setError ( '' ) ; // Clear any previous errors
52- setPasswordValidationErrors ( result . validationErrors ) ;
53- } else {
54- setPasswordValidationErrors ( [ ] ) ; // Clear validation errors
55- setError ( result . error || 'Registration failed' ) ;
56- }
75+ setError ( result . error || 'Registration failed' ) ;
5776 }
5877 } ;
5978
@@ -170,7 +189,13 @@ export function ParticipantFormPage() {
170189 borderColor = "#D5D7DA"
171190 _placeholder = { { color : '#A0AEC0' , fontWeight : 400 } }
172191 value = { password }
173- onChange = { ( e ) => setPassword ( e . target . value ) }
192+ onChange = { ( e ) => {
193+ const newPassword = e . target . value ;
194+ setPassword ( newPassword ) ;
195+ // Real-time validation as user types
196+ const errors = validatePasswordFrontend ( newPassword ) ;
197+ setPasswordValidationErrors ( errors ) ;
198+ } }
174199 />
175200 </ InputGroup >
176201 </ Field >
@@ -210,8 +235,8 @@ export function ParticipantFormPage() {
210235 </ InputGroup >
211236 </ Field >
212237
213- { /* Password Requirements - Only show when there are validation errors */ }
214- { passwordValidationErrors . length > 0 && (
238+ { /* Password Requirements - Show when user starts typing */ }
239+ { password . length > 0 && (
215240 < Box mb = { 4 } >
216241 < Box display = "flex" flexDirection = "column" gap = "6px" >
217242 { [
0 commit comments