'use client' import { useState, useEffect } from 'react' import { validateEmail, sanitizeString } from '@/lib/validation' import { updateProfile } from '@/lib/auth-actions' import { useToast } from './ToastContainer' interface ProfileFormProps { initialName: string | null initialEmail: string userId: string } export default function ProfileForm({ initialName, initialEmail, userId }: ProfileFormProps) { const { showToast } = useToast() const [name, setName] = useState(initialName || '') const [email, setEmail] = useState(initialEmail) const [isSubmitting, setIsSubmitting] = useState(false) const [errors, setErrors] = useState<{ name?: string email?: string }>({}) const [touched, setTouched] = useState<{ name: boolean email: boolean }>({ name: false, email: false, }) // Check if form has changes const hasChanges = name !== (initialName || '') || email !== initialEmail // Inline validation when fields change useEffect(() => { if (touched.name) { const sanitized = sanitizeString(name) if (!sanitized) { setErrors((prev) => ({ ...prev, name: 'Name is required' })) } else if (sanitized.length > 100) { setErrors((prev) => ({ ...prev, name: 'Name must be less than 100 characters' })) } else { setErrors((prev) => ({ ...prev, name: undefined })) } } }, [name, touched.name]) useEffect(() => { if (touched.email) { const result = validateEmail(email) setErrors((prev) => ({ ...prev, email: result.isValid ? undefined : result.error, })) } }, [email, touched.email]) const handleNameBlur = () => { setTouched((prev) => ({ ...prev, name: true })) } const handleEmailBlur = () => { setTouched((prev) => ({ ...prev, email: true })) } const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() // Validate all fields before submission const sanitizedName = sanitizeString(name) const emailResult = validateEmail(email) const newErrors: { name?: string email?: string } = {} if (!sanitizedName) { newErrors.name = 'Name is required' } else if (sanitizedName.length > 100) { newErrors.name = 'Name must be less than 100 characters' } if (!emailResult.isValid) { newErrors.email = emailResult.error } if (Object.keys(newErrors).length > 0) { setErrors(newErrors) setTouched({ name: true, email: true }) return } if (!hasChanges) { showToast('No changes to save', 'info') return } setIsSubmitting(true) setErrors({}) try { const updateData: { name?: string; email?: string } = {} if (name !== (initialName || '')) { updateData.name = sanitizedName } if (email !== initialEmail) { updateData.email = email.trim() } const result = await updateProfile(userId, updateData) if (!result.success) { if (result.error === 'Email already in use') { setErrors({ email: 'This email is already in use' }) showToast('Email already in use', 'error') } else { showToast(result.error || 'Profile update failed', 'error') } } else { showToast('Profile updated successfully', 'success') // Refresh the page to update the session window.location.reload() } } catch (err) { console.error('Profile update error:', err) showToast('An error occurred. Please try again.', 'error') } finally { setIsSubmitting(false) } } return (
setName(e.target.value)} onBlur={handleNameBlur} className={`w-full px-3 sm:px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 text-sm sm:text-base ${ errors.name && touched.name ? 'border-red-500 focus:ring-red-500' : 'border-gray-300 focus:ring-blue-500' }`} placeholder="Enter your name" disabled={isSubmitting} autoComplete="name" maxLength={100} aria-invalid={errors.name && touched.name ? 'true' : 'false'} aria-describedby={errors.name && touched.name ? 'name-error' : undefined} /> {errors.name && touched.name && (

{errors.name}

)}
setEmail(e.target.value)} onBlur={handleEmailBlur} className={`w-full px-3 sm:px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 text-sm sm:text-base ${ errors.email && touched.email ? 'border-red-500 focus:ring-red-500' : 'border-gray-300 focus:ring-blue-500' }`} placeholder="Enter your email" disabled={isSubmitting} autoComplete="email" aria-invalid={errors.email && touched.email ? 'true' : 'false'} aria-describedby={errors.email && touched.email ? 'email-error' : undefined} /> {errors.email && touched.email && (

{errors.email}

)}
) }