diff --git a/api.js b/api.js index 123a9e3b6..5733fc2f5 100644 --- a/api.js +++ b/api.js @@ -4,6 +4,24 @@ const personalKey = "prod"; const baseHost = "https://webdev-hw-api.vercel.app"; const postsHost = `${baseHost}/api/v1/${personalKey}/instapro`; +export async function addNewPost({ token, description, imageUrl }) { + return fetch(postsHost, { + method: "POST", + headers: { + Authorization: token, + }, + body: JSON.stringify({ + description, + imageUrl, + }), + }).then((response) => { + if (response.status === 400) { + throw new Error("Не удалось добавить пост"); + } + return response.json(); + }); +} + export function getPosts({ token }) { return fetch(postsHost, { method: "GET", @@ -23,7 +41,7 @@ export function getPosts({ token }) { }); } -export function registerUser({ login, password, name, imageUrl }) { +export async function registerUser({ login, password, name, imageUrl }) { return fetch(baseHost + "/api/user", { method: "POST", body: JSON.stringify({ @@ -67,3 +85,50 @@ export function uploadImage({ file }) { return response.json(); }); } + +export async function getUserPosts({ token, id }) { + const response = await fetch(postsHost + "/user-posts/" + id, { + method: "GET", + headers: { + Authorization: token, + }, + }); + if (!response.ok) { + throw new Error("Ошибка запроса"); + } + return await response.json(); +} //Сетевой запрос постов пользователя + +export async function setLike({ token, id }) { + try { + const response = await fetch(postsHost + `/${id}/like`, { + method: "POST", + headers: { + Authorization: token, + }, + }); + if (!response.ok) { + throw new Error("сетевая ошибка"); + } + return await response.json(); + } catch (error) { + console.log(error); + } +} + +export async function unsetLike({ token, id }) { + try { + const response = await fetch(postsHost + `/${id}/dislike`, { + method: "POST", + headers: { + Authorization: token, + }, + }); + if (!response.ok) { + throw new Error("сетевая ошибка"); + } + return await response.json(); + } catch (error) { + console.log(error); + } +} diff --git a/components/add-post-page-component.js b/components/add-post-page-component.js index 8277f093b..2fdd02ecf 100644 --- a/components/add-post-page-component.js +++ b/components/add-post-page-component.js @@ -1,23 +1,47 @@ +import { renderHeaderComponent } from "./header-component.js"; +import { renderUploadImageComponent } from './upload-image-component.js' export function renderAddPostPageComponent({ appEl, onAddPostClick }) { + const render = () => { // @TODO: Реализовать страницу добавления поста - const appHtml = ` + let appHtml = `
-
- Cтраница добавления поста - -
+
+
+

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

+
+
+
+ + +
+
+ `; - + let imageUrl = ''; appEl.innerHTML = appHtml; - + renderHeaderComponent({element: document.querySelector('.header-container')}) + renderUploadImageComponent({element: document.querySelector('.upload-image-container'), + onImageUrlChange:(url)=> imageUrl = url}) + let textAreaElement = document.getElementById('post-description') + document.getElementById("add-button").addEventListener("click", () => { + if (!textAreaElement.value || !imageUrl){ + alert ('Заполните все поля') + return + } + onAddPostClick({ - description: "Описание картинки", - imageUrl: "https://image.png", + description: textAreaElement.value, + imageUrl: imageUrl, }); + }); }; render(); + } diff --git a/components/loading-page-component.js b/components/loading-page-component.js index c93522573..3baea5203 100644 --- a/components/loading-page-component.js +++ b/components/loading-page-component.js @@ -9,7 +9,7 @@ import { renderHeaderComponent } from "./header-component.js"; * @param {Object} params.user - Объект пользователя, содержащий данные о текущем авторизованном пользователе (если он есть). * @param {Function} params.goToPage - Функция для навигации по страницам. */ -export function renderLoadingPageComponent({ appEl, user, goToPage }) { +export function renderLoadingPageComponent({ appEl }) { /** * HTML-разметка страницы загрузки. * Содержит контейнер заголовка и индикатор загрузки. @@ -30,8 +30,6 @@ export function renderLoadingPageComponent({ appEl, user, goToPage }) { * Передаются данные пользователя и функция навигации. */ renderHeaderComponent({ - user, - element: document.querySelector(".header-container"), - goToPage, + element: document.querySelector(".header-container") }); } diff --git a/components/posts-page-component.js b/components/posts-page-component.js index 662ccdbdc..44c502be8 100644 --- a/components/posts-page-component.js +++ b/components/posts-page-component.js @@ -1,6 +1,10 @@ import { USER_POSTS_PAGE } from "../routes.js"; import { renderHeaderComponent } from "./header-component.js"; -import { posts, goToPage } from "../index.js"; +import { posts, goToPage, getToken } from "../index.js"; + +import { formatDistanceToNow } from "https://cdn.skypack.dev/date-fns"; +import { ru } from "https://cdn.skypack.dev/date-fns/locale"; +import { toggleLike } from "../helpers.js"; export function renderPostsPageComponent({ appEl }) { // @TODO: реализовать рендер постов из api @@ -14,84 +18,57 @@ export function renderPostsPageComponent({ appEl }) {
-
`; + ` + ) + .join("")} + + `; appEl.innerHTML = appHtml; @@ -106,4 +83,6 @@ export function renderPostsPageComponent({ appEl }) { }); }); } + toggleLike() } + diff --git a/components/user-post-page-component.js b/components/user-post-page-component.js new file mode 100644 index 000000000..c7e3d1180 --- /dev/null +++ b/components/user-post-page-component.js @@ -0,0 +1,74 @@ +import { posts } from "../index.js"; +import { formatDistanceToNow } from "https://cdn.skypack.dev/date-fns"; +import { ru } from "https://cdn.skypack.dev/date-fns/locale"; +import { renderHeaderComponent } from "./header-component.js"; +import { toggleLike } from "../helpers.js"; + +export function renderUserPostsPageComponent({ appEl }) { + let userPosts = posts.posts; + + console.log(userPosts); + const appHtml = + ` +
+
+ +
` + + appEl.innerHTML = appHtml; + renderHeaderComponent({ + element: document.querySelector(".header-container"), + } + ); + toggleLike(); +} diff --git a/helpers.js b/helpers.js index b47d3b777..95c52446c 100644 --- a/helpers.js +++ b/helpers.js @@ -1,15 +1,55 @@ +import { setLike, unsetLike } from "../api.js"; +import { posts, getToken } from "../index.js"; + export function saveUserToLocalStorage(user) { window.localStorage.setItem("user", JSON.stringify(user)); } -export function getUserFromLocalStorage(user) { +export function getUserFromLocalStorage() { try { return JSON.parse(window.localStorage.getItem("user")); } catch (error) { return null; } -} +}; export function removeUserFromLocalStorage(user) { window.localStorage.removeItem("user"); +}; + +export function toggleLike(){ + for (let buttonLike of document.querySelectorAll(".like-button")) { + buttonLike.addEventListener("click", async (event) => { + if (!getUserFromLocalStorage()){ + alert('Сначала авторизуйтесь') + return + } + const postId = event.target.dataset.postId; + const post = posts.find((post) => post.id === postId); + const postLikes = event.target.closest(".post-likes"); + const isLiked = !post.isLiked; + const likeImageElement = postLikes.querySelector("img"); + const postLikeTextElement = postLikes.querySelector(".post-likes-text"); + + likeImageElement.src = isLiked + ? "./assets/images/like-active.svg" + : "./assets/images/like-not-active.svg"; + let response; + if (post.isLiked) { + response = await unsetLike({ token: getToken(), id: postId }); + } else { + response = await setLike({ token: getToken(), id: postId }); + } + post.likes = response.post.likes; + post.isLiked = response.post.isLiked; + postLikeTextElement.innerHTML = ` Нравится: ${ + post.likes.length + ? post.likes.length > 1 + ? `${ post.likes[Math.floor(Math.random() * post.likes.length)].name } и еще ${post.likes.length - 1}` + : post.likes[0].name + : "0" + }`; + console.log(post.likes, post.isLiked,post); + }); + } } diff --git a/index.js b/index.js index 7f1817c75..60d4ccd48 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,4 @@ -import { getPosts } from "./api.js"; +import { getPosts, addNewPost, getUserPosts } from "./api.js"; import { renderAddPostPageComponent } from "./components/add-post-page-component.js"; import { renderAuthPageComponent } from "./components/auth-page-component.js"; import { @@ -15,12 +15,13 @@ import { removeUserFromLocalStorage, saveUserToLocalStorage, } from "./helpers.js"; +import { renderUserPostsPageComponent } from "./components/user-post-page-component.js"; export let user = getUserFromLocalStorage(); export let page = null; export let posts = []; -const getToken = () => { +export const getToken = () => { const token = user ? `Bearer ${user.token}` : undefined; return token; }; @@ -34,6 +35,13 @@ export const logout = () => { /** * Включает страницу приложения */ + +export const updatePosts = (newPosts) => { + posts = newPosts +} + + + export const goToPage = (newPage, data) => { if ( [ @@ -67,11 +75,20 @@ export const goToPage = (newPage, data) => { } if (newPage === USER_POSTS_PAGE) { + page = LOADING_PAGE; + renderApp(); // @@TODO: реализовать получение постов юзера из API console.log("Открываю страницу пользователя: ", data.userId); - page = USER_POSTS_PAGE; - posts = []; - return renderApp(); + return getUserPosts({token: getToken(),id: data.userId}) + .then ((userPosts)=>{ + posts = userPosts; + page = USER_POSTS_PAGE; + renderApp(); + } + ).catch((error)=>{ + console.log(error); + goToPage(POSTS_PAGE) + }) } page = newPage; @@ -110,11 +127,13 @@ const renderApp = () => { return renderAddPostPageComponent({ appEl, onAddPostClick({ description, imageUrl }) { + addNewPost({ token:getToken(), description, imageUrl}) // @TODO: реализовать добавление поста в API console.log("Добавляю пост...", { description, imageUrl }); goToPage(POSTS_PAGE); }, - }); + }) + } if (page === POSTS_PAGE) { @@ -125,8 +144,8 @@ const renderApp = () => { if (page === USER_POSTS_PAGE) { // @TODO: реализовать страницу с фотографиями отдельного пользвателя - appEl.innerHTML = "Здесь будет страница фотографий пользователя"; - return; + + return renderUserPostsPageComponent({appEl}); } };