'use client'; import { useState, useRef, useEffect } from 'react'; import Image from 'next/image'; import { useSession, signIn } from 'next-auth/react'; import { uploadService } from '@/services/upload.service'; import { agentsService } from '@/services/agents.service'; interface ProfileSettingsFormProps { initialData?: { fullName: string; career: string; email: string; phone: string; location: string; avatar?: string; }; onSave?: (data: { fullName: string; career: string; email: string; phone: string; location: string; }) => void; descriptionText?: string; } export function ProfileSettingsForm({ initialData, onSave, descriptionText = 'This information will be displayed on your public profile page.', }: ProfileSettingsFormProps) { const { data: session, update: updateSession } = useSession(); const fileInputRef = useRef(null); const [formData, setFormData] = useState({ fullName: initialData?.fullName || '', career: initialData?.career || '', email: initialData?.email || '', phone: initialData?.phone || '', location: initialData?.location || '', }); const [avatarUrl, setAvatarUrl] = useState(null); const [isUploading, setIsUploading] = useState(false); const [uploadProgress, setUploadProgress] = useState(0); const [isLoading, setIsLoading] = useState(true); const [isSaving, setIsSaving] = useState(false); const [error, setError] = useState(null); const [successMessage, setSuccessMessage] = useState(null); // Fetch profile data on mount useEffect(() => { const fetchProfile = async () => { try { setIsLoading(true); const profile = await agentsService.getMyProfile(); setFormData({ fullName: `${profile.firstName || ''} ${profile.lastName || ''}`.trim(), career: profile.agentType?.name || 'Real Estate Agent', email: profile.email || session?.user?.email || '', phone: profile.phone || '', location: profile.serviceAreas?.[0] || '', }); // Handle avatar URL - if it's an S3 key, get presigned URL if (profile.avatar) { try { const presignedUrl = await uploadService.getPresignedDownloadUrl(profile.avatar); setAvatarUrl(presignedUrl); } catch { // If getting presigned URL fails, the avatar might be a full URL setAvatarUrl(profile.avatar); } } } catch (err) { console.error('Failed to fetch profile:', err); // Use session data as fallback if (session?.user) { setFormData(prev => ({ ...prev, fullName: session.user?.name || prev.fullName, email: session.user?.email || prev.email, })); if (session.user.image) { setAvatarUrl(session.user.image); } } } finally { setIsLoading(false); } }; if (session) { fetchProfile(); } }, [session]); const handleChange = (field: string, value: string) => { setFormData((prev) => ({ ...prev, [field]: value })); setError(null); setSuccessMessage(null); }; const handleUploadClick = () => { fileInputRef.current?.click(); }; const handleFileChange = async (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (!file) return; // Validate file type const validTypes = ['image/jpeg', 'image/png', 'image/gif']; if (!validTypes.includes(file.type)) { setError('Please upload a JPEG, PNG, or GIF image.'); return; } // Validate file size (2MB max) const maxSize = 2 * 1024 * 1024; if (file.size > maxSize) { setError('File size must be less than 2MB.'); return; } try { setIsUploading(true); setError(null); setUploadProgress(0); // Upload the avatar const uploadedFile = await uploadService.uploadAvatar(file, (progress) => { setUploadProgress(progress.percentage); }); // Update the profile with the new avatar key await agentsService.updateProfile({ avatar: uploadedFile.url }); // Get the presigned URL for display const presignedUrl = await uploadService.getPresignedDownloadUrl(uploadedFile.url); setAvatarUrl(presignedUrl); // Update the session to reflect the new avatar await updateSession({ ...session, user: { ...session?.user, image: presignedUrl, }, }); setSuccessMessage('Profile picture updated successfully!'); } catch (err) { console.error('Upload failed:', err); setError('Failed to upload profile picture. Please try again.'); } finally { setIsUploading(false); setUploadProgress(0); // Reset file input if (fileInputRef.current) { fileInputRef.current.value = ''; } } }; const handleDeleteAvatar = async () => { try { setIsUploading(true); setError(null); // Update profile to remove avatar await agentsService.updateProfile({ avatar: null }); setAvatarUrl(null); // Update session await updateSession({ ...session, user: { ...session?.user, image: null, }, }); setSuccessMessage('Profile picture removed successfully!'); } catch (err) { console.error('Delete failed:', err); setError('Failed to remove profile picture. Please try again.'); } finally { setIsUploading(false); } }; const handleSave = async () => { try { setIsSaving(true); setError(null); // Split full name into first and last name const nameParts = formData.fullName.trim().split(' '); const firstName = nameParts[0] || ''; const lastName = nameParts.slice(1).join(' ') || ''; // Update profile await agentsService.updateProfile({ firstName, lastName, email: formData.email, phone: formData.phone, serviceAreas: formData.location ? [formData.location] : [], }); // Update session with new name await updateSession({ ...session, user: { ...session?.user, name: formData.fullName, }, }); if (onSave) { onSave(formData); } setSuccessMessage('Profile settings saved successfully!'); } catch (err) { console.error('Save failed:', err); setError('Failed to save profile settings. Please try again.'); } finally { setIsSaving(false); } }; const handleCancel = () => { // Reset to initial data or session data if (session?.user) { setFormData(prev => ({ ...prev, fullName: session.user?.name || prev.fullName, email: session.user?.email || prev.email, })); } setError(null); setSuccessMessage(null); }; if (isLoading) { return (
); } return (
{/* Header */}

Public Profile

{descriptionText}

{/* Error/Success Messages */} {error && (
{error}
)} {successMessage && (
{successMessage}
)} {/* Profile Photo Section */}
{avatarUrl ? ( Profile ) : ( Profile )}

Public Picture

Supported formats: JPEG, PNG, GIF Max file size: 2MB

{/* Form Fields */}
{/* Row 1: Full Name & Career */}
handleChange('fullName', e.target.value)} className="w-full h-[44px] px-4 border border-[#00293D]/20 rounded-[10px] text-[14px] font-serif text-[#00293D] focus:outline-none focus:border-[#E58625]" />
handleChange('career', e.target.value)} className="w-full h-[44px] px-4 border border-[#00293D]/20 rounded-[10px] text-[14px] font-serif text-[#00293D] focus:outline-none focus:border-[#E58625]" />
{/* Row 2: Email & Phone */}
handleChange('email', e.target.value)} className="w-full h-[44px] px-4 border border-[#00293D]/20 rounded-[10px] text-[14px] font-serif text-[#00293D] focus:outline-none focus:border-[#E58625]" />
handleChange('phone', e.target.value)} className="w-full h-[44px] px-4 border border-[#00293D]/20 rounded-[10px] text-[14px] font-serif text-[#00293D] focus:outline-none focus:border-[#E58625]" />
{/* Row 3: Location */}
Location
handleChange('location', e.target.value)} className="w-full sm:w-1/2 h-[44px] pl-10 pr-4 border border-[#00293D]/20 rounded-[10px] text-[14px] font-serif text-[#00293D] focus:outline-none focus:border-[#E58625]" />
{/* Action Buttons */}
); }