Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 1 addition & 40 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,7 @@
</head>
<body>
<div class="container">
<p id="loading-message">Загрузка комментариев...</p>

<ul class="comments" id="comments-list"></ul>

<div class="add-form" id="add-form" style="display: none;">
<input type="text" class="add-form-name" id="name-input" placeholder="Введите ваше имя" readonly />
<textarea class="add-form-text" id="comment-input" placeholder="Введите ваш комментарий" rows="4"></textarea>
<div class="add-form-row">
<button class="add-form-button" id="add-comment-button">Написать</button>
</div>
</div>

<p id="comment-loading-message" style="display: none;">Комментарий добавляется...</p>

<p id="auth-message" style="display: none;">
Чтобы добавить комментарий, <a href="#" id="auth-link">авторизуйтесь</a>.
</p>

<div class="auth-container" id="login-container" style="display: none;">
<h2 class="auth-title">Авторизация</h2>
<input type="text" class="auth-input" id="login-input" placeholder="Введите логин" />
<input type="password" class="auth-input" id="password-input" placeholder="Введите пароль" />
<div class="auth-buttons">
<button class="auth-button" id="login-button">Войти</button>
<button class="auth-button" id="register-link">Регистрация</button>
</div>
<p id="auth-error" class="error-message"></p>
</div>

<div class="auth-container" id="register-container" style="display: none;">
<h2 class="auth-title">Регистрация</h2>
<input type="text" class="auth-input" id="register-name" placeholder="Введите имя" />
<input type="text" class="auth-input" id="register-login" placeholder="Введите логин" />
<input type="password" class="auth-input" id="register-password" placeholder="Введите пароль" />
<div class="auth-buttons">
<button class="auth-button" id="register-button">Зарегистрироваться</button>
<button class="auth-button" id="back-to-login">Назад</button>
</div>
<p id="auth-error" class="error-message"></p>
</div>

</div>

<script type="module" src="./js/main.js"></script>
Expand Down
117 changes: 102 additions & 15 deletions js/api.js
Original file line number Diff line number Diff line change
@@ -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 AUTH_URL = "https://wedev-api.sky.pro/api/v2/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;
}
}

Expand All @@ -30,31 +68,80 @@ 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(`${AUTH_URL}/login`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ login, password }),
});

await checkResponse(response);

if (!response.ok) {
const error = await response.json();
throw new Error(error.error || "Ошибка авторизации");
}

return response.json();
}

export async function registration(name, login, password) {
return fetch(AUTH_URL, {
const response = await fetch(AUTH_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name, login, password }),
});

await checkResponse(response);

if (!response.ok) {
const error = await response.json();
throw new Error(error.error || "Ошибка регистрации");
}

return response.json();
}
36 changes: 27 additions & 9 deletions js/auth.js
Original file line number Diff line number Diff line change
@@ -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");
}
53 changes: 35 additions & 18 deletions js/comments.js
Original file line number Diff line number Diff line change
@@ -1,58 +1,75 @@
import { fetchComments, postComment } from "./api.js";
import { fetchComments, postComment, toggleLike } from "./api.js";
import { renderComments } from "./render.js";
import { getCurrentUser } from "./auth.js";

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";
}
}

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("Ошибка при установке лайка");
}
}
Loading