Skip to content

Commit ca49afb

Browse files
committed
password validation as user types. don't let the user submit if password doesn't pass validation
1 parent 0f04d27 commit ca49afb

File tree

1 file changed

+36
-11
lines changed

1 file changed

+36
-11
lines changed

frontend/src/pages/participant-form.tsx

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)