360 lines
12 KiB
JavaScript
360 lines
12 KiB
JavaScript
// 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);
|
|
}
|
|
});
|
|
}
|
|
} |