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
65 changes: 64 additions & 1 deletion 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 Down Expand Up @@ -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 }) {
Expand All @@ -67,3 +86,47 @@ 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();
});
}

export function likePost(id, token) {
return fetch(postsHost+'/'+id+'/like', {
method: "POST",
headers: {
Authorization: token,
},

}).then((response) => {
if (response.status === 401) {
throw new Error("Вы не авторизованы");
}
return response.json();
});
}

export function dislikePost(id, token) {
return fetch(postsHost+'/'+id+'/dislike', {
method: "POST",
headers: {
Authorization: token,
},

}).then((response) => {
if (response.status === 401) {
throw new Error("Вы не авторизованы");
}
return response.json();
});
}
43 changes: 39 additions & 4 deletions components/add-post-page-component.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,55 @@
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 = `
<div class="page-container">
<div class="header-container"></div>
Cтраница добавления поста
<button class="button" id="add-button">Добавить</button>
<div class="form">
<h3 class="form-title">Добавить пост</h3>
<div class="form-inputs">
<div class="upload-image-container">
</div>
</div>
<label style="margin-top:10px;">
Опишите фотографию:
<textarea class="input textarea" rows="4"></textarea>
</label>
<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: uploadImageContainer,
onImageUrlChange(newImageUrl) {
imageUrl = newImageUrl;
},
});
}
const textArea = document.querySelector(".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,
});
});
};
Expand Down
101 changes: 28 additions & 73 deletions components/posts-page-component.js
Original file line number Diff line number Diff line change
@@ -1,99 +1,52 @@
import { USER_POSTS_PAGE } from "../routes.js";
import { renderHeaderComponent } from "./header-component.js";
import { posts, goToPage } from "../index.js";
import { handleLikes } from "../handleLikes.js";


export function renderPostsPageComponent({ appEl }) {
// @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>
const postsHtml = posts.map(
(p) => ` <li class="post">
<div class="post-header" data-user-id="${p.user.id}">
<img src="${p.user.imageUrl}" class="post-header__user-image">
<p class="post-header__user-name">${p.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">
<img class="post-image" src="${p.imageUrl}">
</div>
<div class="post-likes">
<button data-post-id="642cffed9b190443860c2f30" class="like-button">
<img src="./assets/images/like-not-active.svg">
<button data-liked="${p.isLiked}" data-post-id="${p.id}" class="like-button">
<img src="./assets/images/like${p.isLiked ? '' : '-not'}-active.svg">
</button>
<p class="post-likes-text">
Нравится: <strong>35</strong>
Нравится: <strong>${p.likes.length}</strong>
</p>
</div>
<p class="post-text">
<span class="user-name">Варварва Н.</span>
Нарисовала картину, посмотрите какая красивая
<span class="user-name">${p.user.name}</span>
${p.description}
</p>
<p class="post-date">
3 часа назад
${new Date(p.createdAt).toLocaleDateString()}
</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>
</li>`
).join('');
/**
* @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">
${postsHtml}
</ul>
</div>`;

appEl.innerHTML = appHtml;
handleLikes()

renderHeaderComponent({
element: document.querySelector(".header-container"),
Expand All @@ -107,3 +60,5 @@ export function renderPostsPageComponent({ appEl }) {
});
}
}

//создать еще одну страницу user-page-component чтобы выглядела как в эталоне
49 changes: 49 additions & 0 deletions components/user-page-component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
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) => ` <li class="post">
<div class="post-header" data-user-id="${p.user.id}">
<img src="${p.user.imageUrl}" class="post-header__user-image">
<p class="post-header__user-name">${p.user.name}</p>
</div>
<div class="post-image-container">
<img class="post-image" src="${p.imageUrl}">
</div>
<div class="post-likes">
<button data-liked="${p.isLiked}" data-post-id="${p.id}" class="like-button">
<img src="./assets/images/like${p.isLiked ? '' : '-not'}-active.svg">
</button>
<p class="post-likes-text">
Нравится: <strong>${p.likes.length}</strong>
</p>
</div>
<p class="post-text">
<span class="user-name">${p.user.name}</span>
${p.description}
</p>
<p class="post-date">
${new Date(p.createdAt).toLocaleDateString()}
</p>
</li>`
).join('');
/**
* @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">
${postsHtml}
</ul>
</div>`;

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

}
42 changes: 42 additions & 0 deletions handleLikes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { dislikePost, likePost } from "./api.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) => {
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()
});
}
});
}
}

Loading