Skip to content
Open
114 changes: 101 additions & 13 deletions api.js
Original file line number Diff line number Diff line change
@@ -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 }) {
Expand All @@ -19,6 +19,7 @@ export function getPosts({ token }) {
return response.json();
})
.then((data) => {
console.log(data.posts);
return data.posts;
});
}
Expand All @@ -33,12 +34,18 @@ export function registerUser({ login, password, name, imageUrl }) {
name,
imageUrl,
}),
}).then((response) => {
if (response.status === 400) {
throw new Error("Такой пользователь уже существует");
}
return response.json();
});
})
.then((response) => {
if (response.status === 400) {
throw new Error("Такой пользователь уже существует");
}
return response.json();
})
.catch((error) => {
if (error.message === "Такой пользователь уже существует") {
alert("Такой пользователь уже существует");
} else alert("Кажется, у вас сломался интернет, попробуйте позже");
});
}

export function loginUser({ login, password }) {
Expand All @@ -48,12 +55,18 @@ export function loginUser({ login, password }) {
login,
password,
}),
}).then((response) => {
if (response.status === 400) {
throw new Error("Неверный логин или пароль");
}
return response.json();
});
})
.then((response) => {
if (response.status === 400) {
throw new Error("Неверный логин или пароль");
}
return response.json();
})
.catch((error) => {
if (error.message === "Неверный логин или пароль") {
alert("Неверный логин или пароль");
} else alert("Кажется, у вас сломался интернет, попробуйте позже");
});
}

// Загружает картинку в облако, возвращает url загруженной картинки
Expand All @@ -68,3 +81,78 @@ export function uploadImage({ file }) {
return response.json();
});
}

export function addPost({ token, description, imageUrl }) {
return fetch(postsHost, {
method: "POST",
body: JSON.stringify({
description,
imageUrl,
}),
headers: {
Authorization: token,
},
});
}

export function getPostsUser({ id }) {
return fetch(postsHost + "/user-posts/" + id, {
method: "GET",
})
.then((response) => {
if (response.status === 401) {
throw new Error("Нет авторизации");
}
return response.json();
})
.then((data) => {
console.log(data.posts);
return data.posts;
})
.catch((error) => {
if (error.message === "Нет авторизации") {
alert("Нет авторизации");
} else alert("Кажется, у вас сломался интернет, попробуйте позже");
});
}

export function likePost(token, id) {
return fetch(postsHost + `/${id}/like`, {
method: "POST",
headers: {
Authorization: token,
},
})
.then((response) => {
if (response.status === 401) {
throw new Error("Нет авторизации");
}

return response.json();
})
.catch((error) => {
if (error.message === "Нет авторизации") {
alert("Нет авторизации");
} else alert("Кажется, у вас сломался интернет, попробуйте позже");
});
}
export function disLikePost(token, id) {
return fetch(postsHost + `/${id}/dislike`, {
method: "POST",
headers: {
Authorization: token,
},
})
.then((response) => {
if (response.status === 401) {
throw new Error("Нет авторизации");
}

return response.json();
})
.catch((error) => {
if (error.message === "Нет авторизации") {
alert("Нет авторизации");
} else alert("Кажется, у вас сломался интернет, попробуйте позже");
});
}
45 changes: 39 additions & 6 deletions components/add-post-page-component.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,53 @@
import { renderHeaderComponent } from "./header-component.js";
import { renderUploadImageComponent } from "./upload-image-component.js";
export function renderAddPostPageComponent({ appEl, onAddPostClick }) {
const render = () => {
let imageUrl = "";

// TODO: Реализовать страницу добавления поста
const appHtml = `
<div class="page-container">
<div class="header-container"></div>
Cтраница добавления поста
<button class="button" id="add-button">Добавить</button>
</div>
<div class="header-container"></div>
<div class="form">
<h3 class="form-title">
Добавить пост
</h3>
<div class="form-inputs">
<div class="upload-image-container"></div>



<textarea id="description" class="input textarea" placeholder="Опишите фотографию"></textarea>

<div class="form-error"></div>

<button class="button" id="add-button">Добавить</button>
</div>
</div>
</div>

`;

appEl.innerHTML = appHtml;
renderHeaderComponent({
element: document.querySelector(".header-container"),
});
const uploadImageContainer = appEl.querySelector(".upload-image-container");

if (uploadImageContainer) {
renderUploadImageComponent({
element: appEl.querySelector(".upload-image-container"),
onImageUrlChange(newImageUrl) {
imageUrl = newImageUrl;
},
});
}
const descriptionElement = document.getElementById("description");

document.getElementById("add-button").addEventListener("click", () => {
onAddPostClick({
description: "Описание картинки",
imageUrl: "https://image.png",
description: descriptionElement.value,
imageUrl: imageUrl,
});
});
};
Expand Down
152 changes: 68 additions & 84 deletions components/posts-page-component.js
Original file line number Diff line number Diff line change
@@ -1,97 +1,64 @@
import { USER_POSTS_PAGE } from "../routes.js";
import { renderHeaderComponent } from "./header-component.js";
import { posts, goToPage } from "../index.js";
import { sanitizeHtml } from "../helpers.js";
import { formatDistanceToNow } from "date-fns";
import { ru } from "date-fns/locale";
import { likePost, disLikePost } from "../api.js";

export function renderPostsPageComponent({ appEl }) {
export function renderPostsPageComponent({ appEl, token }) {
// TODO: реализовать рендер постов из api
console.log("Актуальный список постов:", posts);

/**
* TODO: чтобы отформатировать дату создания поста в виде "19 минут назад"
* можно использовать https://date-fns.org/v2.29.3/docs/formatDistanceToNow
*/
const appHtml = `
<div class="page-container">
<div class="header-container"></div>
<ul class="posts">
<li class="post">
<div class="post-header" data-user-id="642d00329b190443860c2f31">
<img src="https://www.imgonline.com.ua/examples/bee-on-daisy.jpg" class="post-header__user-image">
<p class="post-header__user-name">Иван Иваныч</p>
</div>
<div class="post-image-container">
<img class="post-image" src="https://www.imgonline.com.ua/examples/bee-on-daisy.jpg">
</div>
<div class="post-likes">
<button data-post-id="642d00579b190443860c2f32" class="like-button">
<img src="./assets/images/like-active.svg">
</button>
<p class="post-likes-text">
Нравится: <strong>2</strong>
</p>
</div>
<p class="post-text">
<span class="user-name">Иван Иваныч</span>
Ромашка, ромашка...
</p>
<p class="post-date">
19 минут назад
</p>
</li>
<li class="post">
<div class="post-header" data-user-id="6425602ce156b600f7858df2">
<img src="https://storage.yandexcloud.net/skypro-webdev-homework-bucket/1680601502867-%25C3%2590%25C2%25A1%25C3%2590%25C2%25BD%25C3%2590%25C2%25B8%25C3%2590%25C2%25BC%25C3%2590%25C2%25BE%25C3%2590%25C2%25BA%2520%25C3%2591%25C2%258D%25C3%2590%25C2%25BA%25C3%2591%25C2%2580%25C3%2590%25C2%25B0%25C3%2590%25C2%25BD%25C3%2590%25C2%25B0%25202023-04-04%2520%25C3%2590%25C2%25B2%252014.04.29.png" class="post-header__user-image">
<p class="post-header__user-name">Варварва Н.</p>
</div>


<div class="post-image-container">
<img class="post-image" src="https://storage.yandexcloud.net/skypro-webdev-homework-bucket/1680670675451-%25C3%2590%25C2%25A1%25C3%2590%25C2%25BD%25C3%2590%25C2%25B8%25C3%2590%25C2%25BC%25C3%2590%25C2%25BE%25C3%2590%25C2%25BA%2520%25C3%2591%25C2%258D%25C3%2590%25C2%25BA%25C3%2591%25C2%2580%25C3%2590%25C2%25B0%25C3%2590%25C2%25BD%25C3%2590%25C2%25B0%25202023-03-31%2520%25C3%2590%25C2%25B2%252012.51.20.png">
</div>
<div class="post-likes">
<button data-post-id="642cffed9b190443860c2f30" class="like-button">
<img src="./assets/images/like-not-active.svg">
</button>
<p class="post-likes-text">
Нравится: <strong>35</strong>
</p>
</div>
<p class="post-text">
<span class="user-name">Варварва Н.</span>
Нарисовала картину, посмотрите какая красивая
</p>
<p class="post-date">
3 часа назад
</p>
</li>
<li class="post">
<div class="post-header" data-user-id="6425602ce156b600f7858df2">
<img src="https://storage.yandexcloud.net/skypro-webdev-homework-bucket/1680601502867-%25C3%2590%25C2%25A1%25C3%2590%25C2%25BD%25C3%2590%25C2%25B8%25C3%2590%25C2%25BC%25C3%2590%25C2%25BE%25C3%2590%25C2%25BA%2520%25C3%2591%25C2%258D%25C3%2590%25C2%25BA%25C3%2591%25C2%2580%25C3%2590%25C2%25B0%25C3%2590%25C2%25BD%25C3%2590%25C2%25B0%25202023-04-04%2520%25C3%2590%25C2%25B2%252014.04.29.png" class="post-header__user-image">
<p class="post-header__user-name">Варварва Н.</p>
</div>


<div class="post-image-container">
<img class="post-image" src="https://leonardo.osnova.io/97a160ca-76b6-5cba-87c6-84ef29136bb3/">
</div>
<div class="post-likes">
<button data-post-id="642cf82e9b190443860c2f2b" class="like-button">
<img src="./assets/images/like-not-active.svg">
</button>
<p class="post-likes-text">
Нравится: <strong>0</strong>
</p>
</div>
<p class="post-text">
<span class="user-name">Варварва Н.</span>
Голова
</p>
<p class="post-date">
8 дней назад
</p>
</li>
</ul>
</div>`;

const appHtml = posts.map((comment) => {
return `<div class="page-container">
<div class="header-container"></div>
<ul class="posts">
<li class="post">
<div class="post-header" data-user-id="${comment.user.id}">
<img src="${
comment.user.imageUrl
}" class="post-header__user-image">
<p class="post-header__user-name">${comment.user.name}</p>
</div>
<div class="post-image-container">
<img class="post-image" src="${comment.imageUrl}">
</div>
<div class="post-likes">
<button data-postid="${comment.id}" class="like-button">
<img id="img-like" src="${
comment.isLiked
? "../assets/images/like-active.svg"
: "../assets/images/like-not-active.svg"
}">

</button>
<p class="post-likes-text">
Нравится: <strong>${
comment.likes && comment.likes.length > 0
? comment.likes
.map((name) => sanitizeHtml(name.name))
.join(", ")
: 0
}</strong>
</p>
</div>
<p class="post-text">
<span class="user-name">${comment.user.name}</span>
${sanitizeHtml(comment.description)}
</p>
<p class="post-date">
${formatDistanceToNow(comment.createdAt, new Date(), {
locale: ru,
})}
</p>
</li>
</div>`;
});

appEl.innerHTML = appHtml;

Expand All @@ -106,4 +73,21 @@ export function renderPostsPageComponent({ appEl }) {
});
});
}

for (let likeButton of document.querySelectorAll(".like-button")) {
likeButton.addEventListener("click", async () => {
const likeImage = likeButton.querySelector("img");
let commentID = likeButton.dataset.postid;

if (likeImage.src.includes("like-active")) {
// Dislike post
await disLikePost(token, commentID);
likeImage.src = "../assets/images/like-not-active.svg";
} else {
// Like post
await likePost(token, commentID);
likeImage.src = "../assets/images/like-active.svg";
}
});
}
}
Loading