diff --git a/frontend/src/components/profile/PasswordChangeForm.jsx b/frontend/src/components/profile/PasswordChangeForm.jsx new file mode 100644 index 0000000..d949518 --- /dev/null +++ b/frontend/src/components/profile/PasswordChangeForm.jsx @@ -0,0 +1,107 @@ +import { useState } from 'react'; +import { authAPI } from '../../services/api'; +import Alert from '../common/Alert'; +import FormInput from '../common/FormInput'; +import LoadingButton from '../common/LoadingButton'; +import { Lock } from 'lucide-react'; + +const PasswordChangeForm = () => { + const [passwordData, setPasswordData] = useState({ + currentPassword: '', + newPassword: '', + confirmPassword: '', + }); + const [loading, setLoading] = useState(false); + const [message, setMessage] = useState(''); + const [error, setError] = useState(''); + + const handleChange = (e) => { + setPasswordData({ ...passwordData, [e.target.name]: e.target.value }); + setMessage(''); + setError(''); + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + setLoading(true); + setMessage(''); + setError(''); + + if (passwordData.newPassword !== passwordData.confirmPassword) { + setError('New passwords do not match'); + setLoading(false); + return; + } + + try { + const response = await authAPI.changePassword( + passwordData.currentPassword, + passwordData.newPassword + ); + + if (response.success) { + setMessage(response.message); + setPasswordData({ + currentPassword: '', + newPassword: '', + confirmPassword: '', + }); + } + } catch (err) { + setError(err.data?.error || 'Failed to change password'); + } finally { + setLoading(false); + } + }; + + return ( +
+ ); +}; + +export default PasswordChangeForm; diff --git a/frontend/src/components/profile/ProfileForm.jsx b/frontend/src/components/profile/ProfileForm.jsx new file mode 100644 index 0000000..caa412f --- /dev/null +++ b/frontend/src/components/profile/ProfileForm.jsx @@ -0,0 +1,213 @@ +import { useState, useEffect } from 'react'; +import { authAPI } from '../../services/api'; +import Alert from '../common/Alert'; +import FormInput from '../common/FormInput'; +import FormSelect from '../common/FormSelect'; +import LoadingButton from '../common/LoadingButton'; +import { Mail, Save, Hash, Youtube, Instagram, Facebook, MapPin, Globe } from 'lucide-react'; +import { COUNTRIES } from '../../data/countries'; + +const TikTokIcon = () => ( + +); + +const ProfileForm = ({ user, onUserUpdate }) => { + const [profileData, setProfileData] = useState({ + firstName: '', + lastName: '', + email: '', + wsdcId: '', + youtubeUrl: '', + instagramUrl: '', + facebookUrl: '', + tiktokUrl: '', + country: '', + city: '', + }); + const [loading, setLoading] = useState(false); + const [message, setMessage] = useState(''); + const [error, setError] = useState(''); + + useEffect(() => { + if (user) { + setProfileData({ + firstName: user.firstName || '', + lastName: user.lastName || '', + email: user.email || '', + wsdcId: user.wsdcId || '', + youtubeUrl: user.youtubeUrl || '', + instagramUrl: user.instagramUrl || '', + facebookUrl: user.facebookUrl || '', + tiktokUrl: user.tiktokUrl || '', + country: user.country || '', + city: user.city || '', + }); + } + }, [user]); + + const handleChange = (e) => { + setProfileData({ ...profileData, [e.target.name]: e.target.value }); + setMessage(''); + setError(''); + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + setLoading(true); + setMessage(''); + setError(''); + + try { + const response = await authAPI.updateProfile(profileData); + + if (response.success) { + if (response.data.user) { + onUserUpdate(response.data.user); + } + + setMessage(response.message); + + if (response.data.emailChanged) { + setMessage( + 'Profile updated! Please check your new email address to verify it.' + ); + } + } + } catch (err) { + setError(err.data?.error || 'Failed to update profile'); + } finally { + setLoading(false); + } + }; + + return ( + + ); +}; + +export default ProfileForm; diff --git a/frontend/src/components/profile/index.js b/frontend/src/components/profile/index.js new file mode 100644 index 0000000..f543e13 --- /dev/null +++ b/frontend/src/components/profile/index.js @@ -0,0 +1,2 @@ +export { default as ProfileForm } from './ProfileForm'; +export { default as PasswordChangeForm } from './PasswordChangeForm'; diff --git a/frontend/src/pages/ProfilePage.jsx b/frontend/src/pages/ProfilePage.jsx index 23c20c1..6ca2753 100644 --- a/frontend/src/pages/ProfilePage.jsx +++ b/frontend/src/pages/ProfilePage.jsx @@ -1,142 +1,14 @@ -import { useState, useEffect } from 'react'; +import { useState } from 'react'; import { useAuth } from '../contexts/AuthContext'; -import { authAPI } from '../services/api'; import Layout from '../components/layout/Layout'; -import Alert from '../components/common/Alert'; -import FormInput from '../components/common/FormInput'; -import FormSelect from '../components/common/FormSelect'; -import LoadingButton from '../components/common/LoadingButton'; import Avatar from '../components/common/Avatar'; -import { User, Mail, Lock, Save, Hash, Youtube, Instagram, Facebook, MapPin, Globe } from 'lucide-react'; -import { COUNTRIES } from '../data/countries'; +import { ProfileForm, PasswordChangeForm } from '../components/profile'; +import { User, Lock } from 'lucide-react'; const ProfilePage = () => { const { user, updateUser } = useAuth(); const [activeTab, setActiveTab] = useState('profile'); - // Profile edit state - const [profileData, setProfileData] = useState({ - firstName: '', - lastName: '', - email: '', - wsdcId: '', - youtubeUrl: '', - instagramUrl: '', - facebookUrl: '', - tiktokUrl: '', - country: '', - city: '', - }); - - // Load user data when component mounts or user changes - useEffect(() => { - if (user) { - setProfileData({ - firstName: user.firstName || '', - lastName: user.lastName || '', - email: user.email || '', - wsdcId: user.wsdcId || '', - youtubeUrl: user.youtubeUrl || '', - instagramUrl: user.instagramUrl || '', - facebookUrl: user.facebookUrl || '', - tiktokUrl: user.tiktokUrl || '', - country: user.country || '', - city: user.city || '', - }); - } - }, [user]); - - const [profileLoading, setProfileLoading] = useState(false); - const [profileMessage, setProfileMessage] = useState(''); - const [profileError, setProfileError] = useState(''); - - // Password change state - const [passwordData, setPasswordData] = useState({ - currentPassword: '', - newPassword: '', - confirmPassword: '', - }); - const [passwordLoading, setPasswordLoading] = useState(false); - const [passwordMessage, setPasswordMessage] = useState(''); - const [passwordError, setPasswordError] = useState(''); - - const handleProfileChange = (e) => { - setProfileData({ ...profileData, [e.target.name]: e.target.value }); - setProfileMessage(''); - setProfileError(''); - }; - - const handlePasswordChange = (e) => { - setPasswordData({ ...passwordData, [e.target.name]: e.target.value }); - setPasswordMessage(''); - setPasswordError(''); - }; - - const handleProfileSubmit = async (e) => { - e.preventDefault(); - setProfileLoading(true); - setProfileMessage(''); - setProfileError(''); - - try { - const response = await authAPI.updateProfile(profileData); - - if (response.success) { - // Update context with new user data - if (response.data.user) { - updateUser(response.data.user); - } - - setProfileMessage(response.message); - - if (response.data.emailChanged) { - setProfileMessage( - 'Profile updated! Please check your new email address to verify it.' - ); - } - } - } catch (error) { - setProfileError(error.data?.error || 'Failed to update profile'); - } finally { - setProfileLoading(false); - } - }; - - const handlePasswordSubmit = async (e) => { - e.preventDefault(); - setPasswordLoading(true); - setPasswordMessage(''); - setPasswordError(''); - - // Validate passwords match - if (passwordData.newPassword !== passwordData.confirmPassword) { - setPasswordError('New passwords do not match'); - setPasswordLoading(false); - return; - } - - try { - const response = await authAPI.changePassword( - passwordData.currentPassword, - passwordData.newPassword - ); - - if (response.success) { - setPasswordMessage(response.message); - // Clear form - setPasswordData({ - currentPassword: '', - newPassword: '', - confirmPassword: '', - }); - } - } catch (error) { - setPasswordError(error.data?.error || 'Failed to change password'); - } finally { - setPasswordLoading(false); - } - }; - return (@{user?.username}
{!user?.emailVerified && (- ⚠️ Email not verified + Email not verified
)}