// DOM элементы const avatarImage = document.getElementById("avatarImage"); const avatarPlaceholder = document.getElementById("avatarPlaceholder"); const avatarInput = document.getElementById("avatarInput"); const deleteAvatarBtn = document.getElementById("deleteAvatarBtn"); const usernameInput = document.getElementById("username"); const emailInput = document.getElementById("email"); const updateProfileBtn = document.getElementById("updateProfileBtn"); const currentPasswordInput = document.getElementById("currentPassword"); const newPasswordInput = document.getElementById("newPassword"); const confirmPasswordInput = document.getElementById("confirmPassword"); const changePasswordBtn = document.getElementById("changePasswordBtn"); const messageContainer = document.getElementById("messageContainer"); // Функция для показа сообщений function showMessage(message, type = "success") { messageContainer.textContent = message; messageContainer.className = `message-container ${type}`; messageContainer.style.display = "block"; setTimeout(() => { messageContainer.style.display = "none"; }, 5000); } // Загрузка данных профиля async function loadProfile() { try { const response = await fetch("/api/user"); if (!response.ok) { throw new Error("Ошибка загрузки профиля"); } const user = await response.json(); // Заполняем поля usernameInput.value = user.username || ""; emailInput.value = user.email || ""; // Обрабатываем аватарку if (user.avatar) { avatarImage.src = user.avatar; avatarImage.style.display = "block"; avatarPlaceholder.style.display = "none"; deleteAvatarBtn.style.display = "inline-block"; } else { avatarImage.style.display = "none"; avatarPlaceholder.style.display = "inline-flex"; deleteAvatarBtn.style.display = "none"; } } catch (error) { console.error("Ошибка загрузки профиля:", error); showMessage("Ошибка загрузки данных профиля", "error"); } } // Обработчик загрузки аватарки avatarInput.addEventListener("change", async function (event) { const file = event.target.files[0]; if (!file) return; // Проверка размера файла (5MB) if (file.size > 5 * 1024 * 1024) { showMessage("Файл слишком большой. Максимальный размер: 5 МБ", "error"); return; } // Проверка типа файла const allowedTypes = ["image/jpeg", "image/jpg", "image/png", "image/gif"]; if (!allowedTypes.includes(file.type)) { showMessage( "Недопустимый формат файла. Используйте JPG, PNG или GIF", "error" ); return; } try { const formData = new FormData(); formData.append("avatar", file); const response = await fetch("/api/user/avatar", { method: "POST", body: formData, }); if (!response.ok) { const error = await response.json(); throw new Error(error.error || "Ошибка загрузки аватарки"); } const result = await response.json(); // Обновляем отображение аватарки avatarImage.src = result.avatar + "?t=" + Date.now(); // Добавляем timestamp для обновления кэша avatarImage.style.display = "block"; avatarPlaceholder.style.display = "none"; deleteAvatarBtn.style.display = "inline-block"; showMessage("Аватарка успешно загружена", "success"); } catch (error) { console.error("Ошибка загрузки аватарки:", error); showMessage(error.message, "error"); } // Сбрасываем input для возможности повторной загрузки того же файла event.target.value = ""; }); // Обработчик удаления аватарки deleteAvatarBtn.addEventListener("click", async function () { if (!confirm("Вы уверены, что хотите удалить аватарку?")) { return; } try { const response = await fetch("/api/user/avatar", { method: "DELETE", }); if (!response.ok) { const error = await response.json(); throw new Error(error.error || "Ошибка удаления аватарки"); } // Обновляем отображение avatarImage.style.display = "none"; avatarPlaceholder.style.display = "inline-flex"; deleteAvatarBtn.style.display = "none"; showMessage("Аватарка успешно удалена", "success"); } catch (error) { console.error("Ошибка удаления аватарки:", error); showMessage(error.message, "error"); } }); // Обработчик обновления профиля updateProfileBtn.addEventListener("click", async function () { const username = usernameInput.value.trim(); const email = emailInput.value.trim(); // Валидация if (!username) { showMessage("Логин не может быть пустым", "error"); return; } if (username.length < 3) { showMessage("Логин должен быть не менее 3 символов", "error"); return; } if (email && !isValidEmail(email)) { showMessage("Некорректный email адрес", "error"); return; } try { const response = await fetch("/api/user/profile", { method: "PUT", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ username, email: email || null, }), }); if (!response.ok) { const error = await response.json(); throw new Error(error.error || "Ошибка обновления профиля"); } const result = await response.json(); showMessage(result.message || "Профиль успешно обновлен", "success"); } catch (error) { console.error("Ошибка обновления профиля:", error); showMessage(error.message, "error"); } }); // Обработчик изменения пароля changePasswordBtn.addEventListener("click", async function () { const currentPassword = currentPasswordInput.value; const newPassword = newPasswordInput.value; const confirmPassword = confirmPasswordInput.value; // Валидация if (!currentPassword) { showMessage("Введите текущий пароль", "error"); return; } if (!newPassword) { showMessage("Введите новый пароль", "error"); return; } if (newPassword.length < 6) { showMessage("Новый пароль должен быть не менее 6 символов", "error"); return; } if (newPassword !== confirmPassword) { showMessage("Новый пароль и подтверждение не совпадают", "error"); return; } try { const response = await fetch("/api/user/profile", { method: "PUT", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ currentPassword, newPassword, }), }); if (!response.ok) { const error = await response.json(); throw new Error(error.error || "Ошибка изменения пароля"); } const result = await response.json(); // Очищаем поля паролей currentPasswordInput.value = ""; newPasswordInput.value = ""; confirmPasswordInput.value = ""; showMessage(result.message || "Пароль успешно изменен", "success"); } catch (error) { console.error("Ошибка изменения пароля:", error); showMessage(error.message, "error"); } }); // Функция валидации email function isValidEmail(email) { const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return re.test(email); } // Функция для проверки аутентификации async function checkAuthentication() { const isAuthenticated = localStorage.getItem('isAuthenticated'); if (isAuthenticated !== 'true') { // Если пользователь не аутентифицирован, перенаправляем на страницу входа window.location.href = "/"; return; } // Проверяем, что сессия на сервере еще действительна try { const response = await fetch("/api/auth/status"); if (!response.ok) { // Если сессия недействительна, очищаем localStorage и перенаправляем localStorage.removeItem('isAuthenticated'); localStorage.removeItem('username'); window.location.href = "/"; return; } const authData = await response.json(); if (!authData.authenticated) { // Если сервер говорит, что пользователь не аутентифицирован localStorage.removeItem('isAuthenticated'); localStorage.removeItem('username'); window.location.href = "/"; return; } } catch (error) { console.error("Ошибка проверки аутентификации:", error); // В случае ошибки сети, оставляем пользователя на странице // но показываем предупреждение console.warn("Не удалось проверить статус аутентификации"); } } // Функция для настройки обработчика выхода function setupLogoutHandler() { const logoutForms = document.querySelectorAll('form[action="/logout"]'); logoutForms.forEach(form => { form.addEventListener('submit', function(e) { // Очищаем localStorage перед выходом localStorage.removeItem('isAuthenticated'); localStorage.removeItem('username'); }); }); } // Загружаем профиль при загрузке страницы document.addEventListener("DOMContentLoaded", function () { // Проверяем аутентификацию при загрузке страницы checkAuthentication(); loadProfile(); // Добавляем обработчик для кнопки выхода setupLogoutHandler(); });