diff --git a/index.html b/index.html index 47ede14532..44d7f80cc0 100644 --- a/index.html +++ b/index.html @@ -8,46 +8,7 @@
-

Загрузка комментариев...

- - - - - - - - - - - - +
diff --git a/js/api.js b/js/api.js index 308601ed9e..0323c4b6e2 100644 --- a/js/api.js +++ b/js/api.js @@ -1,23 +1,61 @@ +import { logout } from "./auth.js"; + + const PERSONAL_KEY = "polina-rebrova"; const API_URL = `https://wedev-api.sky.pro/api/v2/${PERSONAL_KEY}/comments`; -const AUTH_URL = "https://wedev-api.sky.pro/api/v2//user"; +const USER_API_URL = "https://wedev-api.sky.pro/api/user"; + + +async function handleUnauthorized(response) { + if (response.status === 401) { + logout(); + alert("Сессия истекла. Пожалуйста, войдите снова."); + window.location.reload(); + throw new Error("Неавторизован"); + } + return response; +} + +async function checkResponse(response) { + const contentType = response.headers.get("content-type"); + + + if (contentType && contentType.includes("text/html")) { + console.error("Сервер вернул HTML вместо JSON. URL:", response.url); + throw new Error(`Ошибка сервера: ${response.status} ${response.statusText}`); + } + + return response; +} export async function fetchComments() { try { + console.log("Запрос к API:", API_URL); + const response = await fetch(API_URL); - if (!response.ok) throw new Error("Ошибка загрузки комментариев"); - + await checkResponse(response); + await handleUnauthorized(response); + + if (!response.ok) throw new Error(`Ошибка загрузки комментариев: ${response.status}`); + const data = await response.json(); + + if (!data.comments || !Array.isArray(data.comments)) { + throw new Error("Неверный формат ответа от сервера"); + } + return data.comments.map((comment) => ({ + id: comment.id, author: comment.author.name, + authorLogin: comment.author.login, text: comment.text, - date: new Date(comment.date).toLocaleString("ru-RU"), + date: comment.date, likes: comment.likes, - isLiked: comment.isLiked, + isLiked: comment.isLiked || false, })); } catch (error) { - alert("Ошибка загрузки комментариев"); - return []; + console.error("Ошибка загрузки комментариев:", error); + throw error; } } @@ -30,31 +68,88 @@ export async function postComment(text) { method: "POST", headers: { Authorization: `Bearer ${token}`, - "Content-Type": "application/json", }, body: JSON.stringify({ text }), }); + await checkResponse(response); + await handleUnauthorized(response); + + if (response.status === 400) { + const error = await response.json(); + throw new Error(error.error || "Ошибка валидации"); + } + if (!response.ok) throw new Error("Ошибка добавления комментария"); - return await fetchComments(); + + return await response.json(); + } catch (error) { + console.error("Ошибка добавления комментария:", error); + throw error; + } +} + +export async function toggleLike(commentId) { + const token = localStorage.getItem("token"); + if (!token) throw new Error("Нет авторизации"); + + try { + const response = await fetch(`${API_URL}/${commentId}/toggle-like`, { + method: "POST", + headers: { + Authorization: `Bearer ${token}`, + }, + }); + + await checkResponse(response); + await handleUnauthorized(response); + + if (!response.ok) throw new Error("Ошибка переключения лайка"); + + const data = await response.json(); + return data.result; } catch (error) { - alert("Ошибка добавления комментария"); - return []; + console.error("Ошибка лайка:", error); + throw error; } } export async function login(login, password) { - return fetch(AUTH_URL + "/login", { + const response = await fetch(`${USER_API_URL}/login`, { method: "POST", - headers: { "Content-Type": "application/json" }, body: JSON.stringify({ login, password }), }); + + await checkResponse(response); + + if (response.status === 400) { + const error = await response.json(); + throw new Error(error.error || "Неправильный логин или пароль"); + } + + if (!response.ok) { + throw new Error("Ошибка авторизации"); + } + + return response.json(); } export async function registration(name, login, password) { - return fetch(AUTH_URL, { + const response = await fetch(USER_API_URL, { method: "POST", - headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name, login, password }), }); + + await checkResponse(response); + + if (response.status === 400) { + const error = await response.json(); + throw new Error(error.error || "Пользователь с таким логином уже существует"); + } + + if (!response.ok) { + throw new Error("Ошибка регистрации"); + } + + return response.json(); } \ No newline at end of file diff --git a/js/auth.js b/js/auth.js index ee0fca89ea..4ecfe522d6 100644 --- a/js/auth.js +++ b/js/auth.js @@ -1,21 +1,39 @@ let currentUser = null; +export function setCurrentUser(user) { + currentUser = user; + if (user && user.token) { + localStorage.setItem("token", user.token); + localStorage.setItem("userName", user.name); + localStorage.setItem("userLogin", user.login); + } else { + localStorage.removeItem("token"); + localStorage.removeItem("userName"); + localStorage.removeItem("userLogin"); + } +} + export function getCurrentUser() { - if (!currentUser) { - const savedUser = localStorage.getItem("user"); - if (savedUser) { - currentUser = JSON.parse(savedUser); - } + if (currentUser) return currentUser; + + const token = localStorage.getItem("token"); + const name = localStorage.getItem("userName"); + const login = localStorage.getItem("userLogin"); + + if (token && name) { + currentUser = { token, name, login }; + return currentUser; } - return currentUser; + return null; } export function checkAuth() { - return localStorage.getItem("token") !== null; + return !!getCurrentUser(); } export function logout() { - localStorage.removeItem("token"); - localStorage.removeItem("user"); currentUser = null; + localStorage.removeItem("token"); + localStorage.removeItem("userName"); + localStorage.removeItem("userLogin"); } \ No newline at end of file diff --git a/js/comments.js b/js/comments.js index feaceee0f7..ab52764af1 100644 --- a/js/comments.js +++ b/js/comments.js @@ -1,4 +1,4 @@ -import { fetchComments, postComment } from "./api.js"; +import { fetchComments, postComment, toggleLike } from "./api.js"; import { renderComments } from "./render.js"; import { getCurrentUser } from "./auth.js"; @@ -6,16 +6,16 @@ export let comments = []; export async function loadComments() { const loadingMessage = document.getElementById("loading-message"); - loadingMessage.style.display = "block"; + if (loadingMessage) loadingMessage.style.display = "block"; try { comments = await fetchComments(); renderComments(); } catch (error) { console.error("Ошибка при загрузке комментариев:", error); - loadingMessage.textContent = "Ошибка загрузки комментариев"; + if (loadingMessage) loadingMessage.textContent = "Ошибка загрузки комментариев"; } finally { - loadingMessage.style.display = "none"; + if (loadingMessage) loadingMessage.style.display = "none"; } } @@ -23,36 +23,53 @@ export async function addComment(text) { const user = getCurrentUser(); if (!user) { alert("Сначала авторизуйтесь!"); - return; + return false; } if (text.length < 3) { alert("Комментарий должен быть не короче 3 символов"); - return; + return false; } const addForm = document.getElementById("add-form"); const commentLoadingMessage = document.getElementById("comment-loading-message"); const addButton = document.getElementById("add-comment-button"); + const commentInput = document.getElementById("comment-input"); - addForm.style.display = "none"; - commentLoadingMessage.style.display = "block"; - addButton.disabled = true; + if (addForm) addForm.style.display = "none"; + if (commentLoadingMessage) commentLoadingMessage.style.display = "block"; + if (addButton) addButton.disabled = true; try { await postComment(text); await loadComments(); + if (commentInput) commentInput.value = ""; + return true; + } catch (error) { + alert(error.message || "Ошибка добавления комментария"); + return false; } finally { - addForm.style.display = "block"; - commentLoadingMessage.style.display = "none"; - addButton.disabled = false; + if (addForm) addForm.style.display = "block"; + if (commentLoadingMessage) commentLoadingMessage.style.display = "none"; + if (addButton) addButton.disabled = false; } } -export function toggleLike(index) { - if (!comments[index]) return; +export async function handleToggleLike(commentId, index) { + const user = getCurrentUser(); + if (!user) { + alert("Авторизуйтесь, чтобы ставить лайки!"); + return; + } - comments[index].isLiked = !comments[index].isLiked; - comments[index].likes += comments[index].isLiked ? 1 : -1; - renderComments(); -} + try { + const result = await toggleLike(commentId); + if (result) { + comments[index].likes = result.likes; + comments[index].isLiked = result.isLiked; + renderComments(); + } + } catch (error) { + alert("Ошибка при установке лайка"); + } +} \ No newline at end of file diff --git a/js/eventHandlers.js b/js/eventHandlers.js index 20a0829f2a..863aca5bc0 100644 --- a/js/eventHandlers.js +++ b/js/eventHandlers.js @@ -1,45 +1,43 @@ import { addComment, toggleLike } from "./comments.js"; import { renderComments } from "./render.js"; -export function addEventListeners() { +export function initEventHandlers() { + initAddCommentHandler(); +} + + +export function initAddCommentHandler() { const addButton = document.getElementById("add-comment-button"); const commentInput = document.getElementById("comment-input"); if (!addButton || !commentInput) { - console.error("Ошибка: один из элементов формы не найден!"); + console.error("Ошибка: элементы формы не найдены!"); return; } - addButton.addEventListener("click", () => { - if (commentInput.value.trim()) { - addComment(commentInput.value.trim()); + + const newAddButton = addButton.cloneNode(true); + addButton.parentNode.replaceChild(newAddButton, addButton); + + newAddButton.addEventListener("click", async () => { + const text = commentInput.value.trim(); + if (text) { + await addComment(text); commentInput.value = ""; - renderComments(); + + } else { + alert("Введите текст комментария"); } }); } -export function addLikeEventListeners() { - document.querySelectorAll(".like-button").forEach((button) => { - button.addEventListener("click", (event) => { - event.stopPropagation(); - const commentIndex = event.target.dataset.index; - toggleLike(commentIndex); - renderComments(); - }); - }); + +export function initLikeHandlers() { + + console.log("Like handlers are now in render.js"); } -export function addReplyListeners() { - document.querySelectorAll(".comment").forEach((comment) => { - comment.addEventListener("click", (event) => { - if (event.target.classList.contains("like-button")) return; - const index = event.currentTarget.dataset.index; - const textInput = document.getElementById("comment-input"); - - if (comments[index]) { - textInput.value = `> ${comments[index].text}\n`; - } - }); - }); +export function initReplyHandlers() { + + console.log("Reply handlers are now in render.js"); } \ No newline at end of file diff --git a/js/main.js b/js/main.js index 97079e2432..dcaabb3064 100644 --- a/js/main.js +++ b/js/main.js @@ -1,64 +1,111 @@ +import { loadComments } from "./comments.js"; import { renderComments } from "./render.js"; -import { loadComments, comments } from "./comments.js"; -import { checkAuth } from "./auth.js"; -import { showLoginForm, showRegisterForm } from "./render.js"; +import { checkAuth, getCurrentUser } from "./auth.js"; +import { renderLoginForm } from "./renderLogin.js"; +import { renderAddForm } from "./renderAddForm.js"; -document.addEventListener("DOMContentLoaded", async () => { - const authMessage = document.getElementById("auth-message"); - const authLink = document.getElementById("auth-link"); - const commentsContainer = document.getElementById("comments-container"); - const addForm = document.getElementById("add-form"); - const loginContainer = document.getElementById("login-container"); - const registerContainer = document.getElementById("register-container"); +let container = null; +let loadingMessage = null; - await loadComments(); - renderComments(); - - if (checkAuth()) { - showCommentsUI(); - } else { - showAuthMessage(); +function initContainer() { + container = document.querySelector(".container"); + if (!container) { + console.error("Container not found"); + return false; } + return true; +} - function showCommentsUI() { - if (!authMessage || !commentsContainer || !addForm || !loginContainer || !registerContainer) { - console.error("Ошибка: один из элементов не найден!"); - return; - } - authMessage.style.display = "none"; - loginContainer.style.display = "none"; - registerContainer.style.display = "none"; - commentsContainer.style.display = "block"; - addForm.style.display = "block"; - } +function showLoading() { + loadingMessage = document.createElement("p"); + loadingMessage.id = "loading-message"; + loadingMessage.textContent = "Загрузка комментариев..."; + container.appendChild(loadingMessage); +} - function showAuthMessage() { - if (!authMessage || !commentsContainer || !addForm || !loginContainer || !registerContainer) { - console.error("Ошибка: один из элементов не найден!"); - return; - } - authMessage.style.display = "block"; - commentsContainer.style.display = "block"; - addForm.style.display = "none"; - loginContainer.style.display = "none"; - registerContainer.style.display = "none"; +function hideLoading() { + if (loadingMessage && loadingMessage.parentNode) { + loadingMessage.remove(); } +} - if (authLink) { - authLink.addEventListener("click", (event) => { - event.preventDefault(); - showLoginForm(); - }); - } else { - console.error("Ошибка: auth-link не найден!"); +function clearContainer() { + while (container.firstChild) { + container.removeChild(container.firstChild); } -}); +} + +export function showCommentsUI() { + if (!container) return; + + clearContainer(); + + const commentsList = document.createElement("ul"); + commentsList.id = "comments-list"; + commentsList.className = "comments"; + container.appendChild(commentsList); + + + renderComments(); + + + renderAddForm(); +} + +function showAuthMessage() { + if (!container) return; + + clearContainer(); + + + const commentsList = document.createElement("ul"); + commentsList.id = "comments-list"; + commentsList.className = "comments"; + container.appendChild(commentsList); + + + renderComments(); + + + const authMessage = document.createElement("p"); + authMessage.id = "auth-message"; + authMessage.style.display = "block"; + authMessage.style.marginTop = "20px"; + authMessage.style.textAlign = "center"; + + const authLink = document.createElement("a"); + authLink.href = "#"; + authLink.id = "auth-link"; + authLink.className = "link-login"; + authLink.textContent = "авторизуйтесь"; + + authMessage.appendChild(document.createTextNode("Чтобы добавить комментарий, ")); + authMessage.appendChild(authLink); + + container.appendChild(authMessage); + + authLink.addEventListener("click", (event) => { event.preventDefault(); - showLoginForm(); + renderLoginForm(); }); +} - registerLink.addEventListener("click", (event) => { - event.preventDefault(); - showRegisterForm(); - }); +export async function init() { + if (!initContainer()) return; + + showLoading(); + + await loadComments(); + + hideLoading(); + + if (checkAuth()) { + showCommentsUI(); + } else { + showAuthMessage(); + } +} + + +document.addEventListener("DOMContentLoaded", init); \ No newline at end of file diff --git a/js/render.js b/js/render.js index 2eee4efb5c..7565ba466e 100644 --- a/js/render.js +++ b/js/render.js @@ -1,83 +1,104 @@ -import { comments } from "./comments.js"; -import { addLikeEventListeners, addReplyListeners } from "./eventHandlers.js"; -import { getCurrentUser } from "./auth.js"; - -export function renderComments() { - const commentsList = document.getElementById("comments-list"); - - if (!commentsList) { - console.error("Ошибка: элемент #comments-list не найден!"); - return; - } - - commentsList.innerHTML = comments - .map((comment, index) => ` -
  • -
    -
    ${comment.author}
    -
    ${comment.date}
    -
    -
    -
    ${comment.text}
    -
    - -
  • - `) - .join(""); - - addLikeEventListeners(); - addReplyListeners(); - renderCommentForm(); -} - -export function renderCommentForm() { - const container = document.querySelector(".container"); - const user = getCurrentUser(); - const formContainer = document.getElementById("comment-form-container"); - - if (formContainer) { - formContainer.remove(); - } - - const formHtml = user - ? ` -
    - - -
    - -
    -
    - - ` - : `

    Чтобы добавить комментарий, авторизуйтесь

    `; - - container.insertAdjacentHTML("beforeend", formHtml); - - if (!user) { - document.getElementById("login-link").addEventListener("click", (event) => { - event.preventDefault(); - showLoginForm(); - }); - } -} - - -export function showLoginForm() { - document.getElementById("auth-message").style.display = "none"; - document.getElementById("comments-container").style.display = "none"; - document.getElementById("login-container").style.display = "block"; - document.getElementById("register-container").style.display = "none"; -} - -export function showRegisterForm() { - document.getElementById("auth-message").style.display = "none"; - document.getElementById("comments-container").style.display = "none"; - document.getElementById("login-container").style.display = "none"; - document.getElementById("register-container").style.display = "block"; +import { comments, handleToggleLike } from "./comments.js"; +import { sanitize, formatDate } from "./utils.js"; + +export function renderComments() { + const commentsList = document.getElementById("comments-list"); + if (!commentsList) { + console.error("comments-list не найден"); + return; + } + + + while (commentsList.firstChild) { + commentsList.removeChild(commentsList.firstChild); + } + + if (comments.length === 0) { + const emptyMessage = document.createElement("li"); + emptyMessage.className = "comment"; + emptyMessage.textContent = "Комментариев пока нет"; + commentsList.appendChild(emptyMessage); + return; + } + + + comments.forEach((comment, index) => { + const commentItem = createCommentElement(comment, index); + commentsList.appendChild(commentItem); + }); +} + +export function createCommentElement(comment, index) { + const li = document.createElement("li"); + li.className = "comment"; + li.dataset.index = index; + + + const header = document.createElement("div"); + header.className = "comment-header"; + + const author = document.createElement("div"); + author.className = "comment-author"; + author.textContent = sanitize(comment.author); + + const date = document.createElement("div"); + date.className = "comment-date"; + date.textContent = formatDate(comment.date); + + header.appendChild(author); + header.appendChild(date); + + + const body = document.createElement("div"); + body.className = "comment-body"; + + const text = document.createElement("div"); + text.className = "comment-text"; + text.textContent = sanitize(comment.text); + + body.appendChild(text); + + + const footer = document.createElement("div"); + footer.className = "comment-footer"; + + const likesContainer = document.createElement("div"); + likesContainer.className = "likes"; + + const likesCounter = document.createElement("span"); + likesCounter.className = "likes-counter"; + likesCounter.textContent = comment.likes; + + const likeButton = document.createElement("button"); + likeButton.className = `like-button ${comment.isLiked ? "liked" : ""}`; + likeButton.dataset.id = comment.id; + likeButton.dataset.index = index; + + + likeButton.addEventListener("click", async (event) => { + event.stopPropagation(); + await handleToggleLike(comment.id, index); + }); + + likesContainer.appendChild(likesCounter); + likesContainer.appendChild(likeButton); + footer.appendChild(likesContainer); + + + li.addEventListener("click", (event) => { + + if (event.target.classList.contains("like-button")) return; + + const commentInput = document.getElementById("comment-input"); + if (commentInput) { + commentInput.value = `> ${comment.text}\n\n`; + commentInput.focus(); + } + }); + + li.appendChild(header); + li.appendChild(body); + li.appendChild(footer); + + return li; } \ No newline at end of file diff --git a/js/renderAddForm.js b/js/renderAddForm.js new file mode 100644 index 0000000000..b511b79e9d --- /dev/null +++ b/js/renderAddForm.js @@ -0,0 +1,65 @@ +import { addComment } from "./comments.js"; +import { getCurrentUser } from "./auth.js"; + +export function renderAddForm() { + const container = document.querySelector(".container"); + if (!container) return; + + const user = getCurrentUser(); + if (!user) return; + + + if (document.getElementById("add-form")) return; + + const addForm = document.createElement("div"); + addForm.id = "add-form"; + addForm.className = "add-form"; + + + const nameInput = document.createElement("input"); + nameInput.type = "text"; + nameInput.id = "name-input"; + nameInput.className = "add-form-name"; + nameInput.value = user.name; + nameInput.readOnly = true; + addForm.appendChild(nameInput); + + + const textarea = document.createElement("textarea"); + textarea.id = "comment-input"; + textarea.className = "add-form-text"; + textarea.placeholder = "Введите ваш комментарий"; + textarea.rows = 4; + addForm.appendChild(textarea); + + + const buttonRow = document.createElement("div"); + buttonRow.className = "add-form-row"; + + const addButton = document.createElement("button"); + addButton.id = "add-comment-button"; + addButton.className = "add-form-button"; + addButton.textContent = "Написать"; + + addButton.addEventListener("click", async () => { + const text = textarea.value.trim(); + if (text) { + await addComment(text); + textarea.value = ""; + } else { + alert("Введите текст комментария"); + } + }); + + buttonRow.appendChild(addButton); + addForm.appendChild(buttonRow); + + + const loadingMessage = document.createElement("p"); + loadingMessage.id = "comment-loading-message"; + loadingMessage.style.display = "none"; + loadingMessage.textContent = "Комментарий добавляется..."; + + container.appendChild(addForm); + container.appendChild(loadingMessage); +} \ No newline at end of file diff --git a/js/renderLogin.js b/js/renderLogin.js new file mode 100644 index 0000000000..f9bf78bdc2 --- /dev/null +++ b/js/renderLogin.js @@ -0,0 +1,108 @@ +import { login } from "./api.js"; +import { setCurrentUser } from "./auth.js"; +import { showRegisterForm } from "./renderRegister.js"; +import { init } from "./main.js"; + +let container = null; + +function clearContainer() { + const container = document.querySelector(".container"); + if (!container) return; + while (container.firstChild) { + container.removeChild(container.firstChild); + } +} + +export function renderLoginForm() { + container = document.querySelector(".container"); + if (!container) return; + + clearContainer(); + + + const loginContainer = document.createElement("div"); + loginContainer.id = "login-container"; + loginContainer.className = "auth-container"; + + + const title = document.createElement("h2"); + title.className = "auth-title"; + title.textContent = "Авторизация"; + loginContainer.appendChild(title); + + + const loginInput = document.createElement("input"); + loginInput.type = "text"; + loginInput.id = "login-input"; + loginInput.className = "auth-input"; + loginInput.placeholder = "Введите логин"; + loginContainer.appendChild(loginInput); + + + const passwordInput = document.createElement("input"); + passwordInput.type = "password"; + passwordInput.id = "password-input"; + passwordInput.className = "auth-input"; + passwordInput.placeholder = "Введите пароль"; + loginContainer.appendChild(passwordInput); + + + const buttonsDiv = document.createElement("div"); + buttonsDiv.className = "auth-buttons"; + + const loginButton = document.createElement("button"); + loginButton.id = "login-button"; + loginButton.className = "auth-button"; + loginButton.textContent = "Войти"; + + const registerLink = document.createElement("button"); + registerLink.id = "register-link"; + registerLink.className = "auth-button"; + registerLink.textContent = "Регистрация"; + + buttonsDiv.appendChild(loginButton); + buttonsDiv.appendChild(registerLink); + loginContainer.appendChild(buttonsDiv); + + + const errorElement = document.createElement("p"); + errorElement.id = "login-error"; + errorElement.className = "error-message"; + loginContainer.appendChild(errorElement); + + container.appendChild(loginContainer); + + const handleLogin = async () => { + const loginValue = loginInput.value.trim(); + const passwordValue = passwordInput.value; + + if (!loginValue || !passwordValue) { + errorElement.textContent = "Заполните все поля"; + return; + } + + try { + const userData = await login(loginValue, passwordValue); + if (userData && userData.user) { + setCurrentUser(userData.user); + await init(); + } + } catch (error) { + errorElement.textContent = error.message; + } + }; + + loginButton.addEventListener("click", handleLogin); + registerLink.addEventListener("click", (e) => { + e.preventDefault(); + showRegisterForm(); + }); + + loginInput.addEventListener("keypress", (e) => { + if (e.key === "Enter") handleLogin(); + }); + + passwordInput.addEventListener("keypress", (e) => { + if (e.key === "Enter") handleLogin(); + }); +} \ No newline at end of file diff --git a/js/renderRegister.js b/js/renderRegister.js new file mode 100644 index 0000000000..f65cf3bb33 --- /dev/null +++ b/js/renderRegister.js @@ -0,0 +1,115 @@ +import { registration } from "./api.js"; +import { setCurrentUser } from "./auth.js"; +import { renderLoginForm } from "./renderLogin.js"; +import { init } from "./main.js"; + +function clearContainer() { + const container = document.querySelector(".container"); + if (!container) return; + while (container.firstChild) { + container.removeChild(container.firstChild); + } +} + +export function showRegisterForm() { + const container = document.querySelector(".container"); + if (!container) return; + + clearContainer(); + + + const registerContainer = document.createElement("div"); + registerContainer.id = "register-container"; + registerContainer.className = "auth-container"; + + const title = document.createElement("h2"); + title.className = "auth-title"; + title.textContent = "Регистрация"; + registerContainer.appendChild(title); + + + const nameInput = document.createElement("input"); + nameInput.type = "text"; + nameInput.id = "register-name"; + nameInput.className = "auth-input"; + nameInput.placeholder = "Введите имя"; + registerContainer.appendChild(nameInput); + + + const loginInput = document.createElement("input"); + loginInput.type = "text"; + loginInput.id = "register-login"; + loginInput.className = "auth-input"; + loginInput.placeholder = "Введите логин"; + registerContainer.appendChild(loginInput); + + + const passwordInput = document.createElement("input"); + passwordInput.type = "password"; + passwordInput.id = "register-password"; + passwordInput.className = "auth-input"; + passwordInput.placeholder = "Введите пароль"; + registerContainer.appendChild(passwordInput); + + + const buttonsDiv = document.createElement("div"); + buttonsDiv.className = "auth-buttons"; + + const registerButton = document.createElement("button"); + registerButton.id = "register-button"; + registerButton.className = "auth-button"; + registerButton.textContent = "Зарегистрироваться"; + + const backButton = document.createElement("button"); + backButton.id = "back-to-login"; + backButton.className = "auth-button"; + backButton.textContent = "Назад"; + + buttonsDiv.appendChild(registerButton); + buttonsDiv.appendChild(backButton); + registerContainer.appendChild(buttonsDiv); + + const errorElement = document.createElement("p"); + errorElement.id = "register-error"; + errorElement.className = "error-message"; + registerContainer.appendChild(errorElement); + + container.appendChild(registerContainer); + + const handleRegister = async () => { + const name = nameInput.value.trim(); + const login = loginInput.value.trim(); + const password = passwordInput.value; + + if (!name || !login || !password) { + errorElement.textContent = "Заполните все поля"; + return; + } + + if (name.length < 2) { + errorElement.textContent = "Имя должно быть не короче 2 символов"; + return; + } + + if (password.length < 6) { + errorElement.textContent = "Пароль должен быть не короче 6 символов"; + return; + } + + try { + const userData = await registration(name, login, password); + if (userData && userData.user) { + setCurrentUser(userData.user); + await init(); + } + } catch (error) { + errorElement.textContent = error.message; + } + }; + + registerButton.addEventListener("click", handleRegister); + backButton.addEventListener("click", (e) => { + e.preventDefault(); + renderLoginForm(); + }); +} \ No newline at end of file diff --git a/js/sanitize.js b/js/sanitize.js deleted file mode 100644 index 299677099e..0000000000 --- a/js/sanitize.js +++ /dev/null @@ -1,9 +0,0 @@ -export function sanitize(text) { - return text - .replaceAll("&", "&") - .replaceAll("<", "<") - .replaceAll(">", ">") - .replaceAll('"', """) - .replaceAll("'", "'"); - } - \ No newline at end of file diff --git a/js/utils.js b/js/utils.js index 6fea44db0b..a94cf1eb27 100644 --- a/js/utils.js +++ b/js/utils.js @@ -1,4 +1,20 @@ -export function formatDate(date) { - return new Date(date).toLocaleString("ru-RU"); - } - \ No newline at end of file +export function sanitize(text) { + if (!text) return ""; + return text + .replaceAll("&", "&") + .replaceAll("<", "<") + .replaceAll(">", ">") + .replaceAll('"', """) + .replaceAll("'", "'"); +} + +export function formatDate(dateString) { + const date = new Date(dateString); + return date.toLocaleString("ru-RU", { + day: "numeric", + month: "numeric", + year: "numeric", + hour: "2-digit", + minute: "2-digit", + }); +} \ No newline at end of file diff --git a/styles.css b/styles.css index e35e866d25..3e3afc0d1b 100644 --- a/styles.css +++ b/styles.css @@ -209,3 +209,63 @@ body { border-radius: 18px; cursor: pointer; } + + +.auth-container { + width: 596px; + background: radial-gradient( + 75.42% 75.42% at 50% 42.37%, + rgba(53, 53, 53, 0) 22.92%, + #7334ea 100% + ); + border-radius: 20px; + padding: 48px; + display: flex; + flex-direction: column; + gap: 16px; +} + +.auth-title { + margin: 0 0 16px 0; + text-align: center; +} + +.auth-input { + font-size: 16px; + font-family: Helvetica; + border-radius: 8px; + border: none; + padding: 11px 22px; +} + +.auth-buttons { + display: flex; + gap: 16px; + justify-content: center; + margin-top: 16px; +} + +.auth-button { + font-size: 18px; + padding: 10px 20px; + background-color: #bcec30; + border: none; + border-radius: 18px; + cursor: pointer; +} + +.auth-button:hover { + opacity: 0.9; +} + +.error-message { + color: #ff6b6b; + text-align: center; + margin: 8px 0 0 0; +} + +#loading-message, +#comment-loading-message { + text-align: center; + color: #bcec30; +} \ No newline at end of file