import { useState, useEffect, useRef } from 'react'; import { useRouter } from 'next/router'; import Layout from '../components/Layout'; export default function Profile() { const router = useRouter(); const fileInputRef = useRef(null); // User state const [user, setUser] = useState(null); // UI state const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [editMode, setEditMode] = useState(false); const [message, setMessage] = useState({ type: '', text: '' }); const [stats, setStats] = useState({ totalCards: 0, totalCollections: 0, totalDecks: 0, totalValue: 0 }); // Form state const [formData, setFormData] = useState({ first_name: '', last_name: '', username: '', bio: '', favorite_games: [] }); useEffect(() => { loadUserProfile(); loadUserStats(); }, []); const loadUserProfile = async () => { try { const token = localStorage.getItem('auth_token'); if (!token) { router.push('/login'); return; } const response = await fetch('/api/user/profile', { headers: { 'Authorization': `Bearer ${token}` } }); if (response.ok) { const userData = await response.json(); setUser(userData); setFormData({ first_name: userData.first_name || '', last_name: userData.last_name || '', username: userData.username || '', bio: userData.bio || '', favorite_games: userData.favorite_games || [] }); } else if (response.status === 401) { router.push('/login'); } } catch (error) { console.error('Error loading profile:', error); setMessage({ type: 'error', text: 'Failed to load profile' }); } finally { setLoading(false); } }; const loadUserStats = async () => { try { const token = localStorage.getItem('auth_token'); if (!token) return; const response = await fetch('/api/user/stats', { headers: { 'Authorization': `Bearer ${token}` } }); if (response.ok) { const statsData = await response.json(); setStats(statsData); } } catch (error) { console.error('Error loading stats:', error); } }; const handleInputChange = (field, value) => { setFormData(prev => ({ ...prev, [field]: value })); }; const handleGameToggle = (game) => { setFormData(prev => ({ ...prev, favorite_games: prev.favorite_games.includes(game) ? prev.favorite_games.filter(g => g !== game) : [...prev.favorite_games, game] })); }; const handleSave = async () => { setSaving(true); setMessage({ type: '', text: '' }); try { const token = localStorage.getItem('auth_token'); const response = await fetch('/api/user/profile', { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify(formData) }); if (response.ok) { const updatedUser = await response.json(); setUser(updatedUser); setEditMode(false); setMessage({ type: 'success', text: 'Profile updated successfully!' }); } else { const error = await response.json(); setMessage({ type: 'error', text: error.message || 'Failed to update profile' }); } } catch (error) { console.error('Error updating profile:', error); setMessage({ type: 'error', text: 'Failed to update profile' }); } finally { setSaving(false); } }; const handleAvatarUpload = async (event) => { const file = event.target.files[0]; if (!file) return; // Validate file type and size if (!file.type.startsWith('image/')) { setMessage({ type: 'error', text: 'Please select an image file' }); return; } if (file.size > 5 * 1024 * 1024) { // 5MB limit setMessage({ type: 'error', text: 'Image must be less than 5MB' }); return; } const formData = new FormData(); formData.append('avatar', file); try { setSaving(true); const token = localStorage.getItem('auth_token'); const response = await fetch('/api/user/avatar', { method: 'POST', headers: { 'Authorization': `Bearer ${token}` }, body: formData }); if (response.ok) { const result = await response.json(); setUser(prev => ({ ...prev, avatar_url: result.avatar_url })); setMessage({ type: 'success', text: 'Avatar updated successfully!' }); } else { const error = await response.json(); setMessage({ type: 'error', text: error.message || 'Failed to upload avatar' }); } } catch (error) { console.error('Error uploading avatar:', error); setMessage({ type: 'error', text: 'Failed to upload avatar' }); } finally { setSaving(false); } }; const generateAvatar = async () => { try { setSaving(true); const token = localStorage.getItem('auth_token'); const response = await fetch('/api/user/avatar/generate', { method: 'POST', headers: { 'Authorization': `Bearer ${token}` } }); if (response.ok) { const result = await response.json(); setUser(prev => ({ ...prev, avatar_url: result.avatar_url })); setMessage({ type: 'success', text: 'Avatar generated successfully!' }); } else { const error = await response.json(); setMessage({ type: 'error', text: error.message || 'Failed to generate avatar' }); } } catch (error) { console.error('Error generating avatar:', error); setMessage({ type: 'error', text: 'Failed to generate avatar' }); } finally { setSaving(false); } }; const formatCurrency = (amount) => { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(amount); }; const formatDate = (dateString) => { return new Date(dateString).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }); }; const getDisplayName = () => { if (!user) return ''; if (user.first_name || user.last_name) { return `${user.first_name} ${user.last_name}`.trim(); } return user.username || user.email; }; const getInitials = () => { if (!user) return ''; if (user.first_name || user.last_name) { return `${user.first_name?.charAt(0) || ''}${user.last_name?.charAt(0) || ''}`.toUpperCase(); } return user.email?.charAt(0).toUpperCase() || 'U'; }; const gameOptions = [ { value: 'MTG', label: 'Magic: The Gathering', color: 'purple', icon: '🔮' }, { value: 'Pokemon', label: 'Pokemon', color: 'blue', icon: '⚡' }, { value: 'Lorcana', label: 'Disney Lorcana', color: 'pink', icon: '✨' } ]; if (loading) { return (
); } return (
{/* Header */}

Profile

Manage your account information and preferences

{/* Message */} {message.text && (
{message.text}
)}
{/* Profile Card */}
{/* Avatar */}
{user?.avatar_url ? ( Profile ) : (
{getInitials()}
)} {/* Avatar Upload Button */}
{/* Generate Avatar Button */}
{/* Basic Info */}

{getDisplayName()}

{user?.username && (

@{user.username}

)}

{user?.email}

{user?.role?.toUpperCase()}
{/* Bio */} {user?.bio && (

{user.bio}

)} {/* Member Since */} {user?.created_at && (

Member since {formatDate(user.created_at)}

)}
{/* Stats Card */}

Collection Stats

Total Cards {stats.totalCards.toLocaleString()}
Collections {stats.totalCollections}
Decks {stats.totalDecks}
Total Value {formatCurrency(stats.totalValue)}
{/* Profile Form */}

Profile Information

{/* Name Fields */}
{editMode ? ( handleInputChange('first_name', e.target.value)} className="input-field w-full" placeholder="Enter your first name" /> ) : (

{user?.first_name || 'Not set'}

)}
{editMode ? ( handleInputChange('last_name', e.target.value)} className="input-field w-full" placeholder="Enter your last name" /> ) : (

{user?.last_name || 'Not set'}

)}
{/* Username */}
{editMode ? ( handleInputChange('username', e.target.value)} className="input-field w-full" placeholder="Choose a unique username" /> ) : (

{user?.username || 'Not set'}

)}
{/* Bio */}
{editMode ? (