import React, { useState, useEffect } from 'react'; import { useAuth } from '../contexts/AuthContext'; import { userAPI, itemAPI, rentalAPI } from '../services/api'; import { User, Item, Rental } from '../types'; import { getImageUrl } from '../utils/imageUrl'; const Profile: React.FC = () => { const { user, updateUser, logout } = useAuth(); const [loading, setLoading] = useState(true); const [editing, setEditing] = useState(false); const [error, setError] = useState(null); const [success, setSuccess] = useState(null); const [profileData, setProfileData] = useState(null); const [formData, setFormData] = useState({ firstName: '', lastName: '', email: '', phone: '', address1: '', address2: '', city: '', state: '', zipCode: '', country: '', profileImage: '' }); const [imageFile, setImageFile] = useState(null); const [imagePreview, setImagePreview] = useState(null); const [stats, setStats] = useState({ itemsListed: 0, acceptedRentals: 0, totalRentals: 0 }); useEffect(() => { fetchProfile(); fetchStats(); }, []); const fetchProfile = async () => { try { const response = await userAPI.getProfile(); setProfileData(response.data); setFormData({ firstName: response.data.firstName || '', lastName: response.data.lastName || '', email: response.data.email || '', phone: response.data.phone || '', address1: response.data.address1 || '', address2: response.data.address2 || '', city: response.data.city || '', state: response.data.state || '', zipCode: response.data.zipCode || '', country: response.data.country || '', profileImage: response.data.profileImage || '' }); if (response.data.profileImage) { setImagePreview(getImageUrl(response.data.profileImage)); } } catch (err: any) { setError(err.response?.data?.message || 'Failed to fetch profile'); } finally { setLoading(false); } }; const fetchStats = async () => { try { // Fetch user's items const itemsResponse = await itemAPI.getItems(); const allItems = itemsResponse.data.items || itemsResponse.data || []; const myItems = allItems.filter((item: Item) => item.ownerId === user?.id); // Fetch rentals where user is the owner (rentals on user's items) const ownerRentalsResponse = await rentalAPI.getMyListings(); const ownerRentals: Rental[] = ownerRentalsResponse.data; const acceptedRentals = ownerRentals.filter(r => ['confirmed', 'active'].includes(r.status)); setStats({ itemsListed: myItems.length, acceptedRentals: acceptedRentals.length, totalRentals: ownerRentals.length }); } catch (err) { console.error('Failed to fetch stats:', err); } }; const handleChange = (e: React.ChangeEvent) => { const { name, value } = e.target; setFormData(prev => ({ ...prev, [name]: value })); }; const handleImageChange = async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (file) { setImageFile(file); // Show preview const reader = new FileReader(); reader.onloadend = () => { setImagePreview(reader.result as string); }; reader.readAsDataURL(file); // Upload image immediately try { const formData = new FormData(); formData.append('profileImage', file); const response = await userAPI.uploadProfileImage(formData); // Update the profileImage in formData with the new filename setFormData(prev => ({ ...prev, profileImage: response.data.filename })); // Update preview to use the uploaded image URL setImagePreview(getImageUrl(response.data.imageUrl)); } catch (err: any) { console.error('Image upload error:', err); setError(err.response?.data?.error || 'Failed to upload image'); // Reset on error setImageFile(null); setImagePreview(profileData?.profileImage ? getImageUrl(profileData.profileImage) : null ); } } }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(null); setSuccess(null); try { // Don't send profileImage in the update data as it's handled separately const { profileImage, ...updateData } = formData; const response = await userAPI.updateProfile(updateData); setProfileData(response.data); updateUser(response.data); // Update the auth context setEditing(false); } catch (err: any) { console.error('Profile update error:', err.response?.data); const errorMessage = err.response?.data?.error || err.response?.data?.message || 'Failed to update profile'; const errorDetails = err.response?.data?.details; if (errorDetails && Array.isArray(errorDetails)) { const detailMessages = errorDetails.map((d: any) => `${d.field}: ${d.message}`).join(', '); setError(`${errorMessage} - ${detailMessages}`); } else { setError(errorMessage); } } }; const handleCancel = () => { setEditing(false); setError(null); setSuccess(null); // Reset form to original data if (profileData) { setFormData({ firstName: profileData.firstName || '', lastName: profileData.lastName || '', email: profileData.email || '', phone: profileData.phone || '', address1: profileData.address1 || '', address2: profileData.address2 || '', city: profileData.city || '', state: profileData.state || '', zipCode: profileData.zipCode || '', country: profileData.country || '', profileImage: profileData.profileImage || '' }); setImagePreview(profileData.profileImage ? getImageUrl(profileData.profileImage) : null ); } }; if (loading) { return (
Loading...
); } return (

My Profile

{error && (
{error}
)} {success && (
{success}
)}
{imagePreview ? ( Profile ) : (
)} {editing && ( )}
{profileData?.firstName} {profileData?.lastName}

@{profileData?.username}

{profileData?.isVerified && ( Verified )}
{editing ? (
) : ( )}
Account Statistics

{stats.itemsListed}

Items Listed

{stats.acceptedRentals}

Accepted Rentals

{stats.totalRentals}

Total Rentals

); }; export default Profile;