From e0ed7657c0ac16bc4c2a6a901652f1d570954102 Mon Sep 17 00:00:00 2001 From: Saule Date: Mon, 22 Sep 2025 13:06:18 +0100 Subject: [PATCH 1/6] added like logics, add posts and integrated API --- api.js | 35 +++++++++- components/add-post-page-component.js | 33 ++++++++- components/posts-page-component.js | 98 +++++++-------------------- components/user-page-component.js | 47 +++++++++++++ handleLikes.js | 0 index.js | 41 +++++++---- 6 files changed, 165 insertions(+), 89 deletions(-) create mode 100644 components/user-page-component.js create mode 100644 handleLikes.js diff --git a/api.js b/api.js index 123a9e3b6..cc54d70c6 100644 --- a/api.js +++ b/api.js @@ -1,7 +1,7 @@ // Замени на свой, чтобы получить независимый от других набор данных. // "боевая" версия инстапро лежит в ключе prod const personalKey = "prod"; -const baseHost = "https://webdev-hw-api.vercel.app"; +const baseHost = "https://wedev-api.sky.pro"; const postsHost = `${baseHost}/api/v1/${personalKey}/instapro`; export function getPosts({ token }) { @@ -54,6 +54,25 @@ export function loginUser({ login, password }) { return response.json(); }); } +export function getUserPosts({ id, token }) { + return fetch(postsHost + "/user-posts/" + id, { + method: "GET", + headers: { + Authorization: token, + }, + }) + .then((response) => { + if (response.status === 401) { + throw new Error("Нет авторизации"); + } + + return response.json(); + }) + .then((data) => { + return data.posts; + }); + +} // Загружает картинку в облако, возвращает url загруженной картинки export function uploadImage({ file }) { @@ -67,3 +86,17 @@ export function uploadImage({ file }) { return response.json(); }); } +export function addPost({token, data }) { + return fetch(postsHost, { + method: "POST", + headers: { + Authorization: token, + }, + body: JSON.stringify(data), + }).then((response) => { + if (response.status === 400) { + throw new Error("Некорректные данные"); + } + return response.json(); + }); +} \ No newline at end of file diff --git a/components/add-post-page-component.js b/components/add-post-page-component.js index 8277f093b..fc068648e 100644 --- a/components/add-post-page-component.js +++ b/components/add-post-page-component.js @@ -1,20 +1,47 @@ +import { renderHeaderComponent } from "./header-component.js"; +import { renderUploadImageComponent } from "./upload-image-component.js"; export function renderAddPostPageComponent({ appEl, onAddPostClick }) { + let imageUrl = ""; const render = () => { // @TODO: Реализовать страницу добавления поста const appHtml = `
Cтраница добавления поста +
+ Опишите фотографию: +
`; appEl.innerHTML = appHtml; - + renderHeaderComponent({ + element: document.querySelector(".header-container"), + }); + const uploadImageContainer = appEl.querySelector(".upload-image-container"); + if (uploadImageContainer) { + renderUploadImageComponent({ + element: uploadImageContainer, + onImageUrlChange(newImageUrl) { + imageUrl = newImageUrl; + }, + }); + } + const textArea = document.querySelector(".add-post-textarea"); + document.getElementById("add-button").addEventListener("click", () => { + // if (imageUrl === "") { + // alert("Введите картинку"); + // return; + // } + // if (textArea.value === "") { + // alert("Введите описание"); + // return; + // } onAddPostClick({ - description: "Описание картинки", - imageUrl: "https://image.png", + description: textArea.value, + imageUrl, }); }); }; diff --git a/components/posts-page-component.js b/components/posts-page-component.js index 662ccdbdc..9a3b04356 100644 --- a/components/posts-page-component.js +++ b/components/posts-page-component.js @@ -5,91 +5,41 @@ import { posts, goToPage } from "../index.js"; export function renderPostsPageComponent({ appEl }) { // @TODO: реализовать рендер постов из api console.log("Актуальный список постов:", posts); - - /** - * @TODO: чтобы отформатировать дату создания поста в виде "19 минут назад" - * можно использовать https://date-fns.org/v2.29.3/docs/formatDistanceToNow - */ - const appHtml = ` -
-
-
`; appEl.innerHTML = appHtml; + handleLikes() renderHeaderComponent({ element: document.querySelector(".header-container"), diff --git a/components/user-page-component.js b/components/user-page-component.js index c75808ca2..66bc56b7a 100644 --- a/components/user-page-component.js +++ b/components/user-page-component.js @@ -1,5 +1,6 @@ import { renderHeaderComponent } from "./header-component.js"; import { posts } from "../index.js"; +import { handleLikes } from "../handleLikes.js"; export function renderUserPageComponent({ appEl }) { const postsHtml = posts.map( (p) => `
  • @@ -39,7 +40,8 @@ export function renderUserPageComponent({ appEl }) { `; - appEl.innerHTML = appHtml; + appEl.innerHTML = appHtml; + handleLikes() renderHeaderComponent({ element: document.querySelector(".header-container"), }); diff --git a/handleLikes.js b/handleLikes.js index e69de29bb..da85a1391 100644 --- a/handleLikes.js +++ b/handleLikes.js @@ -0,0 +1,41 @@ +import { dislikePost, likePost } from "./api.js"; +import { getToken, posts, renderApp, setPosts } from "./index.js"; + +export function handleLikes() { + const likeButtons = document.querySelectorAll(".like-button"); + console.log(likeButtons); + for (const likeButton of likeButtons) { + likeButton.addEventListener("click", () => { + const isLiked = likeButton.dataset.liked; + if (isLiked === "true") { + dislikePost(likeButton.dataset.postId, getToken()).then((data) => { + console.log(data); + const newPosts = posts.map((p) => { + if (p.id === likeButton.dataset.postId) { + return data.post + } else { + return p + } + }); + setPosts(newPosts) + renderApp() + }); + } else { + + likePost(likeButton.dataset.postId, getToken()).then((data) => { + console.log(data); + const newPosts = posts.map((p) => { + if (p.id === likeButton.dataset.postId) { + return data.post + } else { + return p + } + }); + setPosts(newPosts) + renderApp() + }); + } + }); + } +} + diff --git a/index.js b/index.js index 3cdd32d1e..ca2ae6e3b 100644 --- a/index.js +++ b/index.js @@ -28,7 +28,7 @@ export const setUser = (newUser) => { user = newUser } -const getToken = () => { +export const getToken = () => { const token = user ? `Bearer ${user.token}` : undefined; return token; }; @@ -99,7 +99,7 @@ export const goToPage = (newPage, data) => { throw new Error("страницы не существует"); }; -const renderApp = () => { +export const renderApp = () => { const appEl = document.getElementById("app"); if (page === LOADING_PAGE) { return renderLoadingPageComponent({ From e7220e604fb219d17de3b259c926931433e79cde Mon Sep 17 00:00:00 2001 From: Saule Date: Mon, 29 Sep 2025 13:19:48 +0100 Subject: [PATCH 3/6] add validation to send posts --- components/add-post-page-component.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/components/add-post-page-component.js b/components/add-post-page-component.js index fc068648e..3c57d9515 100644 --- a/components/add-post-page-component.js +++ b/components/add-post-page-component.js @@ -31,14 +31,14 @@ export function renderAddPostPageComponent({ appEl, onAddPostClick }) { const textArea = document.querySelector(".add-post-textarea"); document.getElementById("add-button").addEventListener("click", () => { - // if (imageUrl === "") { - // alert("Введите картинку"); - // return; - // } - // if (textArea.value === "") { - // alert("Введите описание"); - // return; - // } + if (imageUrl === "") { + alert("Введите картинку"); + return; + } + if (textArea.value === "") { + alert("Введите описание"); + return; + } onAddPostClick({ description: textArea.value, imageUrl, From 8c26ff68bd861ce43f7aaf9d67ccb55394dbf87f Mon Sep 17 00:00:00 2001 From: Saule Date: Mon, 29 Sep 2025 13:32:45 +0100 Subject: [PATCH 4/6] completed course-work --- components/add-post-page-component.js | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/components/add-post-page-component.js b/components/add-post-page-component.js index 3c57d9515..a81983e58 100644 --- a/components/add-post-page-component.js +++ b/components/add-post-page-component.js @@ -7,11 +7,19 @@ export function renderAddPostPageComponent({ appEl, onAddPostClick }) { const appHtml = `
    - Cтраница добавления поста -
    - Опишите фотографию: - - +
    +

    Добавить пост

    +
    +
    +
    +
    + + +
    +
    `; @@ -29,7 +37,7 @@ export function renderAddPostPageComponent({ appEl, onAddPostClick }) { }); } const textArea = document.querySelector(".add-post-textarea"); - + document.getElementById("add-button").addEventListener("click", () => { if (imageUrl === "") { alert("Введите картинку"); From 148b3370c47c1831f99a54eb24c59f8806158183 Mon Sep 17 00:00:00 2001 From: Saule Date: Mon, 6 Oct 2025 12:36:18 +0100 Subject: [PATCH 5/6] fixed the error --- components/add-post-page-component.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/add-post-page-component.js b/components/add-post-page-component.js index a81983e58..cf2d675f4 100644 --- a/components/add-post-page-component.js +++ b/components/add-post-page-component.js @@ -36,7 +36,7 @@ export function renderAddPostPageComponent({ appEl, onAddPostClick }) { }, }); } - const textArea = document.querySelector(".add-post-textarea"); + const textArea = document.querySelector(".textarea"); document.getElementById("add-button").addEventListener("click", () => { if (imageUrl === "") { From a137ab29f297c0c24940fb0aedad822774e10d15 Mon Sep 17 00:00:00 2001 From: Saule Date: Mon, 6 Oct 2025 12:48:16 +0100 Subject: [PATCH 6/6] fixed the likes with no signing in --- handleLikes.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/handleLikes.js b/handleLikes.js index da85a1391..d579e3c40 100644 --- a/handleLikes.js +++ b/handleLikes.js @@ -1,11 +1,12 @@ import { dislikePost, likePost } from "./api.js"; -import { getToken, posts, renderApp, setPosts } from "./index.js"; +import { getToken, posts, renderApp, setPosts, user } from "./index.js"; export function handleLikes() { const likeButtons = document.querySelectorAll(".like-button"); console.log(likeButtons); for (const likeButton of likeButtons) { likeButton.addEventListener("click", () => { + if (!user) return alert("Авторизуйтесь, чтобы лайкать посты") const isLiked = likeButton.dataset.liked; if (isLiked === "true") { dislikePost(likeButton.dataset.postId, getToken()).then((data) => {