phone auth, image uploading, address broken up
This commit is contained in:
@@ -2,7 +2,7 @@ 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 AddressAutocomplete from '../components/AddressAutocomplete';
|
||||
import { getImageUrl } from '../utils/imageUrl';
|
||||
|
||||
const Profile: React.FC = () => {
|
||||
const { user, updateUser, logout } = useAuth();
|
||||
@@ -16,7 +16,12 @@ const Profile: React.FC = () => {
|
||||
lastName: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
address: '',
|
||||
address1: '',
|
||||
address2: '',
|
||||
city: '',
|
||||
state: '',
|
||||
zipCode: '',
|
||||
country: '',
|
||||
profileImage: ''
|
||||
});
|
||||
const [imageFile, setImageFile] = useState<File | null>(null);
|
||||
@@ -41,11 +46,16 @@ const Profile: React.FC = () => {
|
||||
lastName: response.data.lastName || '',
|
||||
email: response.data.email || '',
|
||||
phone: response.data.phone || '',
|
||||
address: response.data.address || '',
|
||||
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(response.data.profileImage);
|
||||
setImagePreview(getImageUrl(response.data.profileImage));
|
||||
}
|
||||
} catch (err: any) {
|
||||
setError(err.response?.data?.message || 'Failed to fetch profile');
|
||||
@@ -82,15 +92,43 @@ const Profile: React.FC = () => {
|
||||
setFormData(prev => ({ ...prev, [name]: value }));
|
||||
};
|
||||
|
||||
const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const handleImageChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -100,18 +138,24 @@ const Profile: React.FC = () => {
|
||||
setSuccess(null);
|
||||
|
||||
try {
|
||||
const updateData = {
|
||||
...formData,
|
||||
profileImage: imagePreview || formData.profileImage
|
||||
};
|
||||
// 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
|
||||
setSuccess('Profile updated successfully!');
|
||||
setEditing(false);
|
||||
} catch (err: any) {
|
||||
setError(err.response?.data?.message || 'Failed to update profile');
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -126,10 +170,18 @@ const Profile: React.FC = () => {
|
||||
lastName: profileData.lastName || '',
|
||||
email: profileData.email || '',
|
||||
phone: profileData.phone || '',
|
||||
address: profileData.address || '',
|
||||
address1: profileData.address1 || '',
|
||||
address2: profileData.address2 || '',
|
||||
city: profileData.city || '',
|
||||
state: profileData.state || '',
|
||||
zipCode: profileData.zipCode || '',
|
||||
country: profileData.country || '',
|
||||
profileImage: profileData.profileImage || ''
|
||||
});
|
||||
setImagePreview(profileData.profileImage || null);
|
||||
setImagePreview(profileData.profileImage ?
|
||||
getImageUrl(profileData.profileImage) :
|
||||
null
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -248,7 +300,6 @@ const Profile: React.FC = () => {
|
||||
value={formData.email}
|
||||
onChange={handleChange}
|
||||
disabled={!editing}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -266,30 +317,88 @@ const Profile: React.FC = () => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<label htmlFor="address" className="form-label">Address</label>
|
||||
{editing ? (
|
||||
<AddressAutocomplete
|
||||
id="address"
|
||||
name="address"
|
||||
value={formData.address}
|
||||
onChange={(value) => {
|
||||
setFormData(prev => ({ ...prev, address: value }));
|
||||
}}
|
||||
placeholder="Enter your address"
|
||||
required={false}
|
||||
/>
|
||||
) : (
|
||||
<div className="row mb-3">
|
||||
<div className="col-md-6">
|
||||
<label htmlFor="address1" className="form-label">Address Line 1</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="address"
|
||||
name="address"
|
||||
value={formData.address}
|
||||
disabled
|
||||
readOnly
|
||||
id="address1"
|
||||
name="address1"
|
||||
value={formData.address1}
|
||||
onChange={handleChange}
|
||||
placeholder="123 Main Street"
|
||||
disabled={!editing}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<label htmlFor="address2" className="form-label">Address Line 2</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="address2"
|
||||
name="address2"
|
||||
value={formData.address2}
|
||||
onChange={handleChange}
|
||||
placeholder="Apt, Suite, Unit, etc."
|
||||
disabled={!editing}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row mb-3">
|
||||
<div className="col-md-6">
|
||||
<label htmlFor="city" className="form-label">City</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="city"
|
||||
name="city"
|
||||
value={formData.city}
|
||||
onChange={handleChange}
|
||||
disabled={!editing}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-md-3">
|
||||
<label htmlFor="state" className="form-label">State</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="state"
|
||||
name="state"
|
||||
value={formData.state}
|
||||
onChange={handleChange}
|
||||
placeholder="CA"
|
||||
disabled={!editing}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-md-3">
|
||||
<label htmlFor="zipCode" className="form-label">ZIP Code</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="zipCode"
|
||||
name="zipCode"
|
||||
value={formData.zipCode}
|
||||
onChange={handleChange}
|
||||
placeholder="12345"
|
||||
disabled={!editing}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<label htmlFor="country" className="form-label">Country</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="country"
|
||||
name="country"
|
||||
value={formData.country}
|
||||
onChange={handleChange}
|
||||
placeholder="United States"
|
||||
disabled={!editing}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{editing ? (
|
||||
|
||||
Reference in New Issue
Block a user