/** * Auth Validation Utilities * * Pure functions for client-side validation of auth forms. * No side effects, synchronous. */ export interface SignupFormData { firstName: string; lastName: string; email: string; password: string; confirmPassword: string; } export interface ForgotPasswordFormData { email: string; } export interface ResetPasswordFormData { newPassword: string; confirmPassword: string; } export interface SignupValidationError { field: keyof SignupFormData; message: string; } export interface ForgotPasswordValidationError { field: keyof ForgotPasswordFormData; message: string; } export interface ResetPasswordValidationError { field: keyof ResetPasswordFormData; message: string; } export class SignupFormValidation { static validateForm(data: SignupFormData): SignupValidationError[] { const errors: SignupValidationError[] = []; // First name if (!data.firstName.trim()) { errors.push({ field: 'firstName', message: 'First name is required' }); } else if (data.firstName.trim().length < 2) { errors.push({ field: 'firstName', message: 'First name must be at least 2 characters' }); } // Last name if (!data.lastName.trim()) { errors.push({ field: 'lastName', message: 'Last name is required' }); } else if (data.lastName.trim().length < 2) { errors.push({ field: 'lastName', message: 'Last name must be at least 2 characters' }); } // Email if (!data.email.trim()) { errors.push({ field: 'email', message: 'Email is required' }); } else if (!this.isValidEmail(data.email)) { errors.push({ field: 'email', message: 'Please enter a valid email address' }); } // Password if (!data.password) { errors.push({ field: 'password', message: 'Password is required' }); } else if (data.password.length < 8) { errors.push({ field: 'password', message: 'Password must be at least 8 characters' }); } else if (!this.hasValidPasswordComplexity(data.password)) { errors.push({ field: 'password', message: 'Password must contain at least one uppercase letter, one lowercase letter, and one number' }); } // Confirm password if (!data.confirmPassword) { errors.push({ field: 'confirmPassword', message: 'Please confirm your password' }); } else if (data.password !== data.confirmPassword) { errors.push({ field: 'confirmPassword', message: 'Passwords do not match' }); } return errors; } static generateDisplayName(firstName: string, lastName: string): string { const trimmedFirst = firstName.trim(); const trimmedLast = lastName.trim(); return `${trimmedFirst} ${trimmedLast}`.trim() || trimmedFirst || trimmedLast; } private static isValidEmail(email: string): boolean { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); } private static hasValidPasswordComplexity(password: string): boolean { return /[a-z]/.test(password) && /[A-Z]/.test(password) && /\d/.test(password); } } export class ForgotPasswordFormValidation { static validateForm(data: ForgotPasswordFormData): ForgotPasswordValidationError[] { const errors: ForgotPasswordValidationError[] = []; // Email if (!data.email.trim()) { errors.push({ field: 'email', message: 'Email is required' }); } else if (!this.isValidEmail(data.email)) { errors.push({ field: 'email', message: 'Please enter a valid email address' }); } return errors; } private static isValidEmail(email: string): boolean { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); } } export class ResetPasswordFormValidation { static validateForm(data: ResetPasswordFormData): ResetPasswordValidationError[] { const errors: ResetPasswordValidationError[] = []; // New password if (!data.newPassword) { errors.push({ field: 'newPassword', message: 'New password is required' }); } else if (data.newPassword.length < 8) { errors.push({ field: 'newPassword', message: 'Password must be at least 8 characters' }); } else if (!this.hasValidPasswordComplexity(data.newPassword)) { errors.push({ field: 'newPassword', message: 'Password must contain at least one uppercase letter, one lowercase letter, and one number' }); } // Confirm password if (!data.confirmPassword) { errors.push({ field: 'confirmPassword', message: 'Please confirm your new password' }); } else if (data.newPassword !== data.confirmPassword) { errors.push({ field: 'confirmPassword', message: 'Passwords do not match' }); } return errors; } private static hasValidPasswordComplexity(password: string): boolean { return /[a-z]/.test(password) && /[A-Z]/.test(password) && /\d/.test(password); } }