// profile customization logic async function loadProfile() { try { const res = await fetch(`${API_URL}/profile`, { headers: { 'Authorization': `Bearer ${token}` } }); if (res.ok) { const user = await res.json(); // populate form fields profileAvatarInput.value = ''; profileDescInput.value = user.description || ''; profilePronounsInput.value = user.pronouns || ''; // show preview if avatar exists setAvatarPreview(user.avatar_url); // also update header avatar if present updateHeaderAvatar(user.avatar_url); } } catch (e) { console.error('error loading profile', e); } } function displayProfileModal() { profileModal.style.display = 'flex'; loadProfile(); } async function saveProfile() { const form = new FormData(); const file = profileAvatarInput.files && profileAvatarInput.files[0]; if (file) { form.append('avatar_file', file); } form.append('description', profileDescInput.value.trim()); form.append('pronouns', profilePronounsInput.value.trim()); try { const res = await fetch(`${API_URL}/profile`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}` }, body: form }); if (res.ok) { const updated = await res.json(); updateHeaderAvatar(updated.avatar_url); profileModal.style.display = 'none'; } } catch (e) { console.error('error saving profile', e); } } function updateHeaderAvatar(url) { if (url) { let img = document.querySelector('.header-avatar'); if (!img) { img = document.createElement('img'); img.className = 'header-avatar'; if (currentUserDisplay) { currentUserDisplay.prepend(img); } } img.src = url; img.alt = 'avatar'; img.style.display = 'block'; img.onerror = function() { this.style.display = 'none'; }; } } // profile modal preview function setAvatarPreview(url) { let prev = document.getElementById('avatar-preview'); if (!prev) { prev = document.createElement('img'); prev.id = 'avatar-preview'; prev.style.maxWidth = '100px'; prev.style.maxHeight = '100px'; prev.style.borderRadius = '50%'; prev.style.objectFit = 'cover'; if (profileAvatarInput && profileAvatarInput.parentNode) { profileAvatarInput.parentNode.insertBefore(prev, profileAvatarInput.nextSibling); } } if (url) { prev.src = url; prev.style.display = 'block'; prev.onerror = function() { this.style.display = 'none'; }; } else { prev.style.display = 'none'; } } // View own profile async function viewOwnProfile() { if (!userProfileModal) return; currentViewingUserId = userId; // Set to current user try { const res = await fetch(`${API_URL}/profile`, { headers: { 'Authorization': `Bearer ${token}` } }); if (res.ok) { const user = await res.json(); // Set user info userProfileUsername.textContent = user.username; if (user.avatar_url && user.avatar_url.trim() !== '') { userProfileAvatar.src = user.avatar_url; userProfileAvatar.style.display = 'block'; } else { userProfileAvatar.style.display = 'none'; } if (user.pronouns && user.pronouns.trim() !== '') { userProfilePronouns.textContent = user.pronouns; userProfilePronouns.style.display = 'block'; } else { userProfilePronouns.style.display = 'none'; } if (user.description && user.description.trim() !== '') { userProfileDescription.textContent = user.description; } else { userProfileDescription.textContent = ''; } // Show "Edit Profile" button instead of "Add Friend" userProfileAddFriendBtn.textContent = 'Edit Profile'; userProfileAddFriendBtn.classList.remove('added'); userProfileAddFriendBtn.disabled = false; // Remove old event listeners and add new one const newBtn = userProfileAddFriendBtn.cloneNode(true); userProfileAddFriendBtn.parentNode.replaceChild(newBtn, userProfileAddFriendBtn); userProfileAddFriendBtn = newBtn; // Add click handler for edit profile userProfileAddFriendBtn.addEventListener('click', () => { userProfileModal.style.display = 'none'; displayProfileModal(); }); userProfileModal.style.display = 'flex'; } } catch (error) { console.error('Error loading own profile:', error); } } // User profile preview modal functionality let currentViewingUserId = null; async function showUserProfile(userId) { if (!userProfileModal) return; currentViewingUserId = userId; try { const res = await fetch(`${API_URL}/users/${userId}`, { headers: { 'Authorization': `Bearer ${token}` } }); if (res.ok) { const user = await res.json(); // Set user info userProfileUsername.textContent = user.username; // Handle avatar - check if URL exists and is not empty if (user.avatar_url && user.avatar_url.trim() !== '') { userProfileAvatar.src = user.avatar_url; userProfileAvatar.style.display = 'block'; userProfileAvatar.onerror = function() { // Fallback if image fails to load this.style.display = 'none'; }; } else { // Hide avatar if no URL userProfileAvatar.style.display = 'none'; } // Handle pronouns if (user.pronouns && user.pronouns.trim() !== '') { userProfilePronouns.textContent = user.pronouns; userProfilePronouns.style.display = 'block'; } else { userProfilePronouns.style.display = 'none'; } // Handle description if (user.description && user.description.trim() !== '') { userProfileDescription.textContent = user.description; } else { userProfileDescription.textContent = ''; } // Check if already friends const isFriend = friends.some(f => f.id === user.id); const isSelf = String(user.id) === String(userId); if (isFriend) { userProfileAddFriendBtn.textContent = 'Friends'; userProfileAddFriendBtn.classList.add('added'); userProfileAddFriendBtn.disabled = true; } else if (isSelf) { userProfileAddFriendBtn.textContent = 'Your Profile'; userProfileAddFriendBtn.classList.add('added'); userProfileAddFriendBtn.disabled = true; } else { userProfileAddFriendBtn.textContent = 'Add Friend'; userProfileAddFriendBtn.classList.remove('added'); userProfileAddFriendBtn.disabled = false; } userProfileModal.style.display = 'flex'; } } catch (error) { console.error('Error loading user profile:', error); } } async function addFriendFromProfile() { if (!currentViewingUserId || userProfileAddFriendBtn.disabled) return; // Get username from the display const username = userProfileUsername.textContent; try { const res = await fetch(`${API_URL}/friend-request`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ username: username }) }); if (res.ok) { userProfileAddFriendBtn.textContent = 'Request Sent'; userProfileAddFriendBtn.classList.add('added'); userProfileAddFriendBtn.disabled = true; } else { const data = await res.json(); alert(data.error || 'Error sending friend request'); } } catch (error) { console.error('Error adding friend:', error); } } function initUserProfileListeners() { // Close button if (userProfileCloseBtn) { userProfileCloseBtn.addEventListener('click', () => { if (userProfileModal) userProfileModal.style.display = 'none'; }); } // Close on background click if (userProfileModal) { userProfileModal.addEventListener('click', (e) => { if (e.target === userProfileModal) { userProfileModal.style.display = 'none'; } }); } // Add friend button if (userProfileAddFriendBtn) { userProfileAddFriendBtn.addEventListener('click', addFriendFromProfile); } } // Make message usernames clickable to view profile function initMessageUsernameClickHandlers() { // This will be called after messages are rendered document.addEventListener('click', (e) => { const authorSpan = e.target.closest('.message-author'); if (authorSpan && !authorSpan.classList.contains('own-author')) { const messageEl = authorSpan.closest('.message'); if (messageEl) { const senderId = messageEl.getAttribute('data-sender-id'); if (senderId && String(senderId) !== String(userId)) { showUserProfile(senderId); } } } }); } function initProfileListeners() { // Initialize user profile modal listeners initUserProfileListeners(); initMessageUsernameClickHandlers(); // View own profile button const viewProfileBtn = document.getElementById('view-profile-btn'); if (viewProfileBtn) { try { viewProfileBtn.addEventListener('click', viewOwnProfile); } catch(e) { console.error('viewProfileBtn attach', e); } } else if (profileBtn) { // Fallback to old button try { profileBtn.addEventListener('click', viewOwnProfile); } catch(e) { console.error('profileBtn attach', e); } } if (profileCloseBtn) { try { profileCloseBtn.addEventListener('click', () => { profileModal.style.display = 'none'; }); } catch(e) { console.error('profileCloseBtn attach', e); } } if (profileModal) { try { profileModal.addEventListener('click', (e) => { if (e.target === profileModal) profileModal.style.display = 'none'; }); } catch(e) { console.error('profileModal attach', e); } } if (profileSaveBtn) { try { profileSaveBtn.addEventListener('click', saveProfile); } catch(e) { console.error('profileSaveBtn attach', e); } } // watch file input changes for preview if (profileAvatarInput) { profileAvatarInput.addEventListener('change', () => { const file = profileAvatarInput.files[0]; if (file) { const reader = new FileReader(); reader.onload = e => setAvatarPreview(e.target.result); reader.readAsDataURL(file); } }); } }