import React, { useState, useEffect } from 'react'; import { TextField, FormHelperText, Box, Chip } from '@mui/material'; import { CheckCircle, Error as ErrorIcon, Warning } from '@mui/icons-material'; import { useTranslation } from 'react-i18next'; import { validateUsername, validateEmail, validateUrl, validateTextField, validateInteger } from '../utils/inputValidator'; /** * ValidatedTextField Component * Provides client-side validation with visual feedback */ const ValidatedTextField = ({ type = 'text', value, onChange, validationType, minLength, maxLength, min, max, required = false, showValidation = true, relatedValues = {}, ...textFieldProps }) => { const { t } = useTranslation(); const [errors, setErrors] = useState([]); const [touched, setTouched] = useState(false); const [isValid, setIsValid] = useState(null); useEffect(() => { if (!touched || !value) { setErrors([]); setIsValid(null); return; } let validationResult; switch (validationType) { case 'username': validationResult = validateUsername(value); break; case 'email': validationResult = validateEmail(value); break; case 'url': validationResult = validateUrl(value); break; case 'integer': validationResult = validateInteger(value, min, max); break; case 'text': default: validationResult = validateTextField(value, minLength, maxLength, required); break; } setErrors(validationResult.errors); setIsValid(validationResult.valid); // If valid and sanitized value is different, update parent if (validationResult.valid && validationResult.sanitized !== value) { onChange({ target: { value: validationResult.sanitized } }); } }, [value, touched, validationType, minLength, maxLength, min, max, required]); const handleBlur = (e) => { setTouched(true); if (textFieldProps.onBlur) { textFieldProps.onBlur(e); } }; const handleChange = (e) => { onChange(e); }; const getValidationColor = () => { if (!showValidation || !touched || !value) return undefined; return isValid ? 'success' : 'error'; }; const getEndAdornment = () => { if (!showValidation || !touched || !value) return textFieldProps.InputProps?.endAdornment; const adornment = ( {isValid ? ( ) : ( )} {textFieldProps.InputProps?.endAdornment} ); return adornment; }; return ( 0} color={getValidationColor()} InputProps={{ ...textFieldProps.InputProps, endAdornment: getEndAdornment() }} /> {showValidation && touched && errors.length > 0 && ( {errors.map((error, index) => ( {error} ))} )} {showValidation && touched && isValid && ( {t('security.inputSanitized')} )} ); }; export default ValidatedTextField;