@@ -119,8 +119,25 @@ const Contact: React.FC = () => {
119119 { type : 'ai' , text : '>>> [AiTor]: Neural connection active. Ready to assist.' }
120120 ] ) ;
121121
122+ const [ formErrors , setFormErrors ] = useState < Record < string , string > > ( { } ) ;
123+
124+ const emailRegex = / ^ [ ^ \s @ ] + @ [ ^ \s @ ] + \. [ ^ \s @ ] + $ / ;
125+
126+ const validateForm = ( ) : boolean => {
127+ const errors : Record < string , string > = { } ;
128+ if ( ! formData . name . trim ( ) || formData . name . trim ( ) . length < 2 ) errors . name = 'Name must be at least 2 characters' ;
129+ if ( formData . name . length > 100 ) errors . name = 'Name must be less than 100 characters' ;
130+ if ( ! emailRegex . test ( formData . email ) ) errors . email = 'Please enter a valid email address' ;
131+ if ( formData . subject . length > 200 ) errors . subject = 'Subject must be less than 200 characters' ;
132+ if ( ! formData . message . trim ( ) || formData . message . trim ( ) . length < 10 ) errors . message = 'Message must be at least 10 characters' ;
133+ if ( formData . message . length > 2000 ) errors . message = 'Message must be less than 2000 characters' ;
134+ setFormErrors ( errors ) ;
135+ return Object . keys ( errors ) . length === 0 ;
136+ } ;
137+
122138 const handleFormSubmit = ( e : React . FormEvent ) => {
123139 e . preventDefault ( ) ;
140+ if ( ! validateForm ( ) ) return ;
124141 setIsSubmitting ( true ) ;
125142 const mailtoLink = `mailto:alien69flow@proton.me?subject=${ encodeURIComponent ( formData . subject ) } &body=${ encodeURIComponent ( `FROM: ${ formData . name } \nEMAIL: ${ formData . email } \n\n${ formData . message } ` ) } ` ;
126143 window . location . href = mailtoLink ;
@@ -418,32 +435,48 @@ const Contact: React.FC = () => {
418435 </ div >
419436
420437 < form onSubmit = { handleFormSubmit } className = "space-y-4" >
421- < Input
422- placeholder = "Your Name"
423- value = { formData . name }
424- onChange = { e => setFormData ( { ...formData , name : e . target . value } ) }
425- className = "bg-black/40 border-alien-green/20 text-white focus:border-alien-green/60 rounded-xl h-11 placeholder:text-muted-foreground/60 text-sm"
426- />
427- < Input
428- placeholder = "Email Address"
429- type = "email"
430- value = { formData . email }
431- onChange = { e => setFormData ( { ...formData , email : e . target . value } ) }
432- className = "bg-black/40 border-alien-green/20 text-white focus:border-alien-green/60 rounded-xl h-11 placeholder:text-muted-foreground/60 text-sm"
433- />
434- < Input
435- placeholder = "Subject"
436- value = { formData . subject }
437- onChange = { e => setFormData ( { ...formData , subject : e . target . value } ) }
438- className = "bg-black/40 border-alien-green/20 text-white focus:border-alien-green/60 rounded-xl h-11 placeholder:text-muted-foreground/60 text-sm"
439- />
440- < Textarea
441- placeholder = "Your message to the cosmos..."
442- rows = { 4 }
443- value = { formData . message }
444- onChange = { e => setFormData ( { ...formData , message : e . target . value } ) }
445- className = "bg-black/40 border-alien-green/20 text-white focus:border-alien-green/60 rounded-xl placeholder:text-muted-foreground/60 resize-none text-sm"
446- />
438+ < div >
439+ < Input
440+ placeholder = "Your Name"
441+ value = { formData . name }
442+ onChange = { e => setFormData ( { ...formData , name : e . target . value } ) }
443+ maxLength = { 100 }
444+ className = "bg-black/40 border-alien-green/20 text-white focus:border-alien-green/60 rounded-xl h-11 placeholder:text-muted-foreground/60 text-sm"
445+ />
446+ { formErrors . name && < p className = "text-red-400 text-xs mt-1 font-exo" > { formErrors . name } </ p > }
447+ </ div >
448+ < div >
449+ < Input
450+ placeholder = "Email Address"
451+ type = "email"
452+ value = { formData . email }
453+ onChange = { e => setFormData ( { ...formData , email : e . target . value } ) }
454+ maxLength = { 255 }
455+ className = "bg-black/40 border-alien-green/20 text-white focus:border-alien-green/60 rounded-xl h-11 placeholder:text-muted-foreground/60 text-sm"
456+ />
457+ { formErrors . email && < p className = "text-red-400 text-xs mt-1 font-exo" > { formErrors . email } </ p > }
458+ </ div >
459+ < div >
460+ < Input
461+ placeholder = "Subject"
462+ value = { formData . subject }
463+ onChange = { e => setFormData ( { ...formData , subject : e . target . value } ) }
464+ maxLength = { 200 }
465+ className = "bg-black/40 border-alien-green/20 text-white focus:border-alien-green/60 rounded-xl h-11 placeholder:text-muted-foreground/60 text-sm"
466+ />
467+ { formErrors . subject && < p className = "text-red-400 text-xs mt-1 font-exo" > { formErrors . subject } </ p > }
468+ </ div >
469+ < div >
470+ < Textarea
471+ placeholder = "Your message to the cosmos..."
472+ rows = { 4 }
473+ value = { formData . message }
474+ onChange = { e => setFormData ( { ...formData , message : e . target . value } ) }
475+ maxLength = { 2000 }
476+ className = "bg-black/40 border-alien-green/20 text-white focus:border-alien-green/60 rounded-xl placeholder:text-muted-foreground/60 resize-none text-sm"
477+ />
478+ { formErrors . message && < p className = "text-red-400 text-xs mt-1 font-exo" > { formErrors . message } </ p > }
479+ </ div >
447480 < Button
448481 type = "submit"
449482 disabled = { isSubmitting }
0 commit comments